From 65bb984c0e97dadaa1fd873e2d934dc2bd92d8fc Mon Sep 17 00:00:00 2001 From: Vasilis Remmas Date: Wed, 27 Dec 2023 12:41:10 +0100 Subject: [PATCH 01/61] Change behavior when deleting default config This commit changes the behavior of the webhook when deleting the default SriovNetworkNodePolicy and SriovOperatorConfig. This change is needed so that we can smoothly uninstall Helm releases that have the webhooks enabled. Without this change, when running `helm uninstall`, it fails because the webhook doesn't allow deletion of such resources mentioned above. Since these Webhook Configurations resources are deployed via the controller itself and not Helm, it's much more difficult to handle the lifecycle of them via Helm in the current state. Instead, it's easier to send a warning that these resources should not be deleted. Signed-off-by: Vasilis Remmas --- pkg/webhook/validate.go | 12 +++++------- pkg/webhook/validate_test.go | 16 +++++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/webhook/validate.go b/pkg/webhook/validate.go index 366881dc6..3e5606156 100644 --- a/pkg/webhook/validate.go +++ b/pkg/webhook/validate.go @@ -40,7 +40,7 @@ func validateSriovOperatorConfig(cr *sriovnetworkv1.SriovOperatorConfig, operati } if operation == v1.Delete { - return false, warnings, fmt.Errorf("default SriovOperatorConfig shouldn't be deleted") + warnings = append(warnings, "default SriovOperatorConfig shouldn't be deleted") } if cr.Spec.DisableDrain { @@ -97,12 +97,11 @@ func validateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePolicy, o if cr.GetName() == constants.DefaultPolicyName && cr.GetNamespace() == os.Getenv("NAMESPACE") { if operation == v1.Delete { - // reject deletion of default policy - return false, warnings, fmt.Errorf("default SriovNetworkNodePolicy shouldn't be deleted") - } else { - // skip validating default policy - return true, warnings, nil + warnings = append(warnings, "default SriovNetworkNodePolicy shouldn't be deleted") } + + // skip validating default policy + return true, warnings, nil } if cr.GetNamespace() != os.Getenv("NAMESPACE") { @@ -110,7 +109,6 @@ func validateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePolicy, o fmt.Sprintf(" is created or updated but not used. Only policy in %s namespace is respected.", os.Getenv("NAMESPACE"))) } - // DELETE should always succeed unless it's for the default object if operation == v1.Delete { return true, warnings, nil } diff --git a/pkg/webhook/validate_test.go b/pkg/webhook/validate_test.go index 990886906..6197ad660 100644 --- a/pkg/webhook/validate_test.go +++ b/pkg/webhook/validate_test.go @@ -156,15 +156,16 @@ func TestValidateSriovOperatorConfigWithDefaultOperatorConfig(t *testing.T) { config := newDefaultOperatorConfig() snclient = fakesnclientset.NewSimpleClientset() - ok, _, err := validateSriovOperatorConfig(config, "DELETE") - g.Expect(err).To(HaveOccurred()) - g.Expect(ok).To(Equal(false)) + ok, w, err := validateSriovOperatorConfig(config, "DELETE") + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(ok).To(Equal(true)) + g.Expect(w[0]).To(ContainSubstring("default SriovOperatorConfig shouldn't be deleted")) ok, _, err = validateSriovOperatorConfig(config, "UPDATE") g.Expect(err).NotTo(HaveOccurred()) g.Expect(ok).To(Equal(true)) - ok, w, err := validateSriovOperatorConfig(config, "UPDATE") + ok, w, err = validateSriovOperatorConfig(config, "UPDATE") g.Expect(err).NotTo(HaveOccurred()) g.Expect(ok).To(Equal(true)) g.Expect(w[0]).To(ContainSubstring("Node draining is disabled")) @@ -224,9 +225,10 @@ func TestValidateSriovNetworkNodePolicyWithDefaultPolicy(t *testing.T) { } os.Setenv("NAMESPACE", "openshift-sriov-network-operator") g := NewGomegaWithT(t) - ok, _, err = validateSriovNetworkNodePolicy(policy, "DELETE") - g.Expect(err).To(HaveOccurred()) - g.Expect(ok).To(Equal(false)) + ok, w, err := validateSriovNetworkNodePolicy(policy, "DELETE") + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(ok).To(Equal(true)) + g.Expect(w[0]).To(ContainSubstring("default SriovNetworkNodePolicy shouldn't be deleted")) ok, _, err = validateSriovNetworkNodePolicy(policy, "UPDATE") g.Expect(err).NotTo(HaveOccurred()) From 39d6aefc25b1a2eeeca432748d388d1c5b962857 Mon Sep 17 00:00:00 2001 From: Vasilis Remmas Date: Tue, 2 Jan 2024 10:30:48 +0100 Subject: [PATCH 02/61] Update chart README.md to reflect webhook changes Signed-off-by: Vasilis Remmas --- deployment/sriov-network-operator/README.md | 39 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/deployment/sriov-network-operator/README.md b/deployment/sriov-network-operator/README.md index f0cdeed30..c0fba2f69 100644 --- a/deployment/sriov-network-operator/README.md +++ b/deployment/sriov-network-operator/README.md @@ -64,10 +64,45 @@ We have introduced the following Chart parameters. | Name | Type | Default | description | | ---- | ---- | ------- | ----------- | +| `operator.tolerations` | list | `[{"key":"node-role.kubernetes.io/master","operator":"Exists","effect":"NoSchedule"},{"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"}]` | Operator's tolerations | +| `operator.nodeSelector` | object | {} | Operator's node selector | +| `operator.affinity` | object | `{"nodeAffinity":{"preferredDuringSchedulingIgnoredDuringExecution":[{"weight":1,"preference":{"matchExpressions":[{"key":"node-role.kubernetes.io/master","operator":"In","values":[""]}]}},{"weight":1,"preference":{"matchExpressions":[{"key":"node-role.kubernetes.io/control-plane","operator":"In","values":[""]}]}}]}}` | Operator's afffinity configuration | +| `operator.nameOverride` | string | `` | Operator's resource name override | +| `operator.fullnameOverride` | string | `` | Operator's resource full name override | | `operator.resourcePrefix` | string | `openshift.io` | Device plugin resource prefix | -| `operator.enableAdmissionController` | bool | `false` | Enable SR-IOV network resource injector and operator webhook | | `operator.cniBinPath` | string | `/opt/cni/bin` | Path for CNI binary | -| `operator.clusterType` | string | `kubernetes` | Cluster environment type | +| `operator.clustertype` | string | `kubernetes` | Cluster environment type | + +#### Admission Controllers parameters + +The admission controllers can be enabled by switching on a single parameter `operator.admissionControllers.enabled`. By +default, the user needs to pre-create Kubernetes Secrets that match the names provided in +`operator.admissionControllers.certificates.secretNames`. The secrets should have 3 fields populated with the relevant +content: +* `ca.crt` (value needs to be base64 encoded twice) +* `tls.crt` +* `tls.key` + +Aside from the aforementioned mode, the chart supports 3 more modes for certificate consumption by the admission +controllers, which can be found in the table below. In a nutshell, the modes that are supported are: +* Consume pre-created Certificates managed by cert-manager +* Generate self signed Certificates managed by cert-manager +* Specify the content of the certificates as Helm values + +| Name | Type | Default | description | +| ---- | ---- | ------- | ----------- | +| `operator.admissionControllers.enabled` | bool | false | Flag that switches on the admission controllers | +| `operator.admissionControllers.certificates.secretNames.operator` | string | `operator-webhook-cert` | Secret that stores the certificate for the Operator's admission controller | +| `operator.admissionControllers.certificates.secretNames.injector` | string | `network-resources-injector-cert` | Secret that stores the certificate for the Network Resources Injector's admission controller | +| `operator.admissionControllers.certificates.certManager.enabled` | bool | false | Flag that switches on consumption of certificates managed by cert-manager | +| `operator.admissionControllers.certificates.certManager.generateSelfSigned` | bool | false | Flag that switches on generation of self signed certificates managed by cert-manager. The secrets in which the certificates are stored will have the names provided in `operator.admissionControllers.certificates.secretNames` | +| `operator.admissionControllers.certificates.custom.enabled` | bool | false | Flag that switches on consumption of user provided certificates that are part of `operator.admissionControllers.certificates.custom.operator` and `operator.admissionControllers.certificates.custom.injector` objects | +| `operator.admissionControllers.certificates.custom.operator.caCrt` | string | `` | The CA certificate to be used by the Operator's admission controller | +| `operator.admissionControllers.certificates.custom.operator.tlsCrt` | string | `` | The public part of the certificate to be used by the Operator's admission controller | +| `operator.admissionControllers.certificates.custom.operator.tlsKey` | string | `` | The private part of the certificate to be used by the Operator's admission controller | +| `operator.admissionControllers.certificates.custom.injector.caCrt` | string | `` | The CA certificate to be used by the Network Resources Injector's admission controller | +| `operator.admissionControllers.certificates.custom.injector.tlsCrt` | string | `` | The public part of the certificate to be used by the Network Resources Injector's admission controller | +| `operator.admissionControllers.certificates.custom.injector.tlsKey` | string | `` | The private part of the certificate to be used by the Network Resources Injector's admission controller | ### Images parameters From 60a68d4a388dddf13e99451e4b5155082a3eb0e5 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 17:18:22 +0200 Subject: [PATCH 03/61] configure global variables and consts for the all system Signed-off-by: Sebastian Sch --- pkg/consts/constants.go | 81 +++++++++++++++++++++++++++++++++++++++- pkg/vars/vars.go | 82 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 pkg/vars/vars.go diff --git a/pkg/consts/constants.go b/pkg/consts/constants.go index 1f37edfa4..d56d36e7f 100644 --- a/pkg/consts/constants.go +++ b/pkg/consts/constants.go @@ -1,8 +1,19 @@ package consts -import "time" +import ( + "fmt" + "time" +) + +type DrainState string + +// PlatformTypes +type PlatformTypes int const ( + Chroot = "/host" + Host = "/host" + ResyncPeriod = 5 * time.Minute DefaultConfigName = "default" ConfigDaemonPath = "./bindata/manifests/daemon" @@ -33,4 +44,72 @@ const ( DeviceTypeNetDevice = "netdevice" VdpaTypeVirtio = "virtio" VdpaTypeVhost = "vhost" + + ClusterTypeOpenshift = "openshift" + ClusterTypeKubernetes = "kubernetes" + + SriovConfBasePath = "/etc/sriov-operator" + PfAppliedConfig = SriovConfBasePath + "/pci" + SriovSwitchDevConfPath = SriovConfBasePath + "/sriov_config.json" + SriovHostSwitchDevConfPath = Host + SriovSwitchDevConfPath + + DrainAnnotationState = "sriovnetwork.openshift.io/state" + DrainAnnotationStateRequired = "sriovnetwork.openshift.io/state-required" + DrainAnnotationTime = "sriovnetwork.openshift.io/state-time" + + DrainIdle DrainState = "Idle" + DrainDisabled DrainState = "Drain_Disabled" + DrainRequired DrainState = "Drain_Required" + RebootRequired DrainState = "Reboot_Required" + DrainMcpPausing DrainState = "Draining_MCP_Pausing" + DrainMcpPaused DrainState = "Draining_MCP_Paused" + Draining DrainState = "Draining" + DrainingComplete DrainState = "Draining_Complete" + RebootComplete DrainState = "Reboot_Complete" + + SyncStatusSucceeded = "Succeeded" + SyncStatusFailed = "Failed" + SyncStatusInProgress = "InProgress" + + MCPPauseAnnotationState = "sriovnetwork.openshift.io/state" + MCPPauseAnnotationTime = "sriovnetwork.openshift.io/time" + + CheckpointFileName = "sno-initial-node-state.json" + Unknown = "Unknown" + + SysBusPciDevices = "/sys/bus/pci/devices" + SysBusPciDrivers = "/sys/bus/pci/drivers" + SysBusPciDriversProbe = "/sys/bus/pci/drivers_probe" + SysClassNet = "/sys/class/net" + ProcKernelCmdLine = "/proc/cmdline" + NetClass = 0x02 + NumVfsFile = "sriov_numvfs" + + UdevFolder = "/etc/udev" + UdevRulesFolder = UdevFolder + "/rules.d" + HostUdevRulesFolder = Host + UdevRulesFolder + UdevDisableNM = "/bindata/scripts/udev-find-sriov-pf.sh" + NMUdevRule = "SUBSYSTEM==\"net\", ACTION==\"add|change|move\", ATTRS{device}==\"%s\", IMPORT{program}=\"/etc/udev/disable-nm-sriov.sh $env{INTERFACE} %s\"" + + KernelArgPciRealloc = "pci=realloc" + KernelArgIntelIommu = "intel_iommu=on" + KernelArgIommuPt = "iommu=pt" ) + +const ( + // Baremetal platform + Baremetal PlatformTypes = iota + // VirtualOpenStack platform + VirtualOpenStack +) + +func (e PlatformTypes) String() string { + switch e { + case Baremetal: + return "Baremetal" + case VirtualOpenStack: + return "Virtual/Openstack" + default: + return fmt.Sprintf("%d", int(e)) + } +} diff --git a/pkg/vars/vars.go b/pkg/vars/vars.go new file mode 100644 index 000000000..a34cab8af --- /dev/null +++ b/pkg/vars/vars.go @@ -0,0 +1,82 @@ +package vars + +import ( + "os" + "regexp" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" +) + +var ( + // ClusterType used by the operator to specify the platform it's running on + // supported values [kubernetes,openshift] + ClusterType string + + // DevMode controls the developer mode in the operator + // developer mode allows the operator to use un-supported network devices + DevMode bool + + // EnableAdmissionController allows the user to disable the operator webhooks + EnableAdmissionController bool + + // NodeName initialize and used by the config-daemon to identify the node it's running on + NodeName = "" + + // Destdir destination directory for the checkPoint file on the host + Destdir string + + // PlatformType specify the current platform the operator is running on + PlatformType = consts.Baremetal + // PlatformsMap contains supported platforms for virtual VF + PlatformsMap = map[string]consts.PlatformTypes{ + "openstack": consts.VirtualOpenStack, + } + + // SupportedVfIds list of supported virtual functions IDs + // loaded on daemon initialization by reading the supported-nics configmap + SupportedVfIds []string + + // DpdkDrivers supported DPDK drivers for virtual functions + DpdkDrivers = []string{"igb_uio", "vfio-pci", "uio_pci_generic"} + + // InChroot global variable to mark that the config-daemon code is inside chroot on the host file system + InChroot = false + + // UsingSystemdMode global variable to mark the config-daemon is running on systemd mode + UsingSystemdMode = false + + // FilesystemRoot used by test to mock interactions with filesystem + FilesystemRoot = "" + + //Cluster variables + Config *rest.Config = nil + Scheme *runtime.Scheme = nil + + // PfPhysPortNameRe regex to find switchdev devices on the host + PfPhysPortNameRe = regexp.MustCompile(`p\d+`) +) + +func init() { + ClusterType = os.Getenv("CLUSTER_TYPE") + + DevMode = false + mode := os.Getenv("DEV_MODE") + if mode == "TRUE" { + DevMode = true + } + + Destdir = "/host/tmp" + destdir := os.Getenv("DEST_DIR") + if destdir != "" { + Destdir = destdir + } + + EnableAdmissionController = false + enableAdmissionController := os.Getenv("ADMISSION_CONTROLLERS_ENABLED") + if enableAdmissionController == "True" { + EnableAdmissionController = true + } +} From 0dd496f85ed0d566d4a06b84391c81ae28ea2691 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 18:09:42 +0200 Subject: [PATCH 04/61] create a platform folder to contain different platforms like openstack and openshift add interfaces and mocks for better unit test Signed-off-by: Sebastian Sch --- pkg/platforms/mock/mock_platforms.go | 134 ++++++++++ .../openshift/mock/mock_openshift.go | 92 +++++++ .../openshift/openshift.go} | 48 ++-- .../openstack/mock/mock_openstack.go | 76 ++++++ .../openstack/openstack.go} | 234 ++++-------------- .../openstack/openstack_test.go} | 7 +- .../openstack}/testdata/meta_data.json | 0 .../openstack}/testdata/network_data.json | 0 pkg/platforms/platforms.go | 31 +++ 9 files changed, 417 insertions(+), 205 deletions(-) create mode 100644 pkg/platforms/mock/mock_platforms.go create mode 100644 pkg/platforms/openshift/mock/mock_openshift.go rename pkg/{utils/openshift_context.go => platforms/openshift/openshift.go} (50%) create mode 100644 pkg/platforms/openstack/mock/mock_openstack.go rename pkg/{utils/utils_virtual.go => platforms/openstack/openstack.go} (67%) rename pkg/{utils/utils_virtual_test.go => platforms/openstack/openstack_test.go} (95%) rename pkg/{utils => platforms/openstack}/testdata/meta_data.json (100%) rename pkg/{utils => platforms/openstack}/testdata/network_data.json (100%) create mode 100644 pkg/platforms/platforms.go diff --git a/pkg/platforms/mock/mock_platforms.go b/pkg/platforms/mock/mock_platforms.go new file mode 100644 index 000000000..40eb5dc4c --- /dev/null +++ b/pkg/platforms/mock/mock_platforms.go @@ -0,0 +1,134 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: platforms.go + +// Package mock_platforms is a generated GoMock package. +package mock_platforms + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + openshift "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" + versioned "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned" +) + +// MockInterface is a mock of Interface interface. +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface. +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance. +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// CreateOpenstackDevicesInfo mocks base method. +func (m *MockInterface) CreateOpenstackDevicesInfo() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOpenstackDevicesInfo") + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateOpenstackDevicesInfo indicates an expected call of CreateOpenstackDevicesInfo. +func (mr *MockInterfaceMockRecorder) CreateOpenstackDevicesInfo() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOpenstackDevicesInfo", reflect.TypeOf((*MockInterface)(nil).CreateOpenstackDevicesInfo)) +} + +// CreateOpenstackDevicesInfoFromNodeStatus mocks base method. +func (m *MockInterface) CreateOpenstackDevicesInfoFromNodeStatus(arg0 *v1.SriovNetworkNodeState) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CreateOpenstackDevicesInfoFromNodeStatus", arg0) +} + +// CreateOpenstackDevicesInfoFromNodeStatus indicates an expected call of CreateOpenstackDevicesInfoFromNodeStatus. +func (mr *MockInterfaceMockRecorder) CreateOpenstackDevicesInfoFromNodeStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOpenstackDevicesInfoFromNodeStatus", reflect.TypeOf((*MockInterface)(nil).CreateOpenstackDevicesInfoFromNodeStatus), arg0) +} + +// DiscoverSriovDevicesVirtual mocks base method. +func (m *MockInterface) DiscoverSriovDevicesVirtual() ([]v1.InterfaceExt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverSriovDevicesVirtual") + ret0, _ := ret[0].([]v1.InterfaceExt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DiscoverSriovDevicesVirtual indicates an expected call of DiscoverSriovDevicesVirtual. +func (mr *MockInterfaceMockRecorder) DiscoverSriovDevicesVirtual() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevicesVirtual", reflect.TypeOf((*MockInterface)(nil).DiscoverSriovDevicesVirtual)) +} + +// GetFlavor mocks base method. +func (m *MockInterface) GetFlavor() openshift.OpenshiftFlavor { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetFlavor") + ret0, _ := ret[0].(openshift.OpenshiftFlavor) + return ret0 +} + +// GetFlavor indicates an expected call of GetFlavor. +func (mr *MockInterfaceMockRecorder) GetFlavor() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlavor", reflect.TypeOf((*MockInterface)(nil).GetFlavor)) +} + +// GetMcClient mocks base method. +func (m *MockInterface) GetMcClient() versioned.Interface { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMcClient") + ret0, _ := ret[0].(versioned.Interface) + return ret0 +} + +// GetMcClient indicates an expected call of GetMcClient. +func (mr *MockInterfaceMockRecorder) GetMcClient() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMcClient", reflect.TypeOf((*MockInterface)(nil).GetMcClient)) +} + +// IsHypershift mocks base method. +func (m *MockInterface) IsHypershift() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsHypershift") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsHypershift indicates an expected call of IsHypershift. +func (mr *MockInterfaceMockRecorder) IsHypershift() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHypershift", reflect.TypeOf((*MockInterface)(nil).IsHypershift)) +} + +// IsOpenshiftCluster mocks base method. +func (m *MockInterface) IsOpenshiftCluster() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsOpenshiftCluster") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsOpenshiftCluster indicates an expected call of IsOpenshiftCluster. +func (mr *MockInterfaceMockRecorder) IsOpenshiftCluster() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsOpenshiftCluster", reflect.TypeOf((*MockInterface)(nil).IsOpenshiftCluster)) +} diff --git a/pkg/platforms/openshift/mock/mock_openshift.go b/pkg/platforms/openshift/mock/mock_openshift.go new file mode 100644 index 000000000..fb307a36e --- /dev/null +++ b/pkg/platforms/openshift/mock/mock_openshift.go @@ -0,0 +1,92 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: openshift.go + +// Package mock_openshift is a generated GoMock package. +package mock_openshift + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + openshift "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" + versioned "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned" +) + +// MockOpenshiftContextInterface is a mock of OpenshiftContextInterface interface. +type MockOpenshiftContextInterface struct { + ctrl *gomock.Controller + recorder *MockOpenshiftContextInterfaceMockRecorder +} + +// MockOpenshiftContextInterfaceMockRecorder is the mock recorder for MockOpenshiftContextInterface. +type MockOpenshiftContextInterfaceMockRecorder struct { + mock *MockOpenshiftContextInterface +} + +// NewMockOpenshiftContextInterface creates a new mock instance. +func NewMockOpenshiftContextInterface(ctrl *gomock.Controller) *MockOpenshiftContextInterface { + mock := &MockOpenshiftContextInterface{ctrl: ctrl} + mock.recorder = &MockOpenshiftContextInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockOpenshiftContextInterface) EXPECT() *MockOpenshiftContextInterfaceMockRecorder { + return m.recorder +} + +// GetFlavor mocks base method. +func (m *MockOpenshiftContextInterface) GetFlavor() openshift.OpenshiftFlavor { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetFlavor") + ret0, _ := ret[0].(openshift.OpenshiftFlavor) + return ret0 +} + +// GetFlavor indicates an expected call of GetFlavor. +func (mr *MockOpenshiftContextInterfaceMockRecorder) GetFlavor() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFlavor", reflect.TypeOf((*MockOpenshiftContextInterface)(nil).GetFlavor)) +} + +// GetMcClient mocks base method. +func (m *MockOpenshiftContextInterface) GetMcClient() versioned.Interface { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMcClient") + ret0, _ := ret[0].(versioned.Interface) + return ret0 +} + +// GetMcClient indicates an expected call of GetMcClient. +func (mr *MockOpenshiftContextInterfaceMockRecorder) GetMcClient() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMcClient", reflect.TypeOf((*MockOpenshiftContextInterface)(nil).GetMcClient)) +} + +// IsHypershift mocks base method. +func (m *MockOpenshiftContextInterface) IsHypershift() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsHypershift") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsHypershift indicates an expected call of IsHypershift. +func (mr *MockOpenshiftContextInterfaceMockRecorder) IsHypershift() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHypershift", reflect.TypeOf((*MockOpenshiftContextInterface)(nil).IsHypershift)) +} + +// IsOpenshiftCluster mocks base method. +func (m *MockOpenshiftContextInterface) IsOpenshiftCluster() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsOpenshiftCluster") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsOpenshiftCluster indicates an expected call of IsOpenshiftCluster. +func (mr *MockOpenshiftContextInterfaceMockRecorder) IsOpenshiftCluster() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsOpenshiftCluster", reflect.TypeOf((*MockOpenshiftContextInterface)(nil).IsOpenshiftCluster)) +} diff --git a/pkg/utils/openshift_context.go b/pkg/platforms/openshift/openshift.go similarity index 50% rename from pkg/utils/openshift_context.go rename to pkg/platforms/openshift/openshift.go index 44a5b5e41..7ba2b6e29 100644 --- a/pkg/utils/openshift_context.go +++ b/pkg/platforms/openshift/openshift.go @@ -1,10 +1,12 @@ -package utils +package openshift import ( mcclientset "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // OpenshiftFlavor holds metadata about the type of Openshift environment the operator is in. @@ -17,8 +19,16 @@ const ( OpenshiftFlavorDefault OpenshiftFlavor = "default" ) -// OpenshiftContext contains metadata and structs utilized to interact with Openshift clusters -type OpenshiftContext struct { +//go:generate ../../../bin/mockgen -destination mock/mock_openshift.go -source openshift.go +type OpenshiftContextInterface interface { + GetFlavor() OpenshiftFlavor + GetMcClient() mcclientset.Interface + IsOpenshiftCluster() bool + IsHypershift() bool +} + +// openshiftContext contains metadata and structs utilized to interact with Openshift clusters +type openshiftContext struct { // McClient is a client for MachineConfigs in an Openshift environment McClient mcclientset.Interface @@ -29,25 +39,25 @@ type OpenshiftContext struct { OpenshiftFlavor OpenshiftFlavor } -func NewOpenshiftContext(config *rest.Config, scheme *runtime.Scheme) (*OpenshiftContext, error) { - if ClusterType != ClusterTypeOpenshift { - return &OpenshiftContext{nil, false, ""}, nil +func New() (OpenshiftContextInterface, error) { + if vars.ClusterType != consts.ClusterTypeOpenshift { + return &openshiftContext{nil, false, ""}, nil } - mcclient, err := mcclientset.NewForConfig(config) + mcclient, err := mcclientset.NewForConfig(vars.Config) if err != nil { return nil, err } openshiftFlavor := OpenshiftFlavorDefault - infraClient, err := client.New(config, client.Options{ - Scheme: scheme, + infraClient, err := client.New(vars.Config, client.Options{ + Scheme: vars.Scheme, }) if err != nil { return nil, err } - isHypershift, err := IsExternalControlPlaneCluster(infraClient) + isHypershift, err := utils.IsExternalControlPlaneCluster(infraClient) if err != nil { return nil, err } @@ -56,13 +66,21 @@ func NewOpenshiftContext(config *rest.Config, scheme *runtime.Scheme) (*Openshif openshiftFlavor = OpenshiftFlavorHypershift } - return &OpenshiftContext{mcclient, true, openshiftFlavor}, nil + return &openshiftContext{mcclient, true, openshiftFlavor}, nil +} + +func (c *openshiftContext) GetFlavor() OpenshiftFlavor { + return c.OpenshiftFlavor +} + +func (c *openshiftContext) GetMcClient() mcclientset.Interface { + return c.McClient } -func (c OpenshiftContext) IsOpenshiftCluster() bool { +func (c openshiftContext) IsOpenshiftCluster() bool { return c.IsOpenShiftCluster } -func (c OpenshiftContext) IsHypershift() bool { +func (c openshiftContext) IsHypershift() bool { return c.OpenshiftFlavor == OpenshiftFlavorHypershift } diff --git a/pkg/platforms/openstack/mock/mock_openstack.go b/pkg/platforms/openstack/mock/mock_openstack.go new file mode 100644 index 000000000..9ef989297 --- /dev/null +++ b/pkg/platforms/openstack/mock/mock_openstack.go @@ -0,0 +1,76 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: openstack.go + +// Package mock_openstack is a generated GoMock package. +package mock_openstack + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" +) + +// MockOpenstackInterface is a mock of OpenstackInterface interface. +type MockOpenstackInterface struct { + ctrl *gomock.Controller + recorder *MockOpenstackInterfaceMockRecorder +} + +// MockOpenstackInterfaceMockRecorder is the mock recorder for MockOpenstackInterface. +type MockOpenstackInterfaceMockRecorder struct { + mock *MockOpenstackInterface +} + +// NewMockOpenstackInterface creates a new mock instance. +func NewMockOpenstackInterface(ctrl *gomock.Controller) *MockOpenstackInterface { + mock := &MockOpenstackInterface{ctrl: ctrl} + mock.recorder = &MockOpenstackInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockOpenstackInterface) EXPECT() *MockOpenstackInterfaceMockRecorder { + return m.recorder +} + +// CreateOpenstackDevicesInfo mocks base method. +func (m *MockOpenstackInterface) CreateOpenstackDevicesInfo() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOpenstackDevicesInfo") + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateOpenstackDevicesInfo indicates an expected call of CreateOpenstackDevicesInfo. +func (mr *MockOpenstackInterfaceMockRecorder) CreateOpenstackDevicesInfo() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOpenstackDevicesInfo", reflect.TypeOf((*MockOpenstackInterface)(nil).CreateOpenstackDevicesInfo)) +} + +// CreateOpenstackDevicesInfoFromNodeStatus mocks base method. +func (m *MockOpenstackInterface) CreateOpenstackDevicesInfoFromNodeStatus(arg0 *v1.SriovNetworkNodeState) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CreateOpenstackDevicesInfoFromNodeStatus", arg0) +} + +// CreateOpenstackDevicesInfoFromNodeStatus indicates an expected call of CreateOpenstackDevicesInfoFromNodeStatus. +func (mr *MockOpenstackInterfaceMockRecorder) CreateOpenstackDevicesInfoFromNodeStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOpenstackDevicesInfoFromNodeStatus", reflect.TypeOf((*MockOpenstackInterface)(nil).CreateOpenstackDevicesInfoFromNodeStatus), arg0) +} + +// DiscoverSriovDevicesVirtual mocks base method. +func (m *MockOpenstackInterface) DiscoverSriovDevicesVirtual() ([]v1.InterfaceExt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverSriovDevicesVirtual") + ret0, _ := ret[0].([]v1.InterfaceExt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DiscoverSriovDevicesVirtual indicates an expected call of DiscoverSriovDevicesVirtual. +func (mr *MockOpenstackInterfaceMockRecorder) DiscoverSriovDevicesVirtual() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevicesVirtual", reflect.TypeOf((*MockOpenstackInterface)(nil).DiscoverSriovDevicesVirtual)) +} diff --git a/pkg/utils/utils_virtual.go b/pkg/platforms/openstack/openstack.go similarity index 67% rename from pkg/utils/utils_virtual.go rename to pkg/platforms/openstack/openstack.go index a5e6ddc84..658995727 100644 --- a/pkg/utils/utils_virtual.go +++ b/pkg/platforms/openstack/openstack.go @@ -1,12 +1,10 @@ -package utils +package openstack import ( "encoding/json" - "errors" "fmt" "io" "os" - "path/filepath" "strconv" "strings" @@ -18,35 +16,8 @@ import ( dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" -) - -// PlatformType ... -type PlatformType int - -const ( - // Baremetal platform - Baremetal PlatformType = iota - // VirtualOpenStack ... - VirtualOpenStack -) - -func (e PlatformType) String() string { - switch e { - case Baremetal: - return "Baremetal" - case VirtualOpenStack: - return "Virtual/Openstack" - default: - return fmt.Sprintf("%d", int(e)) - } -} - -var ( - // PlatformMap contains supported platforms for virtual VF - PlatformMap = map[string]PlatformType{ - "openstack": VirtualOpenStack, - } + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" ) const ( @@ -64,6 +35,18 @@ var ( ospMetaDataFile = ospMetaDataDir + "/meta_data.json" ) +//go:generate ../../../bin/mockgen -destination mock/mock_openstack.go -source openstack.go +type OpenstackInterface interface { + CreateOpenstackDevicesInfo() error + CreateOpenstackDevicesInfoFromNodeStatus(*sriovnetworkv1.SriovNetworkNodeState) + DiscoverSriovDevicesVirtual() ([]sriovnetworkv1.InterfaceExt, error) +} + +type openstackContext struct { + hostManager host.HostManagerInterface + openStackDevicesInfo OSPDevicesInfo +} + // OSPMetaDataDevice -- Device structure within meta_data.json type OSPMetaDataDevice struct { Vlan int `json:"vlan,omitempty"` @@ -117,8 +100,12 @@ type OSPDeviceInfo struct { NetworkID string } +func New() OpenstackInterface { + return &openstackContext{} +} + // GetOpenstackData gets the metadata and network_data -func GetOpenstackData(useHostPath bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) { +func getOpenstackData(useHostPath bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) { metaData, networkData, err = getOpenstackDataFromConfigDrive(useHostPath) if err != nil { metaData, networkData, err = getOpenstackDataFromMetadataService() @@ -267,11 +254,19 @@ func getPCIAddressFromMACAddress(macAddress string, nics []*net.NIC) (string, er } // CreateOpenstackDevicesInfo create the openstack device info map -func CreateOpenstackDevicesInfo(metaData *OSPMetaData, networkData *OSPNetworkData) (OSPDevicesInfo, error) { +func (o *openstackContext) CreateOpenstackDevicesInfo() error { log.Log.Info("CreateOpenstackDevicesInfo()") devicesInfo := make(OSPDevicesInfo) + + metaData, networkData, err := getOpenstackData(true) + if err != nil { + log.Log.Error(err, "failed to read OpenStack data") + return err + } + if metaData == nil || networkData == nil { - return nil, nil + o.openStackDevicesInfo = make(OSPDevicesInfo) + return nil } // use this for hw pass throw interfaces @@ -291,12 +286,12 @@ func CreateOpenstackDevicesInfo(metaData *OSPMetaData, networkData *OSPNetworkDa // for vhostuser interface type we check the interfaces on the node pci, err := ghw.PCI() if err != nil { - return nil, fmt.Errorf("CreateOpenstackDevicesInfo(): error getting PCI info: %v", err) + return fmt.Errorf("CreateOpenstackDevicesInfo(): error getting PCI info: %v", err) } devices := pci.ListDevices() if len(devices) == 0 { - return nil, fmt.Errorf("CreateOpenstackDevicesInfo(): could not retrieve PCI devices") + return fmt.Errorf("CreateOpenstackDevicesInfo(): could not retrieve PCI devices") } for _, device := range devices { @@ -311,14 +306,14 @@ func CreateOpenstackDevicesInfo(metaData *OSPMetaData, networkData *OSPNetworkDa "device", device) continue } - if devClass != netClass { + if devClass != consts.NetClass { // Not network device continue } macAddress := "" - if name := tryToGetVirtualInterfaceName(device.Address); name != "" { - if mac := getNetDevMac(name); mac != "" { + if name := o.hostManager.TryToGetVirtualInterfaceName(device.Address); name != "" { + if mac := o.hostManager.GetNetDevMac(name); mac != "" { macAddress = mac } } @@ -339,11 +334,12 @@ func CreateOpenstackDevicesInfo(metaData *OSPMetaData, networkData *OSPNetworkDa } } - return devicesInfo, err + o.openStackDevicesInfo = devicesInfo + return nil } // DiscoverSriovDevicesVirtual discovers VFs on a virtual platform -func DiscoverSriovDevicesVirtual(devicesInfo OSPDevicesInfo) ([]sriovnetworkv1.InterfaceExt, error) { +func (o *openstackContext) DiscoverSriovDevicesVirtual() ([]sriovnetworkv1.InterfaceExt, error) { log.Log.V(2).Info("DiscoverSriovDevicesVirtual()") pfList := []sriovnetworkv1.InterfaceExt{} @@ -364,12 +360,12 @@ func DiscoverSriovDevicesVirtual(devicesInfo OSPDevicesInfo) ([]sriovnetworkv1.I "device", device) continue } - if devClass != netClass { + if devClass != consts.NetClass { // Not network device continue } - deviceInfo, exist := devicesInfo[device.Address] + deviceInfo, exist := o.openStackDevicesInfo[device.Address] if !exist { log.Log.Error(nil, "DiscoverSriovDevicesVirtual(): unable to find device in devicesInfo list, skipping", "device", device.Address) @@ -391,17 +387,17 @@ func DiscoverSriovDevicesVirtual(devicesInfo OSPDevicesInfo) ([]sriovnetworkv1.I DeviceID: device.Product.ID, NetFilter: netFilter, } - if mtu := getNetdevMTU(device.Address); mtu > 0 { + if mtu := o.hostManager.GetNetdevMTU(device.Address); mtu > 0 { iface.Mtu = mtu } - if name := tryToGetVirtualInterfaceName(device.Address); name != "" { + if name := o.hostManager.TryToGetVirtualInterfaceName(device.Address); name != "" { iface.Name = name - if iface.Mac = getNetDevMac(name); iface.Mac == "" { + if iface.Mac = o.hostManager.GetNetDevMac(name); iface.Mac == "" { iface.Mac = metaMac } - iface.LinkSpeed = getNetDevLinkSpeed(name) + iface.LinkSpeed = o.hostManager.GetNetDevLinkSpeed(name) } - iface.LinkType = getLinkType(iface) + iface.LinkType = o.hostManager.GetLinkType(iface) iface.TotalVfs = 1 iface.NumVfs = 1 @@ -422,147 +418,11 @@ func DiscoverSriovDevicesVirtual(devicesInfo OSPDevicesInfo) ([]sriovnetworkv1.I return pfList, nil } -func CreateOpenstackDevicesInfoFromNodeStatus(networkState *sriovnetworkv1.SriovNetworkNodeState) OSPDevicesInfo { +func (o *openstackContext) CreateOpenstackDevicesInfoFromNodeStatus(networkState *sriovnetworkv1.SriovNetworkNodeState) { devicesInfo := make(OSPDevicesInfo) for _, iface := range networkState.Status.Interfaces { devicesInfo[iface.PciAddress] = &OSPDeviceInfo{MacAddress: iface.Mac, NetworkID: iface.NetFilter} } - return devicesInfo -} - -// tryToGetVirtualInterfaceName get the interface name of a virtio interface -func tryToGetVirtualInterfaceName(pciAddr string) string { - log.Log.Info("tryToGetVirtualInterfaceName() get interface name for device", "device", pciAddr) - - // To support different driver that is not virtio-pci like mlx - name := tryGetInterfaceName(pciAddr) - if name != "" { - return name - } - - netDir, err := filepath.Glob(filepath.Join(sysBusPciDevices, pciAddr, "virtio*", "net")) - if err != nil || len(netDir) < 1 { - return "" - } - - fInfos, err := os.ReadDir(netDir[0]) - if err != nil { - log.Log.Error(err, "tryToGetVirtualInterfaceName(): failed to read net directory", "dir", netDir[0]) - return "" - } - - names := make([]string, 0) - for _, f := range fInfos { - names = append(names, f.Name()) - } - - if len(names) < 1 { - return "" - } - - return names[0] -} - -// SyncNodeStateVirtual attempt to update the node state to match the desired state -// -// in virtual platforms -func SyncNodeStateVirtual(newState *sriovnetworkv1.SriovNetworkNodeState) error { - var err error - for _, ifaceStatus := range newState.Status.Interfaces { - for _, iface := range newState.Spec.Interfaces { - if iface.PciAddress == ifaceStatus.PciAddress { - if !needUpdateVirtual(&iface, &ifaceStatus) { - log.Log.V(2).Info("SyncNodeStateVirtual(): no need update interface", "address", iface.PciAddress) - break - } - if err = configSriovDeviceVirtual(&iface, &ifaceStatus); err != nil { - log.Log.Error(err, "SyncNodeStateVirtual(): fail to config sriov interface", "address", iface.PciAddress) - return err - } - break - } - } - } - return nil -} - -func needUpdateVirtual(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) bool { - // The device MTU is set by the platorm - // The NumVfs is always 1 - if iface.NumVfs > 0 { - for _, vf := range ifaceStatus.VFs { - ingroup := false - for _, group := range iface.VfGroups { - if sriovnetworkv1.IndexInRange(vf.VfID, group.VfRange) { - ingroup = true - if group.DeviceType != constants.DeviceTypeNetDevice { - if group.DeviceType != vf.Driver { - log.Log.V(2).Info("needUpdateVirtual(): Driver needs update", - "desired", group.DeviceType, "current", vf.Driver) - return true - } - } else { - if sriovnetworkv1.StringInArray(vf.Driver, DpdkDrivers) { - log.Log.V(2).Info("needUpdateVirtual(): Driver needs update", - "desired", group.DeviceType, "current", vf.Driver) - return true - } - } - break - } - } - if !ingroup && sriovnetworkv1.StringInArray(vf.Driver, DpdkDrivers) { - // VF which has DPDK driver loaded but not in any group, needs to be reset to default driver. - return true - } - } - } - return false -} - -func configSriovDeviceVirtual(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error { - log.Log.V(2).Info("configSriovDeviceVirtual(): config interface", "address", iface.PciAddress, "config", iface) - // Config VFs - if iface.NumVfs > 0 { - if iface.NumVfs > 1 { - log.Log.Error(nil, "configSriovDeviceVirtual(): in a virtual environment, only one VF per interface", - "numVfs", iface.NumVfs) - return errors.New("NumVfs > 1") - } - if len(iface.VfGroups) != 1 { - log.Log.Error(nil, "configSriovDeviceVirtual(): missing VFGroup") - return errors.New("NumVfs != 1") - } - addr := iface.PciAddress - log.Log.V(2).Info("configSriovDeviceVirtual()", "address", addr) - driver := "" - vfID := 0 - for _, group := range iface.VfGroups { - log.Log.V(2).Info("configSriovDeviceVirtual()", "group", group) - if sriovnetworkv1.IndexInRange(vfID, group.VfRange) { - log.Log.V(2).Info("configSriovDeviceVirtual()", "indexInRange", vfID) - if sriovnetworkv1.StringInArray(group.DeviceType, DpdkDrivers) { - log.Log.V(2).Info("configSriovDeviceVirtual()", "driver", group.DeviceType) - driver = group.DeviceType - } - break - } - } - if driver == "" { - log.Log.V(2).Info("configSriovDeviceVirtual(): bind default") - if err := BindDefaultDriver(addr); err != nil { - log.Log.Error(err, "configSriovDeviceVirtual(): fail to bind default driver", "device", addr) - return err - } - } else { - log.Log.V(2).Info("configSriovDeviceVirtual(): bind driver", "driver", driver) - if err := BindDpdkDriver(addr, driver); err != nil { - log.Log.Error(err, "configSriovDeviceVirtual(): fail to bind driver for device", - "driver", driver, "device", addr) - return err - } - } - } - return nil + o.openStackDevicesInfo = devicesInfo } diff --git a/pkg/utils/utils_virtual_test.go b/pkg/platforms/openstack/openstack_test.go similarity index 95% rename from pkg/utils/utils_virtual_test.go rename to pkg/platforms/openstack/openstack_test.go index 5c55d4b54..ca18bce6e 100644 --- a/pkg/utils/utils_virtual_test.go +++ b/pkg/platforms/openstack/openstack_test.go @@ -1,4 +1,4 @@ -package utils +package openstack import ( "testing" @@ -6,10 +6,11 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "k8s.io/utils/pointer" + "github.com/jaypipes/ghw" "github.com/jaypipes/ghw/pkg/net" "github.com/jaypipes/ghw/pkg/option" - "k8s.io/utils/pointer" ) func TestUtilsVirtual(t *testing.T) { @@ -44,7 +45,7 @@ var _ = Describe("Virtual", func() { ghw.Network = net.New }) - metaData, _, err := GetOpenstackData(false) + metaData, _, err := getOpenstackData(false) Expect(err).ToNot(HaveOccurred()) Expect(metaData.Devices).To(HaveLen(2)) diff --git a/pkg/utils/testdata/meta_data.json b/pkg/platforms/openstack/testdata/meta_data.json similarity index 100% rename from pkg/utils/testdata/meta_data.json rename to pkg/platforms/openstack/testdata/meta_data.json diff --git a/pkg/utils/testdata/network_data.json b/pkg/platforms/openstack/testdata/network_data.json similarity index 100% rename from pkg/utils/testdata/network_data.json rename to pkg/platforms/openstack/testdata/network_data.json diff --git a/pkg/platforms/platforms.go b/pkg/platforms/platforms.go new file mode 100644 index 000000000..529f51821 --- /dev/null +++ b/pkg/platforms/platforms.go @@ -0,0 +1,31 @@ +package platforms + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openstack" +) + +//go:generate ../../bin/mockgen -destination mock/mock_platforms.go -source platforms.go +type Interface interface { + openshift.OpenshiftContextInterface + openstack.OpenstackInterface +} + +type platformHelper struct { + openshift.OpenshiftContextInterface + openstack.OpenstackInterface +} + +func NewDefaultPlatformHelper() (Interface, error) { + openshiftContext, err := openshift.New() + if err != nil { + return nil, err + } + + openstackContext := openstack.New() + + return &platformHelper{ + openshiftContext, + openstackContext, + }, nil +} From 4f93f9f0bf24713fbaa0052c07581680e9e1cef9 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 18:18:55 +0200 Subject: [PATCH 05/61] create vendor package to hold all the vendor specific functions for example MLX special mstconfig wrapper and create mock for unit tests Signed-off-by: Sebastian Sch --- pkg/vendors/mellanox/mellanox.go | 419 +++++++++++++++++++++ pkg/vendors/mellanox/mock/mock_mellanox.go | 96 +++++ 2 files changed, 515 insertions(+) create mode 100644 pkg/vendors/mellanox/mellanox.go create mode 100644 pkg/vendors/mellanox/mock/mock_mellanox.go diff --git a/pkg/vendors/mellanox/mellanox.go b/pkg/vendors/mellanox/mellanox.go new file mode 100644 index 000000000..c6631ed28 --- /dev/null +++ b/pkg/vendors/mellanox/mellanox.go @@ -0,0 +1,419 @@ +package mlxutils + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + "sigs.k8s.io/controller-runtime/pkg/log" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" +) + +// BlueField mode representation +type BlueFieldMode int + +const ( + BluefieldDpu BlueFieldMode = iota + BluefieldConnectXMode + + internalCPUPageSupplier = "INTERNAL_CPU_PAGE_SUPPLIER" + internalCPUEswitchManager = "INTERNAL_CPU_ESWITCH_MANAGER" + internalCPUIbVporto = "INTERNAL_CPU_IB_VPORT0" + internalCPUOffloadEngine = "INTERNAL_CPU_OFFLOAD_ENGINE" + internalCPUModel = "INTERNAL_CPU_MODEL" + + ecpf = "ECPF" + extHostPf = "EXT_HOST_PF" + embeddedCPU = "EMBEDDED_CPU" + + disabled = "DISABLED" + enabled = "ENABLED" + + VendorMellanox = "15b3" + DeviceBF2 = "a2d6" + DeviceBF3 = "a2dc" + + PreconfiguredLinkType = "Preconfigured" + UknownLinkType = "Uknown" + TotalVfs = "NUM_OF_VFS" + EnableSriov = "SRIOV_EN" + LinkTypeP1 = "LINK_TYPE_P1" + LinkTypeP2 = "LINK_TYPE_P2" + MellanoxVendorID = "15b3" +) + +type MlxNic struct { + EnableSriov bool + TotalVfs int + LinkTypeP1 string + LinkTypeP2 string +} + +//go:generate ../../../bin/mockgen -destination mock/mock_mellanox.go -source mellanox.go +type MellanoxInterface interface { + MstConfigReadData(string) (string, string, error) + GetMellanoxBlueFieldMode(string) (BlueFieldMode, error) + GetMlxNicFwData(pciAddress string) (current, next *MlxNic, err error) + + MlxConfigFW(attributesToChange map[string]MlxNic) error +} + +type mellanoxHelper struct { + utils utils.CmdInterface +} + +func New(utilsHelper utils.CmdInterface) MellanoxInterface { + return &mellanoxHelper{ + utils: utilsHelper, + } +} + +func (m *mellanoxHelper) MstConfigReadData(pciAddress string) (string, string, error) { + log.Log.Info("MstConfigReadData()", "device", pciAddress) + args := []string{"-e", "-d", pciAddress, "q"} + stdout, stderr, err := m.utils.RunCommand("mstconfig", args...) + return stdout, stderr, err +} + +func (m *mellanoxHelper) GetMellanoxBlueFieldMode(PciAddress string) (BlueFieldMode, error) { + log.Log.V(2).Info("MellanoxBlueFieldMode(): checking mode for device", "device", PciAddress) + stdout, stderr, err := m.MstConfigReadData(PciAddress) + if err != nil { + log.Log.Error(err, "MellanoxBlueFieldMode(): failed to get mlx nic fw data", "stderr", stderr) + return -1, fmt.Errorf("failed to get mlx nic fw data %w", err) + } + + attrs := []string{internalCPUPageSupplier, + internalCPUEswitchManager, + internalCPUIbVporto, + internalCPUOffloadEngine, + internalCPUModel} + mstCurrentData, _ := ParseMstconfigOutput(stdout, attrs) + + internalCPUPageSupplierstatus, exist := mstCurrentData[internalCPUPageSupplier] + if !exist { + return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUPageSupplier) + } + + internalCPUEswitchManagerStatus, exist := mstCurrentData[internalCPUEswitchManager] + if !exist { + return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUEswitchManager) + } + + internalCPUIbVportoStatus, exist := mstCurrentData[internalCPUIbVporto] + if !exist { + return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUIbVporto) + } + + internalCPUOffloadEngineStatus, exist := mstCurrentData[internalCPUOffloadEngine] + if !exist { + return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUOffloadEngine) + } + + internalCPUModelStatus, exist := mstCurrentData[internalCPUModel] + if !exist { + return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUModel) + } + + // check for DPU + if strings.Contains(internalCPUPageSupplierstatus, ecpf) && + strings.Contains(internalCPUEswitchManagerStatus, ecpf) && + strings.Contains(internalCPUIbVportoStatus, ecpf) && + strings.Contains(internalCPUOffloadEngineStatus, enabled) && + strings.Contains(internalCPUModelStatus, embeddedCPU) { + log.Log.V(2).Info("MellanoxBlueFieldMode(): device in DPU mode", "device", PciAddress) + return BluefieldDpu, nil + } else if strings.Contains(internalCPUPageSupplierstatus, extHostPf) && + strings.Contains(internalCPUEswitchManagerStatus, extHostPf) && + strings.Contains(internalCPUIbVportoStatus, extHostPf) && + strings.Contains(internalCPUOffloadEngineStatus, disabled) && + strings.Contains(internalCPUModelStatus, embeddedCPU) { + log.Log.V(2).Info("MellanoxBlueFieldMode(): device in ConnectX mode", "device", PciAddress) + return BluefieldConnectXMode, nil + } + + log.Log.Error(err, "MellanoxBlueFieldMode(): unknown device status", + "device", PciAddress, "mstconfig-output", stdout) + return -1, fmt.Errorf("MellanoxBlueFieldMode(): unknown device status for %s", PciAddress) +} + +func (m *mellanoxHelper) MlxConfigFW(attributesToChange map[string]MlxNic) error { + log.Log.Info("mellanox-plugin configFW()") + for pciAddr, fwArgs := range attributesToChange { + cmdArgs := []string{"-d", pciAddr, "-y", "set"} + if fwArgs.EnableSriov { + cmdArgs = append(cmdArgs, fmt.Sprintf("%s=True", EnableSriov)) + } else if fwArgs.TotalVfs == 0 { + cmdArgs = append(cmdArgs, fmt.Sprintf("%s=False", EnableSriov)) + } + if fwArgs.TotalVfs > -1 { + cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%d", TotalVfs, fwArgs.TotalVfs)) + } + if len(fwArgs.LinkTypeP1) > 0 { + cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%s", LinkTypeP1, fwArgs.LinkTypeP1)) + } + if len(fwArgs.LinkTypeP2) > 0 { + cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%s", LinkTypeP2, fwArgs.LinkTypeP2)) + } + + log.Log.V(2).Info("mellanox-plugin: configFW()", "cmd-args", cmdArgs) + if len(cmdArgs) <= 4 { + continue + } + _, strerr, err := m.utils.RunCommand("mstconfig", cmdArgs...) + if err != nil { + log.Log.Error(err, "mellanox-plugin configFW(): failed", "stderr", strerr) + return err + } + } + return nil +} + +func (m *mellanoxHelper) GetMlxNicFwData(pciAddress string) (current, next *MlxNic, err error) { + log.Log.Info("mellanox-plugin getMlnxNicFwData()", "device", pciAddress) + attrs := []string{TotalVfs, EnableSriov, LinkTypeP1, LinkTypeP2} + + out, stderr, err := m.MstConfigReadData(pciAddress) + if err != nil { + log.Log.Error(err, "mellanox-plugin getMlnxNicFwData(): failed", "stderr", stderr) + return + } + mstCurrentData, mstNextData := ParseMstconfigOutput(out, attrs) + current, err = mlnxNicFromMap(mstCurrentData) + if err != nil { + log.Log.Error(err, "mellanox-plugin mlnxNicFromMap() for current mstconfig data failed") + return + } + next, err = mlnxNicFromMap(mstNextData) + if err != nil { + log.Log.Error(err, "mellanox-plugin mlnxNicFromMap() for next mstconfig data failed") + } + return +} + +func ParseMstconfigOutput(mstOutput string, attributes []string) (fwCurrent, fwNext map[string]string) { + log.Log.Info("ParseMstconfigOutput()", "attributes", attributes) + fwCurrent = map[string]string{} + fwNext = map[string]string{} + formatRegex := regexp.MustCompile(`(?P\w+)\s+(?P\S+)\s+(?P\S+)\s+(?P\S+)`) + mstOutputLines := strings.Split(mstOutput, "\n") + for _, attr := range attributes { + for _, line := range mstOutputLines { + if strings.Contains(line, attr) { + regexResult := formatRegex.FindStringSubmatch(line) + fwCurrent[attr] = regexResult[3] + fwNext[attr] = regexResult[4] + break + } + } + } + return +} + +func HasMellanoxInterfacesInSpec(ifaceStatuses sriovnetworkv1.InterfaceExts, ifaceSpecs sriovnetworkv1.Interfaces) bool { + for _, ifaceStatus := range ifaceStatuses { + if ifaceStatus.Vendor == VendorMellanox { + for _, iface := range ifaceSpecs { + if iface.PciAddress == ifaceStatus.PciAddress { + log.Log.V(2).Info("hasMellanoxInterfacesInSpec(): Mellanox device specified in SriovNetworkNodeState spec", + "name", ifaceStatus.Name, + "address", ifaceStatus.PciAddress) + return true + } + } + } + } + return false +} + +func GetPciAddressPrefix(pciAddress string) string { + return pciAddress[:len(pciAddress)-1] +} + +func IsDualPort(pciAddress string, mellanoxNicsStatus map[string]map[string]sriovnetworkv1.InterfaceExt) bool { + log.Log.Info("mellanox-plugin IsDualPort()", "address", pciAddress) + pciAddressPrefix := GetPciAddressPrefix(pciAddress) + return len(mellanoxNicsStatus[pciAddressPrefix]) > 1 +} + +// handleTotalVfs return required total VFs or max (required VFs for dual port NIC) and needReboot if totalVfs will change +func HandleTotalVfs(fwCurrent, fwNext, attrs *MlxNic, ifaceSpec sriovnetworkv1.Interface, isDualPort bool, mellanoxNicsSpec map[string]sriovnetworkv1.Interface) ( + totalVfs int, needReboot, changeWithoutReboot bool) { + totalVfs = ifaceSpec.NumVfs + // Check if the other port is changing theGetMlnxNicFwData number of VF + if isDualPort { + otherIfaceSpec := getOtherPortSpec(ifaceSpec.PciAddress, mellanoxNicsSpec) + if otherIfaceSpec != nil { + if otherIfaceSpec.NumVfs > totalVfs { + totalVfs = otherIfaceSpec.NumVfs + } + } + } + + // if the PF is externally managed we just need to check the totalVfs requested in the policy is not higher than + // the configured amount + if ifaceSpec.ExternallyManaged { + if totalVfs > fwCurrent.TotalVfs { + log.Log.Error(nil, "The nic is externallyManaged and TotalVfs configured on the system is lower then requested VFs, failing configuration", + "current", fwCurrent.TotalVfs, "requested", totalVfs) + attrs.TotalVfs = totalVfs + needReboot = true + changeWithoutReboot = false + } + return + } + + if fwCurrent.TotalVfs != totalVfs { + log.Log.V(2).Info("Changing TotalVfs, needs reboot", "current", fwCurrent.TotalVfs, "requested", totalVfs) + attrs.TotalVfs = totalVfs + needReboot = true + } + + // Remove policy then re-apply it + if !needReboot && fwNext.TotalVfs != totalVfs { + log.Log.V(2).Info("Changing TotalVfs to same as Next Boot value, doesn't require rebooting", + "current", fwCurrent.TotalVfs, "next", fwNext.TotalVfs, "requested", totalVfs) + attrs.TotalVfs = totalVfs + changeWithoutReboot = true + } + + return +} + +// handleEnableSriov based on totalVfs it decide to disable (totalVfs=0) or enable (totalVfs changed from 0) sriov +// and need reboot if enableSriov will change +func HandleEnableSriov(totalVfs int, fwCurrent, fwNext, attrs *MlxNic) (needReboot, changeWithoutReboot bool) { + if totalVfs == 0 && fwCurrent.EnableSriov { + log.Log.V(2).Info("disabling Sriov, needs reboot") + attrs.EnableSriov = false + return true, false + } else if totalVfs > 0 && !fwCurrent.EnableSriov { + log.Log.V(2).Info("enabling Sriov, needs reboot") + attrs.EnableSriov = true + return true, false + } else if totalVfs > 0 && !fwNext.EnableSriov { + attrs.EnableSriov = true + return false, true + } + + return false, false +} + +// handleLinkType based on existing linkType and requested link +func HandleLinkType(pciPrefix string, fwData, attr *MlxNic, + mellanoxNicsSpec map[string]sriovnetworkv1.Interface, + mellanoxNicsStatus map[string]map[string]sriovnetworkv1.InterfaceExt) (bool, error) { + needReboot := false + + pciAddress := pciPrefix + "0" + if firstPortSpec, ok := mellanoxNicsSpec[pciAddress]; ok { + ifaceStatus := getIfaceStatus(pciAddress, mellanoxNicsStatus) + needChange, err := isLinkTypeRequireChange(firstPortSpec, ifaceStatus, fwData.LinkTypeP1) + if err != nil { + return false, err + } + + if needChange { + log.Log.V(2).Info("Changing LinkTypeP1, needs reboot", + "from", fwData.LinkTypeP1, "to", firstPortSpec.LinkType) + attr.LinkTypeP1 = firstPortSpec.LinkType + needReboot = true + } + } + + pciAddress = pciPrefix + "1" + if secondPortSpec, ok := mellanoxNicsSpec[pciAddress]; ok { + ifaceStatus := getIfaceStatus(pciAddress, mellanoxNicsStatus) + needChange, err := isLinkTypeRequireChange(secondPortSpec, ifaceStatus, fwData.LinkTypeP2) + if err != nil { + return false, err + } + + if needChange { + log.Log.V(2).Info("Changing LinkTypeP2, needs reboot", + "from", fwData.LinkTypeP2, "to", secondPortSpec.LinkType) + attr.LinkTypeP2 = secondPortSpec.LinkType + needReboot = true + } + } + + return needReboot, nil +} + +func mlnxNicFromMap(mstData map[string]string) (*MlxNic, error) { + log.Log.Info("mellanox-plugin mlnxNicFromMap()", "data", mstData) + fwData := &MlxNic{} + if strings.Contains(mstData[EnableSriov], "True") { + fwData.EnableSriov = true + } + i, err := strconv.Atoi(mstData[TotalVfs]) + if err != nil { + return nil, err + } + + fwData.TotalVfs = i + fwData.LinkTypeP1 = getLinkType(mstData[LinkTypeP1]) + if linkTypeP2, ok := mstData[LinkTypeP2]; ok { + fwData.LinkTypeP2 = getLinkType(linkTypeP2) + } + + return fwData, nil +} + +func getLinkType(linkType string) string { + log.Log.Info("mellanox-plugin getLinkType()", "link-type", linkType) + if strings.Contains(linkType, consts.LinkTypeETH) { + return consts.LinkTypeETH + } else if strings.Contains(linkType, consts.LinkTypeIB) { + return consts.LinkTypeIB + } else if len(linkType) > 0 { + log.Log.Error(nil, "mellanox-plugin getLinkType(): link type is not one of [ETH, IB], treating as unknown", + "link-type", linkType) + return UknownLinkType + } else { + log.Log.Info("mellanox-plugin getLinkType(): LINK_TYPE_P* attribute was not found, treating as preconfigured link type") + return PreconfiguredLinkType + } +} + +func isLinkTypeRequireChange(iface sriovnetworkv1.Interface, ifaceStatus sriovnetworkv1.InterfaceExt, fwLinkType string) (bool, error) { + log.Log.Info("mellanox-plugin isLinkTypeRequireChange()", "device", iface.PciAddress) + if iface.LinkType != "" && !strings.EqualFold(ifaceStatus.LinkType, iface.LinkType) { + if !strings.EqualFold(iface.LinkType, consts.LinkTypeETH) && !strings.EqualFold(iface.LinkType, consts.LinkTypeIB) { + return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Not supported link type: %s,"+ + " supported link types: [eth, ETH, ib, and IB]", iface.LinkType) + } + if fwLinkType == UknownLinkType { + return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Unknown link type: %s", fwLinkType) + } + if fwLinkType == PreconfiguredLinkType { + return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Network card %s does not support link type change", iface.PciAddress) + } + + return true, nil + } + + return false, nil +} + +func getOtherPortSpec(pciAddress string, mellanoxNicsSpec map[string]sriovnetworkv1.Interface) *sriovnetworkv1.Interface { + log.Log.Info("mellanox-plugin getOtherPortSpec()", "pciAddress", pciAddress) + pciAddrPrefix := GetPciAddressPrefix(pciAddress) + pciAddrSuffix := pciAddress[len(pciAddrPrefix):] + + if pciAddrSuffix == "0" { + iface := mellanoxNicsSpec[pciAddrPrefix+"1"] + return &iface + } + + iface := mellanoxNicsSpec[pciAddrPrefix+"0"] + return &iface +} + +func getIfaceStatus(pciAddress string, mellanoxNicsStatus map[string]map[string]sriovnetworkv1.InterfaceExt) sriovnetworkv1.InterfaceExt { + return mellanoxNicsStatus[GetPciAddressPrefix(pciAddress)][pciAddress] +} diff --git a/pkg/vendors/mellanox/mock/mock_mellanox.go b/pkg/vendors/mellanox/mock/mock_mellanox.go new file mode 100644 index 000000000..78c1d4903 --- /dev/null +++ b/pkg/vendors/mellanox/mock/mock_mellanox.go @@ -0,0 +1,96 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: mellanox.go + +// Package mock_mlxutils is a generated GoMock package. +package mock_mlxutils + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + mlxutils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" +) + +// MockMellanoxInterface is a mock of MellanoxInterface interface. +type MockMellanoxInterface struct { + ctrl *gomock.Controller + recorder *MockMellanoxInterfaceMockRecorder +} + +// MockMellanoxInterfaceMockRecorder is the mock recorder for MockMellanoxInterface. +type MockMellanoxInterfaceMockRecorder struct { + mock *MockMellanoxInterface +} + +// NewMockMellanoxInterface creates a new mock instance. +func NewMockMellanoxInterface(ctrl *gomock.Controller) *MockMellanoxInterface { + mock := &MockMellanoxInterface{ctrl: ctrl} + mock.recorder = &MockMellanoxInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMellanoxInterface) EXPECT() *MockMellanoxInterfaceMockRecorder { + return m.recorder +} + +// GetMellanoxBlueFieldMode mocks base method. +func (m *MockMellanoxInterface) GetMellanoxBlueFieldMode(arg0 string) (mlxutils.BlueFieldMode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMellanoxBlueFieldMode", arg0) + ret0, _ := ret[0].(mlxutils.BlueFieldMode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetMellanoxBlueFieldMode indicates an expected call of GetMellanoxBlueFieldMode. +func (mr *MockMellanoxInterfaceMockRecorder) GetMellanoxBlueFieldMode(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMellanoxBlueFieldMode", reflect.TypeOf((*MockMellanoxInterface)(nil).GetMellanoxBlueFieldMode), arg0) +} + +// GetMlxNicFwData mocks base method. +func (m *MockMellanoxInterface) GetMlxNicFwData(pciAddress string) (*mlxutils.MlxNic, *mlxutils.MlxNic, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMlxNicFwData", pciAddress) + ret0, _ := ret[0].(*mlxutils.MlxNic) + ret1, _ := ret[1].(*mlxutils.MlxNic) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetMlxNicFwData indicates an expected call of GetMlxNicFwData. +func (mr *MockMellanoxInterfaceMockRecorder) GetMlxNicFwData(pciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMlxNicFwData", reflect.TypeOf((*MockMellanoxInterface)(nil).GetMlxNicFwData), pciAddress) +} + +// MlxConfigFW mocks base method. +func (m *MockMellanoxInterface) MlxConfigFW(attributesToChange map[string]mlxutils.MlxNic) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MlxConfigFW", attributesToChange) + ret0, _ := ret[0].(error) + return ret0 +} + +// MlxConfigFW indicates an expected call of MlxConfigFW. +func (mr *MockMellanoxInterfaceMockRecorder) MlxConfigFW(attributesToChange interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MlxConfigFW", reflect.TypeOf((*MockMellanoxInterface)(nil).MlxConfigFW), attributesToChange) +} + +// MstConfigReadData mocks base method. +func (m *MockMellanoxInterface) MstConfigReadData(arg0 string) (string, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MstConfigReadData", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// MstConfigReadData indicates an expected call of MstConfigReadData. +func (mr *MockMellanoxInterfaceMockRecorder) MstConfigReadData(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MstConfigReadData", reflect.TypeOf((*MockMellanoxInterface)(nil).MstConfigReadData), arg0) +} From 387679bb514c5fbe08cbe77524f9277c9792b044 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 18:20:21 +0200 Subject: [PATCH 06/61] move all the functions from utils to a right place under the host package create also interfaces for everything so we can have better unit tests coverage Signed-off-by: Sebastian Sch --- pkg/helper/host.go | 49 ++ pkg/helper/mock/mock_helper.go | 1067 ++++++++++++++++++++++++++++++++ pkg/host/host.go | 457 -------------- pkg/host/interface.go | 55 ++ pkg/host/kernel.go | 627 +++++++++++++++++++ pkg/host/mock/mock_host.go | 254 -------- pkg/host/mock/mock_store.go | 108 ++++ pkg/host/network.go | 215 +++++++ pkg/host/service.go | 313 ++++++++++ pkg/host/sriov.go | 629 +++++++++++++++++++ pkg/{utils => host}/store.go | 93 ++- pkg/host/udev.go | 190 ++++++ pkg/service/service.go | 15 - pkg/service/service_manager.go | 94 --- pkg/service/types.go | 23 - pkg/service/utils.go | 151 ----- pkg/utils/cluster.go | 8 +- pkg/utils/command.go | 41 -- pkg/utils/driver.go | 119 ---- pkg/utils/mock/mock_utils.go | 70 +++ pkg/utils/shutdown.go | 6 +- pkg/utils/sriov.go | 151 ----- pkg/utils/utils.go | 995 ++--------------------------- pkg/utils/utils_mlx.go | 118 ---- 24 files changed, 3433 insertions(+), 2415 deletions(-) create mode 100644 pkg/helper/host.go create mode 100644 pkg/helper/mock/mock_helper.go delete mode 100644 pkg/host/host.go create mode 100644 pkg/host/interface.go create mode 100644 pkg/host/kernel.go delete mode 100644 pkg/host/mock/mock_host.go create mode 100644 pkg/host/mock/mock_store.go create mode 100644 pkg/host/network.go create mode 100644 pkg/host/service.go create mode 100644 pkg/host/sriov.go rename pkg/{utils => host}/store.go (55%) create mode 100644 pkg/host/udev.go delete mode 100644 pkg/service/service.go delete mode 100644 pkg/service/service_manager.go delete mode 100644 pkg/service/types.go delete mode 100644 pkg/service/utils.go delete mode 100644 pkg/utils/command.go delete mode 100644 pkg/utils/driver.go create mode 100644 pkg/utils/mock/mock_utils.go delete mode 100644 pkg/utils/sriov.go delete mode 100644 pkg/utils/utils_mlx.go diff --git a/pkg/helper/host.go b/pkg/helper/host.go new file mode 100644 index 000000000..df3325762 --- /dev/null +++ b/pkg/helper/host.go @@ -0,0 +1,49 @@ +package helper + +import ( + "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" +) + +//go:generate ../../bin/mockgen -destination mock/mock_helper.go -source host.go +type HostHelpersInterface interface { + utils.CmdInterface + host.HostManagerInterface + host.StoreManagerInterface + mlx.MellanoxInterface +} + +type hostHelpers struct { + utils.CmdInterface + host.HostManagerInterface + host.StoreManagerInterface + mlx.MellanoxInterface +} + +// Use for unit tests +func NewHostHelpers(utilsHelper utils.CmdInterface, + hostManager host.HostManagerInterface, + storeManager host.StoreManagerInterface, + mlxHelper mlx.MellanoxInterface) HostHelpersInterface { + return &hostHelpers{utilsHelper, hostManager, storeManager, mlxHelper} +} + +func NewDefaultHostHelpers() (HostHelpersInterface, error) { + utilsHelper := utils.New() + mlxHelper := mlx.New(utilsHelper) + hostManager := host.NewHostManager(utilsHelper) + storeManager, err := host.NewStoreManager() + if err != nil { + log.Log.Error(err, "failed to create store manager") + return nil, err + } + + return &hostHelpers{ + utilsHelper, + hostManager, + storeManager, + mlxHelper}, nil +} diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go new file mode 100644 index 000000000..74814f4e6 --- /dev/null +++ b/pkg/helper/mock/mock_helper.go @@ -0,0 +1,1067 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: host.go + +// Package mock_helper is a generated GoMock package. +package mock_helper + +import ( + reflect "reflect" + + unit "github.com/coreos/go-systemd/v22/unit" + gomock "github.com/golang/mock/gomock" + ghw "github.com/jaypipes/ghw" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + host "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + mlxutils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" + netlink "github.com/vishvananda/netlink" +) + +// MockHostHelpersInterface is a mock of HostHelpersInterface interface. +type MockHostHelpersInterface struct { + ctrl *gomock.Controller + recorder *MockHostHelpersInterfaceMockRecorder +} + +// MockHostHelpersInterfaceMockRecorder is the mock recorder for MockHostHelpersInterface. +type MockHostHelpersInterfaceMockRecorder struct { + mock *MockHostHelpersInterface +} + +// NewMockHostHelpersInterface creates a new mock instance. +func NewMockHostHelpersInterface(ctrl *gomock.Controller) *MockHostHelpersInterface { + mock := &MockHostHelpersInterface{ctrl: ctrl} + mock.recorder = &MockHostHelpersInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHostHelpersInterface) EXPECT() *MockHostHelpersInterfaceMockRecorder { + return m.recorder +} + +// AddUdevRule mocks base method. +func (m *MockHostHelpersInterface) AddUdevRule(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddUdevRule", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddUdevRule indicates an expected call of AddUdevRule. +func (mr *MockHostHelpersInterfaceMockRecorder) AddUdevRule(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).AddUdevRule), arg0) +} + +// BindDefaultDriver mocks base method. +func (m *MockHostHelpersInterface) BindDefaultDriver(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDefaultDriver", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDefaultDriver indicates an expected call of BindDefaultDriver. +func (mr *MockHostHelpersInterfaceMockRecorder) BindDefaultDriver(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDefaultDriver), arg0) +} + +// BindDpdkDriver mocks base method. +func (m *MockHostHelpersInterface) BindDpdkDriver(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDpdkDriver", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDpdkDriver indicates an expected call of BindDpdkDriver. +func (mr *MockHostHelpersInterfaceMockRecorder) BindDpdkDriver(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDpdkDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDpdkDriver), arg0, arg1) +} + +// Chroot mocks base method. +func (m *MockHostHelpersInterface) Chroot(arg0 string) (func() error, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Chroot", arg0) + ret0, _ := ret[0].(func() error) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Chroot indicates an expected call of Chroot. +func (mr *MockHostHelpersInterfaceMockRecorder) Chroot(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Chroot", reflect.TypeOf((*MockHostHelpersInterface)(nil).Chroot), arg0) +} + +// ClearPCIAddressFolder mocks base method. +func (m *MockHostHelpersInterface) ClearPCIAddressFolder() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClearPCIAddressFolder") + ret0, _ := ret[0].(error) + return ret0 +} + +// ClearPCIAddressFolder indicates an expected call of ClearPCIAddressFolder. +func (mr *MockHostHelpersInterfaceMockRecorder) ClearPCIAddressFolder() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearPCIAddressFolder", reflect.TypeOf((*MockHostHelpersInterface)(nil).ClearPCIAddressFolder)) +} + +// CompareServices mocks base method. +func (m *MockHostHelpersInterface) CompareServices(serviceA, serviceB *host.Service) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CompareServices", serviceA, serviceB) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CompareServices indicates an expected call of CompareServices. +func (mr *MockHostHelpersInterfaceMockRecorder) CompareServices(serviceA, serviceB interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareServices", reflect.TypeOf((*MockHostHelpersInterface)(nil).CompareServices), serviceA, serviceB) +} + +// ConfigSriovDevice mocks base method. +func (m *MockHostHelpersInterface) ConfigSriovDevice(iface *v1.Interface, ifaceStatus *v1.InterfaceExt) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovDevice", iface, ifaceStatus) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovDevice indicates an expected call of ConfigSriovDevice. +func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovDevice(iface, ifaceStatus interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovDevice), iface, ifaceStatus) +} + +// ConfigSriovDeviceVirtual mocks base method. +func (m *MockHostHelpersInterface) ConfigSriovDeviceVirtual(iface *v1.Interface) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovDeviceVirtual", iface) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovDeviceVirtual indicates an expected call of ConfigSriovDeviceVirtual. +func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovDeviceVirtual(iface interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovDeviceVirtual", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovDeviceVirtual), iface) +} + +// ConfigSriovInterfaces mocks base method. +func (m *MockHostHelpersInterface) ConfigSriovInterfaces(arg0 host.StoreManagerInterface, arg1 []v1.Interface, arg2 []v1.InterfaceExt, arg3 map[string]bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovInterfaces", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovInterfaces indicates an expected call of ConfigSriovInterfaces. +func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovInterfaces(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovInterfaces), arg0, arg1, arg2, arg3) +} + +// DiscoverSriovDevices mocks base method. +func (m *MockHostHelpersInterface) DiscoverSriovDevices(arg0 host.StoreManagerInterface) ([]v1.InterfaceExt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverSriovDevices", arg0) + ret0, _ := ret[0].([]v1.InterfaceExt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DiscoverSriovDevices indicates an expected call of DiscoverSriovDevices. +func (mr *MockHostHelpersInterfaceMockRecorder) DiscoverSriovDevices(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostHelpersInterface)(nil).DiscoverSriovDevices), arg0) +} + +// EnableRDMA mocks base method. +func (m *MockHostHelpersInterface) EnableRDMA(arg0, arg1, arg2 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableRDMA", arg0, arg1, arg2) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EnableRDMA indicates an expected call of EnableRDMA. +func (mr *MockHostHelpersInterfaceMockRecorder) EnableRDMA(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).EnableRDMA), arg0, arg1, arg2) +} + +// EnableRDMAOnRHELMachine mocks base method. +func (m *MockHostHelpersInterface) EnableRDMAOnRHELMachine() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableRDMAOnRHELMachine") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EnableRDMAOnRHELMachine indicates an expected call of EnableRDMAOnRHELMachine. +func (mr *MockHostHelpersInterfaceMockRecorder) EnableRDMAOnRHELMachine() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMAOnRHELMachine", reflect.TypeOf((*MockHostHelpersInterface)(nil).EnableRDMAOnRHELMachine)) +} + +// EnableService mocks base method. +func (m *MockHostHelpersInterface) EnableService(service *host.Service) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableService", service) + ret0, _ := ret[0].(error) + return ret0 +} + +// EnableService indicates an expected call of EnableService. +func (mr *MockHostHelpersInterfaceMockRecorder) EnableService(service interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableService", reflect.TypeOf((*MockHostHelpersInterface)(nil).EnableService), service) +} + +// GetCheckPointNodeState mocks base method. +func (m *MockHostHelpersInterface) GetCheckPointNodeState() (*v1.SriovNetworkNodeState, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCheckPointNodeState") + ret0, _ := ret[0].(*v1.SriovNetworkNodeState) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCheckPointNodeState indicates an expected call of GetCheckPointNodeState. +func (mr *MockHostHelpersInterfaceMockRecorder) GetCheckPointNodeState() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCheckPointNodeState", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetCheckPointNodeState)) +} + +// GetCurrentKernelArgs mocks base method. +func (m *MockHostHelpersInterface) GetCurrentKernelArgs() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentKernelArgs") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentKernelArgs indicates an expected call of GetCurrentKernelArgs. +func (mr *MockHostHelpersInterfaceMockRecorder) GetCurrentKernelArgs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentKernelArgs", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetCurrentKernelArgs)) +} + +// GetLinkType mocks base method. +func (m *MockHostHelpersInterface) GetLinkType(arg0 v1.InterfaceExt) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLinkType", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetLinkType indicates an expected call of GetLinkType. +func (mr *MockHostHelpersInterfaceMockRecorder) GetLinkType(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLinkType", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetLinkType), arg0) +} + +// GetMellanoxBlueFieldMode mocks base method. +func (m *MockHostHelpersInterface) GetMellanoxBlueFieldMode(arg0 string) (mlxutils.BlueFieldMode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMellanoxBlueFieldMode", arg0) + ret0, _ := ret[0].(mlxutils.BlueFieldMode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetMellanoxBlueFieldMode indicates an expected call of GetMellanoxBlueFieldMode. +func (mr *MockHostHelpersInterfaceMockRecorder) GetMellanoxBlueFieldMode(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMellanoxBlueFieldMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetMellanoxBlueFieldMode), arg0) +} + +// GetMlxNicFwData mocks base method. +func (m *MockHostHelpersInterface) GetMlxNicFwData(pciAddress string) (*mlxutils.MlxNic, *mlxutils.MlxNic, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMlxNicFwData", pciAddress) + ret0, _ := ret[0].(*mlxutils.MlxNic) + ret1, _ := ret[1].(*mlxutils.MlxNic) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetMlxNicFwData indicates an expected call of GetMlxNicFwData. +func (mr *MockHostHelpersInterfaceMockRecorder) GetMlxNicFwData(pciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMlxNicFwData", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetMlxNicFwData), pciAddress) +} + +// GetNetDevLinkSpeed mocks base method. +func (m *MockHostHelpersInterface) GetNetDevLinkSpeed(arg0 string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetDevLinkSpeed", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetNetDevLinkSpeed indicates an expected call of GetNetDevLinkSpeed. +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevLinkSpeed(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevLinkSpeed", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevLinkSpeed), arg0) +} + +// GetNetDevMac mocks base method. +func (m *MockHostHelpersInterface) GetNetDevMac(arg0 string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetDevMac", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetNetDevMac indicates an expected call of GetNetDevMac. +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevMac(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevMac), arg0) +} + +// GetNetdevMTU mocks base method. +func (m *MockHostHelpersInterface) GetNetdevMTU(arg0 string) int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetdevMTU", arg0) + ret0, _ := ret[0].(int) + return ret0 +} + +// GetNetdevMTU indicates an expected call of GetNetdevMTU. +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetdevMTU(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetdevMTU), arg0) +} + +// GetNicSriovMode mocks base method. +func (m *MockHostHelpersInterface) GetNicSriovMode(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNicSriovMode", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetNicSriovMode indicates an expected call of GetNicSriovMode. +func (mr *MockHostHelpersInterfaceMockRecorder) GetNicSriovMode(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNicSriovMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNicSriovMode), arg0) +} + +// GetOSPrettyName mocks base method. +func (m *MockHostHelpersInterface) GetOSPrettyName() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOSPrettyName") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetOSPrettyName indicates an expected call of GetOSPrettyName. +func (mr *MockHostHelpersInterfaceMockRecorder) GetOSPrettyName() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOSPrettyName", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetOSPrettyName)) +} + +// GetPhysPortName mocks base method. +func (m *MockHostHelpersInterface) GetPhysPortName(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPhysPortName", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPhysPortName indicates an expected call of GetPhysPortName. +func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysPortName(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysPortName", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysPortName), arg0) +} + +// GetPhysSwitchID mocks base method. +func (m *MockHostHelpersInterface) GetPhysSwitchID(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPhysSwitchID", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPhysSwitchID indicates an expected call of GetPhysSwitchID. +func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysSwitchID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysSwitchID", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysSwitchID), arg0) +} + +// GetVfInfo mocks base method. +func (m *MockHostHelpersInterface) GetVfInfo(arg0 string, arg1 []*ghw.PCIDevice) v1.VirtualFunction { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVfInfo", arg0, arg1) + ret0, _ := ret[0].(v1.VirtualFunction) + return ret0 +} + +// GetVfInfo indicates an expected call of GetVfInfo. +func (mr *MockHostHelpersInterfaceMockRecorder) GetVfInfo(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVfInfo", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetVfInfo), arg0, arg1) +} + +// HasDriver mocks base method. +func (m *MockHostHelpersInterface) HasDriver(arg0 string) (bool, string) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasDriver", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + return ret0, ret1 +} + +// HasDriver indicates an expected call of HasDriver. +func (mr *MockHostHelpersInterfaceMockRecorder) HasDriver(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).HasDriver), arg0) +} + +// InstallRDMA mocks base method. +func (m *MockHostHelpersInterface) InstallRDMA(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InstallRDMA", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// InstallRDMA indicates an expected call of InstallRDMA. +func (mr *MockHostHelpersInterfaceMockRecorder) InstallRDMA(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).InstallRDMA), arg0) +} + +// IsCoreOS mocks base method. +func (m *MockHostHelpersInterface) IsCoreOS() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsCoreOS") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsCoreOS indicates an expected call of IsCoreOS. +func (mr *MockHostHelpersInterfaceMockRecorder) IsCoreOS() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCoreOS", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsCoreOS)) +} + +// IsKernelArgsSet mocks base method. +func (m *MockHostHelpersInterface) IsKernelArgsSet(arg0, arg1 string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelArgsSet", arg0, arg1) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsKernelArgsSet indicates an expected call of IsKernelArgsSet. +func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelArgsSet(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelArgsSet", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelArgsSet), arg0, arg1) +} + +// IsKernelLockdownMode mocks base method. +func (m *MockHostHelpersInterface) IsKernelLockdownMode() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelLockdownMode") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsKernelLockdownMode indicates an expected call of IsKernelLockdownMode. +func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelLockdownMode() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelLockdownMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelLockdownMode)) +} + +// IsKernelModuleLoaded mocks base method. +func (m *MockHostHelpersInterface) IsKernelModuleLoaded(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelModuleLoaded", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsKernelModuleLoaded indicates an expected call of IsKernelModuleLoaded. +func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelModuleLoaded(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelModuleLoaded", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelModuleLoaded), arg0) +} + +// IsRHELSystem mocks base method. +func (m *MockHostHelpersInterface) IsRHELSystem() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsRHELSystem") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsRHELSystem indicates an expected call of IsRHELSystem. +func (mr *MockHostHelpersInterfaceMockRecorder) IsRHELSystem() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsRHELSystem", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsRHELSystem)) +} + +// IsServiceEnabled mocks base method. +func (m *MockHostHelpersInterface) IsServiceEnabled(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsServiceEnabled", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsServiceEnabled indicates an expected call of IsServiceEnabled. +func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceEnabled(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceEnabled", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceEnabled), arg0) +} + +// IsServiceExist mocks base method. +func (m *MockHostHelpersInterface) IsServiceExist(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsServiceExist", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsServiceExist indicates an expected call of IsServiceExist. +func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceExist(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceExist", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceExist), arg0) +} + +// IsSwitchdev mocks base method. +func (m *MockHostHelpersInterface) IsSwitchdev(arg0 string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSwitchdev", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSwitchdev indicates an expected call of IsSwitchdev. +func (mr *MockHostHelpersInterfaceMockRecorder) IsSwitchdev(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSwitchdev", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsSwitchdev), arg0) +} + +// IsUbuntuSystem mocks base method. +func (m *MockHostHelpersInterface) IsUbuntuSystem() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsUbuntuSystem") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsUbuntuSystem indicates an expected call of IsUbuntuSystem. +func (mr *MockHostHelpersInterfaceMockRecorder) IsUbuntuSystem() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUbuntuSystem", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsUbuntuSystem)) +} + +// LoadKernelModule mocks base method. +func (m *MockHostHelpersInterface) LoadKernelModule(name string, args ...string) error { + m.ctrl.T.Helper() + varargs := []interface{}{name} + for _, a := range args { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "LoadKernelModule", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadKernelModule indicates an expected call of LoadKernelModule. +func (mr *MockHostHelpersInterfaceMockRecorder) LoadKernelModule(name interface{}, args ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{name}, args...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadKernelModule", reflect.TypeOf((*MockHostHelpersInterface)(nil).LoadKernelModule), varargs...) +} + +// LoadPfsStatus mocks base method. +func (m *MockHostHelpersInterface) LoadPfsStatus(pciAddress string) (*v1.Interface, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadPfsStatus", pciAddress) + ret0, _ := ret[0].(*v1.Interface) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// LoadPfsStatus indicates an expected call of LoadPfsStatus. +func (mr *MockHostHelpersInterfaceMockRecorder) LoadPfsStatus(pciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPfsStatus", reflect.TypeOf((*MockHostHelpersInterface)(nil).LoadPfsStatus), pciAddress) +} + +// MlxConfigFW mocks base method. +func (m *MockHostHelpersInterface) MlxConfigFW(attributesToChange map[string]mlxutils.MlxNic) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MlxConfigFW", attributesToChange) + ret0, _ := ret[0].(error) + return ret0 +} + +// MlxConfigFW indicates an expected call of MlxConfigFW. +func (mr *MockHostHelpersInterfaceMockRecorder) MlxConfigFW(attributesToChange interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MlxConfigFW", reflect.TypeOf((*MockHostHelpersInterface)(nil).MlxConfigFW), attributesToChange) +} + +// MstConfigReadData mocks base method. +func (m *MockHostHelpersInterface) MstConfigReadData(arg0 string) (string, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MstConfigReadData", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// MstConfigReadData indicates an expected call of MstConfigReadData. +func (mr *MockHostHelpersInterfaceMockRecorder) MstConfigReadData(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MstConfigReadData", reflect.TypeOf((*MockHostHelpersInterface)(nil).MstConfigReadData), arg0) +} + +// PrepareNMUdevRule mocks base method. +func (m *MockHostHelpersInterface) PrepareNMUdevRule(arg0 []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PrepareNMUdevRule", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// PrepareNMUdevRule indicates an expected call of PrepareNMUdevRule. +func (mr *MockHostHelpersInterfaceMockRecorder) PrepareNMUdevRule(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareNMUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).PrepareNMUdevRule), arg0) +} + +// RdmaIsLoaded mocks base method. +func (m *MockHostHelpersInterface) RdmaIsLoaded() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RdmaIsLoaded") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RdmaIsLoaded indicates an expected call of RdmaIsLoaded. +func (mr *MockHostHelpersInterfaceMockRecorder) RdmaIsLoaded() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RdmaIsLoaded", reflect.TypeOf((*MockHostHelpersInterface)(nil).RdmaIsLoaded)) +} + +// ReadScriptManifestFile mocks base method. +func (m *MockHostHelpersInterface) ReadScriptManifestFile(path string) (*host.ScriptManifestFile, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadScriptManifestFile", path) + ret0, _ := ret[0].(*host.ScriptManifestFile) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadScriptManifestFile indicates an expected call of ReadScriptManifestFile. +func (mr *MockHostHelpersInterfaceMockRecorder) ReadScriptManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadScriptManifestFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadScriptManifestFile), path) +} + +// ReadService mocks base method. +func (m *MockHostHelpersInterface) ReadService(arg0 string) (*host.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadService", arg0) + ret0, _ := ret[0].(*host.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadService indicates an expected call of ReadService. +func (mr *MockHostHelpersInterfaceMockRecorder) ReadService(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadService", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadService), arg0) +} + +// ReadServiceInjectionManifestFile mocks base method. +func (m *MockHostHelpersInterface) ReadServiceInjectionManifestFile(path string) (*host.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadServiceInjectionManifestFile", path) + ret0, _ := ret[0].(*host.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadServiceInjectionManifestFile indicates an expected call of ReadServiceInjectionManifestFile. +func (mr *MockHostHelpersInterfaceMockRecorder) ReadServiceInjectionManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadServiceInjectionManifestFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadServiceInjectionManifestFile), path) +} + +// ReadServiceManifestFile mocks base method. +func (m *MockHostHelpersInterface) ReadServiceManifestFile(path string) (*host.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadServiceManifestFile", path) + ret0, _ := ret[0].(*host.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadServiceManifestFile indicates an expected call of ReadServiceManifestFile. +func (mr *MockHostHelpersInterfaceMockRecorder) ReadServiceManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadServiceManifestFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadServiceManifestFile), path) +} + +// RebindVfToDefaultDriver mocks base method. +func (m *MockHostHelpersInterface) RebindVfToDefaultDriver(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RebindVfToDefaultDriver", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RebindVfToDefaultDriver indicates an expected call of RebindVfToDefaultDriver. +func (mr *MockHostHelpersInterfaceMockRecorder) RebindVfToDefaultDriver(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebindVfToDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).RebindVfToDefaultDriver), arg0) +} + +// ReloadDriver mocks base method. +func (m *MockHostHelpersInterface) ReloadDriver(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReloadDriver", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ReloadDriver indicates an expected call of ReloadDriver. +func (mr *MockHostHelpersInterfaceMockRecorder) ReloadDriver(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReloadDriver), arg0) +} + +// RemoveFromService mocks base method. +func (m *MockHostHelpersInterface) RemoveFromService(service *host.Service, options ...*unit.UnitOption) (*host.Service, error) { + m.ctrl.T.Helper() + varargs := []interface{}{service} + for _, a := range options { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveFromService", varargs...) + ret0, _ := ret[0].(*host.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveFromService indicates an expected call of RemoveFromService. +func (mr *MockHostHelpersInterfaceMockRecorder) RemoveFromService(service interface{}, options ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{service}, options...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveFromService", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveFromService), varargs...) +} + +// RemoveUdevRule mocks base method. +func (m *MockHostHelpersInterface) RemoveUdevRule(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveUdevRule", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveUdevRule indicates an expected call of RemoveUdevRule. +func (mr *MockHostHelpersInterfaceMockRecorder) RemoveUdevRule(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveUdevRule), arg0) +} + +// ResetSriovDevice mocks base method. +func (m *MockHostHelpersInterface) ResetSriovDevice(arg0 v1.InterfaceExt) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResetSriovDevice", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ResetSriovDevice indicates an expected call of ResetSriovDevice. +func (mr *MockHostHelpersInterfaceMockRecorder) ResetSriovDevice(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetSriovDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).ResetSriovDevice), arg0) +} + +// RunCommand mocks base method. +func (m *MockHostHelpersInterface) RunCommand(arg0 string, arg1 ...string) (string, string, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RunCommand", varargs...) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// RunCommand indicates an expected call of RunCommand. +func (mr *MockHostHelpersInterfaceMockRecorder) RunCommand(arg0 interface{}, arg1 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunCommand", reflect.TypeOf((*MockHostHelpersInterface)(nil).RunCommand), varargs...) +} + +// SaveLastPfAppliedStatus mocks base method. +func (m *MockHostHelpersInterface) SaveLastPfAppliedStatus(PfInfo *v1.Interface) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SaveLastPfAppliedStatus", PfInfo) + ret0, _ := ret[0].(error) + return ret0 +} + +// SaveLastPfAppliedStatus indicates an expected call of SaveLastPfAppliedStatus. +func (mr *MockHostHelpersInterfaceMockRecorder) SaveLastPfAppliedStatus(PfInfo interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveLastPfAppliedStatus", reflect.TypeOf((*MockHostHelpersInterface)(nil).SaveLastPfAppliedStatus), PfInfo) +} + +// SetNetdevMTU mocks base method. +func (m *MockHostHelpersInterface) SetNetdevMTU(arg0 string, arg1 int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetNetdevMTU", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetNetdevMTU indicates an expected call of SetNetdevMTU. +func (mr *MockHostHelpersInterfaceMockRecorder) SetNetdevMTU(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetNetdevMTU), arg0, arg1) +} + +// SetSriovNumVfs mocks base method. +func (m *MockHostHelpersInterface) SetSriovNumVfs(arg0 string, arg1 int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetSriovNumVfs", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetSriovNumVfs indicates an expected call of SetSriovNumVfs. +func (mr *MockHostHelpersInterfaceMockRecorder) SetSriovNumVfs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSriovNumVfs", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetSriovNumVfs), arg0, arg1) +} + +// SetVfAdminMac mocks base method. +func (m *MockHostHelpersInterface) SetVfAdminMac(arg0 string, arg1, arg2 netlink.Link) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetVfAdminMac", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetVfAdminMac indicates an expected call of SetVfAdminMac. +func (mr *MockHostHelpersInterfaceMockRecorder) SetVfAdminMac(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfAdminMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfAdminMac), arg0, arg1, arg2) +} + +// SetVfGUID mocks base method. +func (m *MockHostHelpersInterface) SetVfGUID(arg0 string, arg1 netlink.Link) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetVfGUID", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetVfGUID indicates an expected call of SetVfGUID. +func (mr *MockHostHelpersInterfaceMockRecorder) SetVfGUID(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfGUID", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfGUID), arg0, arg1) +} + +// TriggerUdevEvent mocks base method. +func (m *MockHostHelpersInterface) TriggerUdevEvent() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TriggerUdevEvent") + ret0, _ := ret[0].(error) + return ret0 +} + +// TriggerUdevEvent indicates an expected call of TriggerUdevEvent. +func (mr *MockHostHelpersInterfaceMockRecorder) TriggerUdevEvent() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TriggerUdevEvent", reflect.TypeOf((*MockHostHelpersInterface)(nil).TriggerUdevEvent)) +} + +// TryEnableRdma mocks base method. +func (m *MockHostHelpersInterface) TryEnableRdma() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryEnableRdma") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TryEnableRdma indicates an expected call of TryEnableRdma. +func (mr *MockHostHelpersInterfaceMockRecorder) TryEnableRdma() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableRdma", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryEnableRdma)) +} + +// TryEnableTun mocks base method. +func (m *MockHostHelpersInterface) TryEnableTun() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TryEnableTun") +} + +// TryEnableTun indicates an expected call of TryEnableTun. +func (mr *MockHostHelpersInterfaceMockRecorder) TryEnableTun() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableTun", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryEnableTun)) +} + +// TryEnableVhostNet mocks base method. +func (m *MockHostHelpersInterface) TryEnableVhostNet() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TryEnableVhostNet") +} + +// TryEnableVhostNet indicates an expected call of TryEnableVhostNet. +func (mr *MockHostHelpersInterfaceMockRecorder) TryEnableVhostNet() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableVhostNet", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryEnableVhostNet)) +} + +// TryGetInterfaceName mocks base method. +func (m *MockHostHelpersInterface) TryGetInterfaceName(arg0 string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryGetInterfaceName", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// TryGetInterfaceName indicates an expected call of TryGetInterfaceName. +func (mr *MockHostHelpersInterfaceMockRecorder) TryGetInterfaceName(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryGetInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryGetInterfaceName), arg0) +} + +// TryToGetVirtualInterfaceName mocks base method. +func (m *MockHostHelpersInterface) TryToGetVirtualInterfaceName(arg0 string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryToGetVirtualInterfaceName", arg0) + ret0, _ := ret[0].(string) + return ret0 +} + +// TryToGetVirtualInterfaceName indicates an expected call of TryToGetVirtualInterfaceName. +func (mr *MockHostHelpersInterfaceMockRecorder) TryToGetVirtualInterfaceName(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryToGetVirtualInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryToGetVirtualInterfaceName), arg0) +} + +// Unbind mocks base method. +func (m *MockHostHelpersInterface) Unbind(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Unbind", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Unbind indicates an expected call of Unbind. +func (mr *MockHostHelpersInterfaceMockRecorder) Unbind(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockHostHelpersInterface)(nil).Unbind), arg0) +} + +// UnbindDriverIfNeeded mocks base method. +func (m *MockHostHelpersInterface) UnbindDriverIfNeeded(arg0 string, arg1 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbindDriverIfNeeded", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnbindDriverIfNeeded indicates an expected call of UnbindDriverIfNeeded. +func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverIfNeeded(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverIfNeeded", reflect.TypeOf((*MockHostHelpersInterface)(nil).UnbindDriverIfNeeded), arg0, arg1) +} + +// UpdateSystemService mocks base method. +func (m *MockHostHelpersInterface) UpdateSystemService(serviceObj *host.Service) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateSystemService", serviceObj) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateSystemService indicates an expected call of UpdateSystemService. +func (mr *MockHostHelpersInterfaceMockRecorder) UpdateSystemService(serviceObj interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSystemService", reflect.TypeOf((*MockHostHelpersInterface)(nil).UpdateSystemService), serviceObj) +} + +// VFIsReady mocks base method. +func (m *MockHostHelpersInterface) VFIsReady(arg0 string) (netlink.Link, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "VFIsReady", arg0) + ret0, _ := ret[0].(netlink.Link) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// VFIsReady indicates an expected call of VFIsReady. +func (mr *MockHostHelpersInterfaceMockRecorder) VFIsReady(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VFIsReady", reflect.TypeOf((*MockHostHelpersInterface)(nil).VFIsReady), arg0) +} + +// WriteCheckpointFile mocks base method. +func (m *MockHostHelpersInterface) WriteCheckpointFile(arg0 *v1.SriovNetworkNodeState) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteCheckpointFile", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteCheckpointFile indicates an expected call of WriteCheckpointFile. +func (mr *MockHostHelpersInterfaceMockRecorder) WriteCheckpointFile(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCheckpointFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).WriteCheckpointFile), arg0) +} + +// WriteSwitchdevConfFile mocks base method. +func (m *MockHostHelpersInterface) WriteSwitchdevConfFile(arg0 *v1.SriovNetworkNodeState, arg1 map[string]bool) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteSwitchdevConfFile", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WriteSwitchdevConfFile indicates an expected call of WriteSwitchdevConfFile. +func (mr *MockHostHelpersInterfaceMockRecorder) WriteSwitchdevConfFile(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSwitchdevConfFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).WriteSwitchdevConfFile), arg0, arg1) +} diff --git a/pkg/host/host.go b/pkg/host/host.go deleted file mode 100644 index 241e6ba17..000000000 --- a/pkg/host/host.go +++ /dev/null @@ -1,457 +0,0 @@ -/* -Copyright 2023. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package host - -import ( - "fmt" - "os" - pathlib "path" - "strings" - - "sigs.k8s.io/controller-runtime/pkg/log" - - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" -) - -const ( - hostPathFromDaemon = "/host" - redhatReleaseFile = "/etc/redhat-release" - rhelRDMAConditionFile = "/usr/libexec/rdma-init-kernel" - rhelRDMAServiceName = "rdma" - rhelPackageManager = "yum" - - ubuntuRDMAConditionFile = "/usr/sbin/rdma-ndd" - ubuntuRDMAServiceName = "rdma-ndd" - ubuntuPackageManager = "apt-get" - - genericOSReleaseFile = "/etc/os-release" -) - -// Contains all the host manipulation functions -// -//go:generate ../../bin/mockgen -destination mock/mock_host.go -source host.go -type HostManagerInterface interface { - TryEnableTun() - TryEnableVhostNet() - TryEnableRdma() (bool, error) - - // private functions - // part of the interface for the mock generation - LoadKernelModule(name string, args ...string) error - IsKernelModuleLoaded(string) (bool, error) - IsRHELSystem() (bool, error) - IsUbuntuSystem() (bool, error) - IsCoreOS() (bool, error) - RdmaIsLoaded() (bool, error) - EnableRDMA(string, string, string) (bool, error) - InstallRDMA(string) error - TriggerUdevEvent() error - ReloadDriver(string) error - EnableRDMAOnRHELMachine() (bool, error) - GetOSPrettyName() (string, error) -} - -type HostManager struct { - RunOnHost bool - cmd utils.CommandInterface -} - -func NewHostManager(runOnHost bool) HostManagerInterface { - return &HostManager{ - RunOnHost: runOnHost, - cmd: &utils.Command{}, - } -} - -func (h *HostManager) LoadKernelModule(name string, args ...string) error { - log.Log.Info("LoadKernelModule(): try to load kernel module", "name", name, "args", args) - chrootDefinition := getChrootExtension(h.RunOnHost) - cmdArgs := strings.Join(args, " ") - - // check if the driver is already loaded in to the system - isLoaded, err := h.IsKernelModuleLoaded(name) - if err != nil { - log.Log.Error(err, "LoadKernelModule(): failed to check if kernel module is already loaded", "name", name) - } - if isLoaded { - log.Log.Info("LoadKernelModule(): kernel module already loaded", "name", name) - return nil - } - - _, _, err = h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s modprobe %s %s", chrootDefinition, name, cmdArgs)) - if err != nil { - log.Log.Error(err, "LoadKernelModule(): failed to load kernel module with arguments", "name", name, "args", args) - return err - } - return nil -} - -func (h *HostManager) IsKernelModuleLoaded(kernelModuleName string) (bool, error) { - log.Log.Info("IsKernelModuleLoaded(): check if kernel module is loaded", "name", kernelModuleName) - chrootDefinition := getChrootExtension(h.RunOnHost) - - stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s lsmod | grep \"^%s\"", chrootDefinition, kernelModuleName)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "IsKernelModuleLoaded(): failed to check if kernel module is loaded", - "name", kernelModuleName, "stderr", stderr.String()) - return false, err - } - log.Log.V(2).Info("IsKernelModuleLoaded():", "stdout", stdout.String()) - if stderr.Len() != 0 { - log.Log.Error(err, "IsKernelModuleLoaded(): failed to check if kernel module is loaded", "name", kernelModuleName, "stderr", stderr.String()) - return false, fmt.Errorf(stderr.String()) - } - - if stdout.Len() != 0 { - log.Log.Info("IsKernelModuleLoaded(): kernel module already loaded", "name", kernelModuleName) - return true, nil - } - - return false, nil -} - -func (h *HostManager) TryEnableTun() { - if err := h.LoadKernelModule("tun"); err != nil { - log.Log.Error(err, "tryEnableTun(): TUN kernel module not loaded") - } -} - -func (h *HostManager) TryEnableVhostNet() { - if err := h.LoadKernelModule("vhost_net"); err != nil { - log.Log.Error(err, "tryEnableVhostNet(): VHOST_NET kernel module not loaded") - } -} - -func (h *HostManager) TryEnableRdma() (bool, error) { - log.Log.V(2).Info("tryEnableRdma()") - chrootDefinition := getChrootExtension(h.RunOnHost) - - // check if the driver is already loaded in to the system - _, stderr, mlx4Err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx4_en' <(%s lsmod)", chrootDefinition)) - if mlx4Err != nil && stderr.Len() != 0 { - log.Log.Error(mlx4Err, "tryEnableRdma(): failed to check for kernel module 'mlx4_en'", "stderr", stderr.String()) - return false, fmt.Errorf(stderr.String()) - } - - _, stderr, mlx5Err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx5_core' <(%s lsmod)", chrootDefinition)) - if mlx5Err != nil && stderr.Len() != 0 { - log.Log.Error(mlx5Err, "tryEnableRdma(): failed to check for kernel module 'mlx5_core'", "stderr", stderr.String()) - return false, fmt.Errorf(stderr.String()) - } - - if mlx4Err != nil && mlx5Err != nil { - log.Log.Error(nil, "tryEnableRdma(): no RDMA capable devices") - return false, nil - } - - isRhelSystem, err := h.IsRHELSystem() - if err != nil { - log.Log.Error(err, "tryEnableRdma(): failed to check if the machine is base on RHEL") - return false, err - } - - // RHEL check - if isRhelSystem { - return h.EnableRDMAOnRHELMachine() - } - - isUbuntuSystem, err := h.IsUbuntuSystem() - if err != nil { - log.Log.Error(err, "tryEnableRdma(): failed to check if the machine is base on Ubuntu") - return false, err - } - - if isUbuntuSystem { - return h.EnableRDMAOnUbuntuMachine() - } - - osName, err := h.GetOSPrettyName() - if err != nil { - log.Log.Error(err, "tryEnableRdma(): failed to check OS name") - return false, err - } - - log.Log.Error(nil, "tryEnableRdma(): Unsupported OS", "name", osName) - return false, fmt.Errorf("unable to load RDMA unsupported OS: %s", osName) -} - -func (h *HostManager) EnableRDMAOnRHELMachine() (bool, error) { - log.Log.Info("EnableRDMAOnRHELMachine()") - isCoreOsSystem, err := h.IsCoreOS() - if err != nil { - log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if the machine runs CoreOS") - return false, err - } - - // CoreOS check - if isCoreOsSystem { - isRDMALoaded, err := h.RdmaIsLoaded() - if err != nil { - log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded") - return false, err - } - - return isRDMALoaded, nil - } - - // RHEL - log.Log.Info("EnableRDMAOnRHELMachine(): enabling RDMA on RHEL machine") - isRDMAEnable, err := h.EnableRDMA(rhelRDMAConditionFile, rhelRDMAServiceName, rhelPackageManager) - if err != nil { - log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to enable RDMA on RHEL machine") - return false, err - } - - // check if we need to install rdma-core package - if isRDMAEnable { - isRDMALoaded, err := h.RdmaIsLoaded() - if err != nil { - log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded") - return false, err - } - - // if ib kernel module is not loaded trigger a loading - if isRDMALoaded { - err = h.TriggerUdevEvent() - if err != nil { - log.Log.Error(err, "EnableRDMAOnRHELMachine() failed to trigger udev event") - return false, err - } - } - } - - return true, nil -} - -func (h *HostManager) EnableRDMAOnUbuntuMachine() (bool, error) { - log.Log.Info("EnableRDMAOnUbuntuMachine(): enabling RDMA on RHEL machine") - isRDMAEnable, err := h.EnableRDMA(ubuntuRDMAConditionFile, ubuntuRDMAServiceName, ubuntuPackageManager) - if err != nil { - log.Log.Error(err, "EnableRDMAOnUbuntuMachine(): failed to enable RDMA on Ubuntu machine") - return false, err - } - - // check if we need to install rdma-core package - if isRDMAEnable { - isRDMALoaded, err := h.RdmaIsLoaded() - if err != nil { - log.Log.Error(err, "EnableRDMAOnUbuntuMachine(): failed to check if RDMA kernel modules are loaded") - return false, err - } - - // if ib kernel module is not loaded trigger a loading - if isRDMALoaded { - err = h.TriggerUdevEvent() - if err != nil { - log.Log.Error(err, "EnableRDMAOnUbuntuMachine() failed to trigger udev event") - return false, err - } - } - } - - return true, nil -} - -func (h *HostManager) IsRHELSystem() (bool, error) { - log.Log.Info("IsRHELSystem(): checking for RHEL machine") - path := redhatReleaseFile - if !h.RunOnHost { - path = pathlib.Join(hostPathFromDaemon, path) - } - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - log.Log.V(2).Info("IsRHELSystem() not a RHEL machine") - return false, nil - } - - log.Log.Error(err, "IsRHELSystem() failed to check for os release file", "path", path) - return false, err - } - - return true, nil -} - -func (h *HostManager) IsCoreOS() (bool, error) { - log.Log.Info("IsCoreOS(): checking for CoreOS machine") - path := redhatReleaseFile - if !h.RunOnHost { - path = pathlib.Join(hostPathFromDaemon, path) - } - - data, err := os.ReadFile(path) - if err != nil { - log.Log.Error(err, "IsCoreOS(): failed to read RHEL release file on path", "path", path) - return false, err - } - - if strings.Contains(string(data), "CoreOS") { - return true, nil - } - - return false, nil -} - -func (h *HostManager) IsUbuntuSystem() (bool, error) { - log.Log.Info("IsUbuntuSystem(): checking for Ubuntu machine") - path := genericOSReleaseFile - if !h.RunOnHost { - path = pathlib.Join(hostPathFromDaemon, path) - } - - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - log.Log.Error(nil, "IsUbuntuSystem() os-release on path doesn't exist", "path", path) - return false, err - } - - log.Log.Error(err, "IsUbuntuSystem() failed to check for os release file", "path", path) - return false, err - } - - stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep -i --quiet 'ubuntu' %s", path)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "IsUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file", "stderr", stderr.String()) - return false, fmt.Errorf(stderr.String()) - } - - if stdout.Len() > 0 { - return true, nil - } - - return false, nil -} - -func (h *HostManager) RdmaIsLoaded() (bool, error) { - log.Log.V(2).Info("RdmaIsLoaded()") - chrootDefinition := getChrootExtension(h.RunOnHost) - - // check if the driver is already loaded in to the system - _, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet '\\(^ib\\|^rdma\\)' <(%s lsmod)", chrootDefinition)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "RdmaIsLoaded(): fail to check if ib and rdma kernel modules are loaded", "stderr", stderr.String()) - return false, fmt.Errorf(stderr.String()) - } - - if err != nil { - return false, nil - } - - return true, nil -} - -func (h *HostManager) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { - path := conditionFilePath - if !h.RunOnHost { - path = pathlib.Join(hostPathFromDaemon, path) - } - log.Log.Info("EnableRDMA(): checking for service file", "path", path) - - if _, err := os.Stat(path); err != nil { - if os.IsNotExist(err) { - log.Log.V(2).Info("EnableRDMA(): RDMA server doesn't exist") - err = h.InstallRDMA(packageManager) - if err != nil { - log.Log.Error(err, "EnableRDMA() failed to install RDMA package") - return false, err - } - - err = h.TriggerUdevEvent() - if err != nil { - log.Log.Error(err, "EnableRDMA() failed to trigger udev event") - return false, err - } - - return false, nil - } - - log.Log.Error(err, "EnableRDMA() failed to check for os release file", "path", path) - return false, err - } - - log.Log.Info("EnableRDMA(): service installed", "name", serviceName) - return true, nil -} - -func (h *HostManager) InstallRDMA(packageManager string) error { - log.Log.Info("InstallRDMA(): installing RDMA") - chrootDefinition := getChrootExtension(h.RunOnHost) - - stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s %s install -y rdma-core", chrootDefinition, packageManager)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "InstallRDMA(): failed to install RDMA package", "stdout", stdout.String(), "stderr", stderr.String()) - return err - } - - return nil -} - -func (h *HostManager) TriggerUdevEvent() error { - log.Log.Info("TriggerUdevEvent(): installing RDMA") - - err := h.ReloadDriver("mlx4_en") - if err != nil { - return err - } - - err = h.ReloadDriver("mlx5_core") - if err != nil { - return err - } - - return nil -} - -func (h *HostManager) ReloadDriver(driverName string) error { - log.Log.Info("ReloadDriver(): reload driver", "name", driverName) - chrootDefinition := getChrootExtension(h.RunOnHost) - - _, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s modprobe -r %s && %s modprobe %s", chrootDefinition, driverName, chrootDefinition, driverName)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "InstallRDMA(): failed to reload kernel module", - "name", driverName, "stderr", stderr.String()) - return err - } - - return nil -} - -func (h *HostManager) GetOSPrettyName() (string, error) { - path := genericOSReleaseFile - if !h.RunOnHost { - path = pathlib.Join(hostPathFromDaemon, path) - } - - log.Log.Info("GetOSPrettyName(): getting os name from os-release file") - - stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("cat %s | grep PRETTY_NAME | cut -c 13-", path)) - if err != nil && stderr.Len() != 0 { - log.Log.Error(err, "IsUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file", "stderr", stderr.String()) - return "", fmt.Errorf(stderr.String()) - } - - if stdout.Len() > 0 { - return stdout.String(), nil - } - - return "", fmt.Errorf("failed to find pretty operating system name") -} - -func getChrootExtension(runOnHost bool) string { - if !runOnHost { - return fmt.Sprintf("chroot %s/host", utils.FilesystemRoot) - } - return utils.FilesystemRoot -} diff --git a/pkg/host/interface.go b/pkg/host/interface.go new file mode 100644 index 000000000..edccfd5c8 --- /dev/null +++ b/pkg/host/interface.go @@ -0,0 +1,55 @@ +package host + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" +) + +const ( + hostPathFromDaemon = consts.Host + redhatReleaseFile = "/etc/redhat-release" + rhelRDMAConditionFile = "/usr/libexec/rdma-init-kernel" + rhelRDMAServiceName = "rdma" + rhelPackageManager = "yum" + + ubuntuRDMAConditionFile = "/usr/sbin/rdma-ndd" + ubuntuRDMAServiceName = "rdma-ndd" + ubuntuPackageManager = "apt-get" + + genericOSReleaseFile = "/etc/os-release" +) + +// Contains all the host manipulation functions +type HostManagerInterface interface { + KernelInterface + NetworkInterface + ServiceInterface + UdevInterface + SriovInterface +} + +type hostManager struct { + utils.CmdInterface + KernelInterface + NetworkInterface + ServiceInterface + UdevInterface + SriovInterface +} + +func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { + k := newKernelInterface(utilsInterface) + n := newNetworkInterface(utilsInterface) + sv := newServiceInterface(utilsInterface) + u := newUdevInterface(utilsInterface) + sr := newSriovInterface(utilsInterface, k, n, u) + + return &hostManager{ + utilsInterface, + k, + n, + sv, + u, + sr, + } +} diff --git a/pkg/host/kernel.go b/pkg/host/kernel.go new file mode 100644 index 000000000..ac7277eef --- /dev/null +++ b/pkg/host/kernel.go @@ -0,0 +1,627 @@ +package host + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" + "sigs.k8s.io/controller-runtime/pkg/log" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" +) + +type KernelInterface interface { + // TryEnableTun load the tun kernel module + TryEnableTun() + // TryEnableVhostNet load the vhost-net kernel module + TryEnableVhostNet() + // TryEnableRdma tries to enable RDMA on the machine base on the operating system + // if the package doesn't exist it will also will try to install it + // supported operating systems are RHEL RHCOS and ubuntu + TryEnableRdma() (bool, error) + // TriggerUdevEvent triggers a udev event + TriggerUdevEvent() error + // GetCurrentKernelArgs reads the /proc/cmdline to check the current kernel arguments + GetCurrentKernelArgs() (string, error) + // IsKernelArgsSet check is the requested kernel arguments are set + IsKernelArgsSet(string, string) bool + // Unbind unbinds a virtual function from is current driver + Unbind(string) error + // BindDpdkDriver binds the virtual function to a DPDK driver + BindDpdkDriver(string, string) error + // BindDefaultDriver binds the virtual function to is default driver + BindDefaultDriver(string) error + // HasDriver returns try if the virtual function is bind to a driver + HasDriver(string) (bool, string) + // RebindVfToDefaultDriver rebinds the virtual function to is default driver + RebindVfToDefaultDriver(string) error + // UnbindDriverIfNeeded unbinds the virtual function from a driver if needed + UnbindDriverIfNeeded(string, bool) error + // LoadKernelModule loads a kernel module to the host + LoadKernelModule(name string, args ...string) error + // IsKernelModuleLoaded returns try if the requested kernel module is loaded + IsKernelModuleLoaded(string) (bool, error) + // ReloadDriver reloads a requested driver + ReloadDriver(string) error + // IsKernelLockdownMode returns true if the kernel is in lockdown mode + IsKernelLockdownMode() bool + // IsRHELSystem returns try if the system is a RHEL base + IsRHELSystem() (bool, error) + // IsUbuntuSystem returns try if the system is an ubuntu base + IsUbuntuSystem() (bool, error) + // IsCoreOS returns true if the system is a CoreOS or RHCOS base + IsCoreOS() (bool, error) + // RdmaIsLoaded returns try if RDMA kernel modules are loaded + RdmaIsLoaded() (bool, error) + // EnableRDMA enable RDMA on the system + EnableRDMA(string, string, string) (bool, error) + // InstallRDMA install RDMA packages on the system + InstallRDMA(string) error + // EnableRDMAOnRHELMachine enable RDMA on a RHEL base system + EnableRDMAOnRHELMachine() (bool, error) + // GetOSPrettyName returns OS name + GetOSPrettyName() (string, error) +} + +type kernel struct { + utilsHelper utils.CmdInterface +} + +func newKernelInterface(utilsHelper utils.CmdInterface) KernelInterface { + return &kernel{utilsHelper: utilsHelper} +} + +func (k *kernel) LoadKernelModule(name string, args ...string) error { + log.Log.Info("LoadKernelModule(): try to load kernel module", "name", name, "args", args) + chrootDefinition := utils.GetChrootExtension() + cmdArgs := strings.Join(args, " ") + + // check if the driver is already loaded in to the system + isLoaded, err := k.IsKernelModuleLoaded(name) + if err != nil { + log.Log.Error(err, "LoadKernelModule(): failed to check if kernel module is already loaded", "name", name) + } + if isLoaded { + log.Log.Info("LoadKernelModule(): kernel module already loaded", "name", name) + return nil + } + + _, _, err = k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("%s modprobe %s %s", chrootDefinition, name, cmdArgs)) + if err != nil { + log.Log.Error(err, "LoadKernelModule(): failed to load kernel module with arguments", "name", name, "args", args) + return err + } + return nil +} + +func (k *kernel) IsKernelModuleLoaded(kernelModuleName string) (bool, error) { + log.Log.Info("IsKernelModuleLoaded(): check if kernel module is loaded", "name", kernelModuleName) + chrootDefinition := utils.GetChrootExtension() + + stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("%s lsmod | grep \"^%s\"", chrootDefinition, kernelModuleName)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "IsKernelModuleLoaded(): failed to check if kernel module is loaded", + "name", kernelModuleName, "stderr", stderr) + return false, err + } + log.Log.V(2).Info("IsKernelModuleLoaded():", "stdout", stdout) + if len(stderr) != 0 { + log.Log.Error(err, "IsKernelModuleLoaded(): failed to check if kernel module is loaded", "name", kernelModuleName, "stderr", stderr) + return false, fmt.Errorf(stderr) + } + + if len(stdout) != 0 { + log.Log.Info("IsKernelModuleLoaded(): kernel module already loaded", "name", kernelModuleName) + return true, nil + } + + return false, nil +} + +func (k *kernel) TryEnableTun() { + if err := k.LoadKernelModule("tun"); err != nil { + log.Log.Error(err, "tryEnableTun(): TUN kernel module not loaded") + } +} + +func (k *kernel) TryEnableVhostNet() { + if err := k.LoadKernelModule("vhost_net"); err != nil { + log.Log.Error(err, "tryEnableVhostNet(): VHOST_NET kernel module not loaded") + } +} + +// GetCurrentKernelArgs This retrieves the kernel cmd line arguments +func (k *kernel) GetCurrentKernelArgs() (string, error) { + path := consts.ProcKernelCmdLine + if !vars.UsingSystemdMode { + path = filepath.Join(consts.Host, path) + } + + path = filepath.Join(vars.FilesystemRoot, path) + cmdLine, err := os.ReadFile(path) + if err != nil { + return "", fmt.Errorf("GetCurrentKernelArgs(): Error reading %s: %v", path, err) + } + return string(cmdLine), nil +} + +// IsKernelArgsSet This checks if the kernel cmd line is set properly. Please note that the same key could be repeated +// several times in the kernel cmd line. We can only ensure that the kernel cmd line has the key/val kernel arg that we set. +func (k *kernel) IsKernelArgsSet(cmdLine string, karg string) bool { + elements := strings.Fields(cmdLine) + for _, element := range elements { + if element == karg { + return true + } + } + return false +} + +// Unbind unbind driver for one device +func (k *kernel) Unbind(pciAddr string) error { + log.Log.V(2).Info("Unbind(): unbind device driver for device", "device", pciAddr) + yes, driver := k.HasDriver(pciAddr) + if !yes { + return nil + } + + filePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDrivers, driver, "unbind") + err := os.WriteFile(filePath, []byte(pciAddr), os.ModeAppend) + if err != nil { + log.Log.Error(err, "Unbind(): fail to unbind driver for device", "device", pciAddr) + return err + } + return nil +} + +// BindDpdkDriver bind dpdk driver for one device +// Bind the device given by "pciAddr" to the driver "driver" +func (k *kernel) BindDpdkDriver(pciAddr, driver string) error { + log.Log.V(2).Info("BindDpdkDriver(): bind device to driver", + "device", pciAddr, "driver", driver) + + if yes, d := k.HasDriver(pciAddr); yes { + if driver == d { + log.Log.V(2).Info("BindDpdkDriver(): device already bound to driver", + "device", pciAddr, "driver", driver) + return nil + } + + if err := k.Unbind(pciAddr); err != nil { + return err + } + } + + driverOverridePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "driver_override") + err := os.WriteFile(driverOverridePath, []byte(driver), os.ModeAppend) + if err != nil { + log.Log.Error(err, "BindDpdkDriver(): fail to write driver_override for device", + "device", pciAddr, "driver", driver) + return err + } + bindPath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDrivers, driver, "bind") + err = os.WriteFile(bindPath, []byte(pciAddr), os.ModeAppend) + if err != nil { + log.Log.Error(err, "BindDpdkDriver(): fail to bind driver for device", + "driver", driver, "device", pciAddr) + _, err := os.Readlink(filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "iommu_group")) + if err != nil { + log.Log.Error(err, "Could not read IOMMU group for device", "device", pciAddr) + return fmt.Errorf( + "cannot bind driver %s to device %s, make sure IOMMU is enabled in BIOS. %w", driver, pciAddr, err) + } + return err + } + err = os.WriteFile(driverOverridePath, []byte(""), os.ModeAppend) + if err != nil { + log.Log.Error(err, "BindDpdkDriver(): failed to clear driver_override for device", "device", pciAddr) + return err + } + + return nil +} + +// BindDefaultDriver bind driver for one device +// Bind the device given by "pciAddr" to the default driver +func (k *kernel) BindDefaultDriver(pciAddr string) error { + log.Log.V(2).Info("BindDefaultDriver(): bind device to default driver", "device", pciAddr) + + if yes, d := k.HasDriver(pciAddr); yes { + if !sriovnetworkv1.StringInArray(d, vars.DpdkDrivers) { + log.Log.V(2).Info("BindDefaultDriver(): device already bound to default driver", + "device", pciAddr, "driver", d) + return nil + } + if err := k.Unbind(pciAddr); err != nil { + return err + } + } + + driverOverridePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "driver_override") + err := os.WriteFile(driverOverridePath, []byte("\x00"), os.ModeAppend) + if err != nil { + log.Log.Error(err, "BindDefaultDriver(): failed to write driver_override for device", "device", pciAddr) + return err + } + + pciDriversProbe := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDriversProbe) + err = os.WriteFile(pciDriversProbe, []byte(pciAddr), os.ModeAppend) + if err != nil { + log.Log.Error(err, "BindDefaultDriver(): failed to bind driver for device", "device", pciAddr) + return err + } + + return nil +} + +// Workaround function to handle a case where the vf default driver is stuck and not able to create the vf kernel interface. +// This function unbind the VF from the default driver and try to bind it again +// bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2045087 +func (k *kernel) RebindVfToDefaultDriver(vfAddr string) error { + log.Log.Info("RebindVfToDefaultDriver()", "vf", vfAddr) + if err := k.Unbind(vfAddr); err != nil { + return err + } + if err := k.BindDefaultDriver(vfAddr); err != nil { + log.Log.Error(err, "RebindVfToDefaultDriver(): fail to bind default driver", "device", vfAddr) + return err + } + + log.Log.Info("RebindVfToDefaultDriver(): workaround implemented", "vf", vfAddr) + return nil +} + +func (k *kernel) UnbindDriverIfNeeded(vfAddr string, isRdma bool) error { + if isRdma { + log.Log.Info("UnbindDriverIfNeeded(): unbinding driver", "device", vfAddr) + if err := k.Unbind(vfAddr); err != nil { + return err + } + log.Log.Info("UnbindDriverIfNeeded(): unbounded driver", "device", vfAddr) + } + return nil +} + +func (k *kernel) HasDriver(pciAddr string) (bool, string) { + driver, err := dputils.GetDriverName(pciAddr) + if err != nil { + log.Log.V(2).Info("HasDriver(): device driver is empty for device", "device", pciAddr) + return false, "" + } + log.Log.V(2).Info("HasDriver(): device driver for device", "device", pciAddr, "driver", driver) + return true, driver +} + +func (k *kernel) TryEnableRdma() (bool, error) { + log.Log.V(2).Info("tryEnableRdma()") + chrootDefinition := utils.GetChrootExtension() + + // check if the driver is already loaded in to the system + _, stderr, mlx4Err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx4_en' <(%s lsmod)", chrootDefinition)) + if mlx4Err != nil && len(stderr) != 0 { + log.Log.Error(mlx4Err, "tryEnableRdma(): failed to check for kernel module 'mlx4_en'", "stderr", stderr) + return false, fmt.Errorf(stderr) + } + + _, stderr, mlx5Err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx5_core' <(%s lsmod)", chrootDefinition)) + if mlx5Err != nil && len(stderr) != 0 { + log.Log.Error(mlx5Err, "tryEnableRdma(): failed to check for kernel module 'mlx5_core'", "stderr", stderr) + return false, fmt.Errorf(stderr) + } + + if mlx4Err != nil && mlx5Err != nil { + log.Log.Error(nil, "tryEnableRdma(): no RDMA capable devices") + return false, nil + } + + isRhelSystem, err := k.IsRHELSystem() + if err != nil { + log.Log.Error(err, "tryEnableRdma(): failed to check if the machine is base on RHEL") + return false, err + } + + // RHEL check + if isRhelSystem { + return k.EnableRDMAOnRHELMachine() + } + + isUbuntuSystem, err := k.IsUbuntuSystem() + if err != nil { + log.Log.Error(err, "tryEnableRdma(): failed to check if the machine is base on Ubuntu") + return false, err + } + + if isUbuntuSystem { + return k.EnableRDMAOnUbuntuMachine() + } + + osName, err := k.GetOSPrettyName() + if err != nil { + log.Log.Error(err, "tryEnableRdma(): failed to check OS name") + return false, err + } + + log.Log.Error(nil, "tryEnableRdma(): Unsupported OS", "name", osName) + return false, fmt.Errorf("unable to load RDMA unsupported OS: %s", osName) +} + +func (k *kernel) EnableRDMAOnRHELMachine() (bool, error) { + log.Log.Info("EnableRDMAOnRHELMachine()") + isCoreOsSystem, err := k.IsCoreOS() + if err != nil { + log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if the machine runs CoreOS") + return false, err + } + + // CoreOS check + if isCoreOsSystem { + isRDMALoaded, err := k.RdmaIsLoaded() + if err != nil { + log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded") + return false, err + } + + return isRDMALoaded, nil + } + + // RHEL + log.Log.Info("EnableRDMAOnRHELMachine(): enabling RDMA on RHEL machine") + isRDMAEnable, err := k.EnableRDMA(rhelRDMAConditionFile, rhelRDMAServiceName, rhelPackageManager) + if err != nil { + log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to enable RDMA on RHEL machine") + return false, err + } + + // check if we need to install rdma-core package + if isRDMAEnable { + isRDMALoaded, err := k.RdmaIsLoaded() + if err != nil { + log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded") + return false, err + } + + // if ib kernel module is not loaded trigger a loading + if isRDMALoaded { + err = k.TriggerUdevEvent() + if err != nil { + log.Log.Error(err, "EnableRDMAOnRHELMachine() failed to trigger udev event") + return false, err + } + } + } + + return true, nil +} + +func (k *kernel) EnableRDMAOnUbuntuMachine() (bool, error) { + log.Log.Info("EnableRDMAOnUbuntuMachine(): enabling RDMA on RHEL machine") + isRDMAEnable, err := k.EnableRDMA(ubuntuRDMAConditionFile, ubuntuRDMAServiceName, ubuntuPackageManager) + if err != nil { + log.Log.Error(err, "EnableRDMAOnUbuntuMachine(): failed to enable RDMA on Ubuntu machine") + return false, err + } + + // check if we need to install rdma-core package + if isRDMAEnable { + isRDMALoaded, err := k.RdmaIsLoaded() + if err != nil { + log.Log.Error(err, "EnableRDMAOnUbuntuMachine(): failed to check if RDMA kernel modules are loaded") + return false, err + } + + // if ib kernel module is not loaded trigger a loading + if isRDMALoaded { + err = k.TriggerUdevEvent() + if err != nil { + log.Log.Error(err, "EnableRDMAOnUbuntuMachine() failed to trigger udev event") + return false, err + } + } + } + + return true, nil +} + +func (k *kernel) IsRHELSystem() (bool, error) { + log.Log.Info("IsRHELSystem(): checking for RHEL machine") + path := redhatReleaseFile + if !vars.UsingSystemdMode { + path = filepath.Join(hostPathFromDaemon, path) + } + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + log.Log.V(2).Info("IsRHELSystem() not a RHEL machine") + return false, nil + } + + log.Log.Error(err, "IsRHELSystem() failed to check for os release file", "path", path) + return false, err + } + + return true, nil +} + +func (k *kernel) IsCoreOS() (bool, error) { + log.Log.Info("IsCoreOS(): checking for CoreOS machine") + path := redhatReleaseFile + if !vars.UsingSystemdMode { + path = filepath.Join(hostPathFromDaemon, path) + } + + data, err := os.ReadFile(path) + if err != nil { + log.Log.Error(err, "IsCoreOS(): failed to read RHEL release file on path", "path", path) + return false, err + } + + if strings.Contains(string(data), "CoreOS") { + return true, nil + } + + return false, nil +} + +func (k *kernel) IsUbuntuSystem() (bool, error) { + log.Log.Info("IsUbuntuSystem(): checking for Ubuntu machine") + path := genericOSReleaseFile + if !vars.UsingSystemdMode { + path = filepath.Join(hostPathFromDaemon, path) + } + + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + log.Log.Error(nil, "IsUbuntuSystem() os-release on path doesn't exist", "path", path) + return false, err + } + + log.Log.Error(err, "IsUbuntuSystem() failed to check for os release file", "path", path) + return false, err + } + + stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("grep -i --quiet 'ubuntu' %s", path)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "IsUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file", "stderr", stderr) + return false, fmt.Errorf(stderr) + } + + if len(stdout) > 0 { + return true, nil + } + + return false, nil +} + +func (k *kernel) RdmaIsLoaded() (bool, error) { + log.Log.V(2).Info("RdmaIsLoaded()") + chrootDefinition := utils.GetChrootExtension() + + // check if the driver is already loaded in to the system + _, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("grep --quiet '\\(^ib\\|^rdma\\)' <(%s lsmod)", chrootDefinition)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "RdmaIsLoaded(): fail to check if ib and rdma kernel modules are loaded", "stderr", stderr) + return false, fmt.Errorf(stderr) + } + + if err != nil { + return false, nil + } + + return true, nil +} + +func (k *kernel) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { + path := conditionFilePath + if !vars.UsingSystemdMode { + path = filepath.Join(hostPathFromDaemon, path) + } + log.Log.Info("EnableRDMA(): checking for service file", "path", path) + + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + log.Log.V(2).Info("EnableRDMA(): RDMA server doesn't exist") + err = k.InstallRDMA(packageManager) + if err != nil { + log.Log.Error(err, "EnableRDMA() failed to install RDMA package") + return false, err + } + + err = k.TriggerUdevEvent() + if err != nil { + log.Log.Error(err, "EnableRDMA() failed to trigger udev event") + return false, err + } + + return false, nil + } + + log.Log.Error(err, "EnableRDMA() failed to check for os release file", "path", path) + return false, err + } + + log.Log.Info("EnableRDMA(): service installed", "name", serviceName) + return true, nil +} + +func (k *kernel) InstallRDMA(packageManager string) error { + log.Log.Info("InstallRDMA(): installing RDMA") + chrootDefinition := utils.GetChrootExtension() + + stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("%s %s install -y rdma-core", chrootDefinition, packageManager)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "InstallRDMA(): failed to install RDMA package", "stdout", stdout, "stderr", stderr) + return err + } + + return nil +} + +func (k *kernel) TriggerUdevEvent() error { + log.Log.Info("TriggerUdevEvent(): installing RDMA") + + err := k.ReloadDriver("mlx4_en") + if err != nil { + return err + } + + err = k.ReloadDriver("mlx5_core") + if err != nil { + return err + } + + return nil +} + +func (k *kernel) ReloadDriver(driverName string) error { + log.Log.Info("ReloadDriver(): reload driver", "name", driverName) + chrootDefinition := utils.GetChrootExtension() + + _, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("%s modprobe -r %s && %s modprobe %s", chrootDefinition, driverName, chrootDefinition, driverName)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "InstallRDMA(): failed to reload kernel module", + "name", driverName, "stderr", stderr) + return err + } + + return nil +} + +func (k *kernel) GetOSPrettyName() (string, error) { + path := genericOSReleaseFile + if !vars.UsingSystemdMode { + path = filepath.Join(hostPathFromDaemon, path) + } + + log.Log.Info("GetOSPrettyName(): getting os name from os-release file") + + stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("cat %s | grep PRETTY_NAME | cut -c 13-", path)) + if err != nil && len(stderr) != 0 { + log.Log.Error(err, "IsUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file", "stderr", stderr) + return "", fmt.Errorf(stderr) + } + + if len(stdout) > 0 { + return stdout, nil + } + + return "", fmt.Errorf("failed to find pretty operating system name") +} + +// IsKernelLockdownMode returns true when kernel lockdown mode is enabled +// TODO: change this to return error +func (k *kernel) IsKernelLockdownMode() bool { + path := utils.GetHostExtension() + path = filepath.Join(path, "/sys/kernel/security/lockdown") + + stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", "cat", path) + log.Log.V(2).Info("IsKernelLockdownMode()", "output", stdout, "error", err) + if err != nil { + log.Log.Error(err, "IsKernelLockdownMode(): failed to check for lockdown file", "stderr", stderr) + return false + } + return strings.Contains(stdout, "[integrity]") || strings.Contains(stdout, "[confidentiality]") +} diff --git a/pkg/host/mock/mock_host.go b/pkg/host/mock/mock_host.go deleted file mode 100644 index e09bfd3c8..000000000 --- a/pkg/host/mock/mock_host.go +++ /dev/null @@ -1,254 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: host.go - -// Package mock_host is a generated GoMock package. -package mock_host - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockHostManagerInterface is a mock of HostManagerInterface interface. -type MockHostManagerInterface struct { - ctrl *gomock.Controller - recorder *MockHostManagerInterfaceMockRecorder -} - -// MockHostManagerInterfaceMockRecorder is the mock recorder for MockHostManagerInterface. -type MockHostManagerInterfaceMockRecorder struct { - mock *MockHostManagerInterface -} - -// NewMockHostManagerInterface creates a new mock instance. -func NewMockHostManagerInterface(ctrl *gomock.Controller) *MockHostManagerInterface { - mock := &MockHostManagerInterface{ctrl: ctrl} - mock.recorder = &MockHostManagerInterfaceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockHostManagerInterface) EXPECT() *MockHostManagerInterfaceMockRecorder { - return m.recorder -} - -// EnableRDMA mocks base method. -func (m *MockHostManagerInterface) EnableRDMA(arg0, arg1, arg2 string) (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EnableRDMA", arg0, arg1, arg2) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// EnableRDMA indicates an expected call of EnableRDMA. -func (mr *MockHostManagerInterfaceMockRecorder) EnableRDMA(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMA", reflect.TypeOf((*MockHostManagerInterface)(nil).EnableRDMA), arg0, arg1, arg2) -} - -// EnableRDMAOnRHELMachine mocks base method. -func (m *MockHostManagerInterface) EnableRDMAOnRHELMachine() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EnableRDMAOnRHELMachine") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// EnableRDMAOnRHELMachine indicates an expected call of EnableRDMAOnRHELMachine. -func (mr *MockHostManagerInterfaceMockRecorder) EnableRDMAOnRHELMachine() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMAOnRHELMachine", reflect.TypeOf((*MockHostManagerInterface)(nil).EnableRDMAOnRHELMachine)) -} - -// GetOSPrettyName mocks base method. -func (m *MockHostManagerInterface) GetOSPrettyName() (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetOSPrettyName") - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetOSPrettyName indicates an expected call of GetOSPrettyName. -func (mr *MockHostManagerInterfaceMockRecorder) GetOSPrettyName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOSPrettyName", reflect.TypeOf((*MockHostManagerInterface)(nil).GetOSPrettyName)) -} - -// InstallRDMA mocks base method. -func (m *MockHostManagerInterface) InstallRDMA(arg0 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InstallRDMA", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// InstallRDMA indicates an expected call of InstallRDMA. -func (mr *MockHostManagerInterfaceMockRecorder) InstallRDMA(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallRDMA", reflect.TypeOf((*MockHostManagerInterface)(nil).InstallRDMA), arg0) -} - -// IsCoreOS mocks base method. -func (m *MockHostManagerInterface) IsCoreOS() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsCoreOS") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// IsCoreOS indicates an expected call of IsCoreOS. -func (mr *MockHostManagerInterfaceMockRecorder) IsCoreOS() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCoreOS", reflect.TypeOf((*MockHostManagerInterface)(nil).IsCoreOS)) -} - -// IsKernelModuleLoaded mocks base method. -func (m *MockHostManagerInterface) IsKernelModuleLoaded(arg0 string) (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsKernelModuleLoaded", arg0) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// IsKernelModuleLoaded indicates an expected call of IsKernelModuleLoaded. -func (mr *MockHostManagerInterfaceMockRecorder) IsKernelModuleLoaded(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelModuleLoaded", reflect.TypeOf((*MockHostManagerInterface)(nil).IsKernelModuleLoaded), arg0) -} - -// IsRHELSystem mocks base method. -func (m *MockHostManagerInterface) IsRHELSystem() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsRHELSystem") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// IsRHELSystem indicates an expected call of IsRHELSystem. -func (mr *MockHostManagerInterfaceMockRecorder) IsRHELSystem() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsRHELSystem", reflect.TypeOf((*MockHostManagerInterface)(nil).IsRHELSystem)) -} - -// IsUbuntuSystem mocks base method. -func (m *MockHostManagerInterface) IsUbuntuSystem() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsUbuntuSystem") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// IsUbuntuSystem indicates an expected call of IsUbuntuSystem. -func (mr *MockHostManagerInterfaceMockRecorder) IsUbuntuSystem() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUbuntuSystem", reflect.TypeOf((*MockHostManagerInterface)(nil).IsUbuntuSystem)) -} - -// LoadKernelModule mocks base method. -func (m *MockHostManagerInterface) LoadKernelModule(name string, args ...string) error { - m.ctrl.T.Helper() - varargs := []interface{}{name} - for _, a := range args { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "LoadKernelModule", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// LoadKernelModule indicates an expected call of LoadKernelModule. -func (mr *MockHostManagerInterfaceMockRecorder) LoadKernelModule(name interface{}, args ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{name}, args...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadKernelModule", reflect.TypeOf((*MockHostManagerInterface)(nil).LoadKernelModule), varargs...) -} - -// RdmaIsLoaded mocks base method. -func (m *MockHostManagerInterface) RdmaIsLoaded() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RdmaIsLoaded") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RdmaIsLoaded indicates an expected call of RdmaIsLoaded. -func (mr *MockHostManagerInterfaceMockRecorder) RdmaIsLoaded() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RdmaIsLoaded", reflect.TypeOf((*MockHostManagerInterface)(nil).RdmaIsLoaded)) -} - -// ReloadDriver mocks base method. -func (m *MockHostManagerInterface) ReloadDriver(arg0 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReloadDriver", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// ReloadDriver indicates an expected call of ReloadDriver. -func (mr *MockHostManagerInterfaceMockRecorder) ReloadDriver(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).ReloadDriver), arg0) -} - -// TriggerUdevEvent mocks base method. -func (m *MockHostManagerInterface) TriggerUdevEvent() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TriggerUdevEvent") - ret0, _ := ret[0].(error) - return ret0 -} - -// TriggerUdevEvent indicates an expected call of TriggerUdevEvent. -func (mr *MockHostManagerInterfaceMockRecorder) TriggerUdevEvent() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TriggerUdevEvent", reflect.TypeOf((*MockHostManagerInterface)(nil).TriggerUdevEvent)) -} - -// TryEnableRdma mocks base method. -func (m *MockHostManagerInterface) TryEnableRdma() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TryEnableRdma") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// TryEnableRdma indicates an expected call of TryEnableRdma. -func (mr *MockHostManagerInterfaceMockRecorder) TryEnableRdma() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableRdma", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableRdma)) -} - -// TryEnableTun mocks base method. -func (m *MockHostManagerInterface) TryEnableTun() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "TryEnableTun") -} - -// TryEnableTun indicates an expected call of TryEnableTun. -func (mr *MockHostManagerInterfaceMockRecorder) TryEnableTun() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableTun", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableTun)) -} - -// TryEnableVhostNet mocks base method. -func (m *MockHostManagerInterface) TryEnableVhostNet() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "TryEnableVhostNet") -} - -// TryEnableVhostNet indicates an expected call of TryEnableVhostNet. -func (mr *MockHostManagerInterfaceMockRecorder) TryEnableVhostNet() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableVhostNet", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableVhostNet)) -} diff --git a/pkg/host/mock/mock_store.go b/pkg/host/mock/mock_store.go new file mode 100644 index 000000000..54eae5850 --- /dev/null +++ b/pkg/host/mock/mock_store.go @@ -0,0 +1,108 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: store.go + +// Package mock_host is a generated GoMock package. +package mock_host + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" +) + +// MockStoreManagerInterface is a mock of StoreManagerInterface interface. +type MockStoreManagerInterface struct { + ctrl *gomock.Controller + recorder *MockStoreManagerInterfaceMockRecorder +} + +// MockStoreManagerInterfaceMockRecorder is the mock recorder for MockStoreManagerInterface. +type MockStoreManagerInterfaceMockRecorder struct { + mock *MockStoreManagerInterface +} + +// NewMockStoreManagerInterface creates a new mock instance. +func NewMockStoreManagerInterface(ctrl *gomock.Controller) *MockStoreManagerInterface { + mock := &MockStoreManagerInterface{ctrl: ctrl} + mock.recorder = &MockStoreManagerInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockStoreManagerInterface) EXPECT() *MockStoreManagerInterfaceMockRecorder { + return m.recorder +} + +// ClearPCIAddressFolder mocks base method. +func (m *MockStoreManagerInterface) ClearPCIAddressFolder() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClearPCIAddressFolder") + ret0, _ := ret[0].(error) + return ret0 +} + +// ClearPCIAddressFolder indicates an expected call of ClearPCIAddressFolder. +func (mr *MockStoreManagerInterfaceMockRecorder) ClearPCIAddressFolder() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearPCIAddressFolder", reflect.TypeOf((*MockStoreManagerInterface)(nil).ClearPCIAddressFolder)) +} + +// GetCheckPointNodeState mocks base method. +func (m *MockStoreManagerInterface) GetCheckPointNodeState() (*v1.SriovNetworkNodeState, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCheckPointNodeState") + ret0, _ := ret[0].(*v1.SriovNetworkNodeState) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCheckPointNodeState indicates an expected call of GetCheckPointNodeState. +func (mr *MockStoreManagerInterfaceMockRecorder) GetCheckPointNodeState() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCheckPointNodeState", reflect.TypeOf((*MockStoreManagerInterface)(nil).GetCheckPointNodeState)) +} + +// LoadPfsStatus mocks base method. +func (m *MockStoreManagerInterface) LoadPfsStatus(pciAddress string) (*v1.Interface, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadPfsStatus", pciAddress) + ret0, _ := ret[0].(*v1.Interface) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// LoadPfsStatus indicates an expected call of LoadPfsStatus. +func (mr *MockStoreManagerInterfaceMockRecorder) LoadPfsStatus(pciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPfsStatus", reflect.TypeOf((*MockStoreManagerInterface)(nil).LoadPfsStatus), pciAddress) +} + +// SaveLastPfAppliedStatus mocks base method. +func (m *MockStoreManagerInterface) SaveLastPfAppliedStatus(PfInfo *v1.Interface) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SaveLastPfAppliedStatus", PfInfo) + ret0, _ := ret[0].(error) + return ret0 +} + +// SaveLastPfAppliedStatus indicates an expected call of SaveLastPfAppliedStatus. +func (mr *MockStoreManagerInterfaceMockRecorder) SaveLastPfAppliedStatus(PfInfo interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveLastPfAppliedStatus", reflect.TypeOf((*MockStoreManagerInterface)(nil).SaveLastPfAppliedStatus), PfInfo) +} + +// WriteCheckpointFile mocks base method. +func (m *MockStoreManagerInterface) WriteCheckpointFile(arg0 *v1.SriovNetworkNodeState) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteCheckpointFile", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteCheckpointFile indicates an expected call of WriteCheckpointFile. +func (mr *MockStoreManagerInterfaceMockRecorder) WriteCheckpointFile(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCheckpointFile", reflect.TypeOf((*MockStoreManagerInterface)(nil).WriteCheckpointFile), arg0) +} diff --git a/pkg/host/network.go b/pkg/host/network.go new file mode 100644 index 000000000..14885f6b9 --- /dev/null +++ b/pkg/host/network.go @@ -0,0 +1,215 @@ +package host + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/cenkalti/backoff" + "sigs.k8s.io/controller-runtime/pkg/log" + + dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" +) + +type NetworkInterface interface { + // TryToGetVirtualInterfaceName tries to find the virtio interface name base on pci address + // used for virtual environment where we pass SR-IOV virtual function into the system + // supported platform openstack + TryToGetVirtualInterfaceName(string) string + // TryGetInterfaceName tries to find the SR-IOV virtual interface name base on pci address + TryGetInterfaceName(string) string + // GetPhysSwitchID returns the physical switch ID for a specific pci address + GetPhysSwitchID(string) (string, error) + // GetPhysPortName returns the physical port name for a specific pci address + GetPhysPortName(string) (string, error) + // IsSwitchdev returns true of the pci address is on switchdev mode + IsSwitchdev(string) bool + // GetNetdevMTU returns the interface MTU for devices attached to kernel drivers + GetNetdevMTU(string) int + // SetNetdevMTU sets the MTU for a request interface + SetNetdevMTU(string, int) error + // GetNetDevMac returns the network interface mac address + GetNetDevMac(string) string + // GetNetDevLinkSpeed returns the network interface link speed + GetNetDevLinkSpeed(string) string +} + +type network struct { + utilsHelper utils.CmdInterface +} + +func newNetworkInterface(utilsHelper utils.CmdInterface) NetworkInterface { + return &network{utilsHelper: utilsHelper} +} + +// TryToGetVirtualInterfaceName get the interface name of a virtio interface +func (n *network) TryToGetVirtualInterfaceName(pciAddr string) string { + log.Log.Info("TryToGetVirtualInterfaceName() get interface name for device", "device", pciAddr) + + // To support different driver that is not virtio-pci like mlx + name := n.TryGetInterfaceName(pciAddr) + if name != "" { + return name + } + + netDir, err := filepath.Glob(filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "virtio*", "net")) + if err != nil || len(netDir) < 1 { + return "" + } + + fInfos, err := os.ReadDir(netDir[0]) + if err != nil { + log.Log.Error(err, "TryToGetVirtualInterfaceName(): failed to read net directory", "dir", netDir[0]) + return "" + } + + names := make([]string, 0) + for _, f := range fInfos { + names = append(names, f.Name()) + } + + if len(names) < 1 { + return "" + } + + return names[0] +} + +func (n *network) TryGetInterfaceName(pciAddr string) string { + names, err := dputils.GetNetNames(pciAddr) + if err != nil || len(names) < 1 { + return "" + } + netDevName := names[0] + + // Switchdev PF and their VFs representors are existing under the same PCI address since kernel 5.8 + // if device is switchdev then return PF name + for _, name := range names { + if !n.IsSwitchdev(name) { + continue + } + // Try to get the phys port name, if not exists then fallback to check without it + // phys_port_name should be in formant p e.g p0,p1,p2 ...etc. + if physPortName, err := n.GetPhysPortName(name); err == nil { + if !vars.PfPhysPortNameRe.MatchString(physPortName) { + continue + } + } + return name + } + + log.Log.V(2).Info("tryGetInterfaceName()", "name", netDevName) + return netDevName +} + +func (n *network) GetPhysSwitchID(name string) (string, error) { + swIDFile := filepath.Join(vars.FilesystemRoot, consts.SysClassNet, name, "phys_switch_id") + physSwitchID, err := os.ReadFile(swIDFile) + if err != nil { + return "", err + } + if physSwitchID != nil { + return strings.TrimSpace(string(physSwitchID)), nil + } + return "", nil +} + +func (n *network) GetPhysPortName(name string) (string, error) { + devicePortNameFile := filepath.Join(vars.FilesystemRoot, consts.SysClassNet, name, "phys_port_name") + physPortName, err := os.ReadFile(devicePortNameFile) + if err != nil { + return "", err + } + if physPortName != nil { + return strings.TrimSpace(string(physPortName)), nil + } + return "", nil +} + +func (n *network) IsSwitchdev(name string) bool { + switchID, err := n.GetPhysSwitchID(name) + if err != nil || switchID == "" { + return false + } + + return true +} + +func (n *network) GetNetdevMTU(pciAddr string) int { + log.Log.V(2).Info("GetNetdevMTU(): get MTU", "device", pciAddr) + ifaceName := n.TryGetInterfaceName(pciAddr) + if ifaceName == "" { + return 0 + } + mtuFile := "net/" + ifaceName + "/mtu" + mtuFilePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, mtuFile) + data, err := os.ReadFile(mtuFilePath) + if err != nil { + log.Log.Error(err, "GetNetdevMTU(): fail to read mtu file", "path", mtuFilePath) + return 0 + } + mtu, err := strconv.Atoi(strings.TrimSpace(string(data))) + if err != nil { + log.Log.Error(err, "GetNetdevMTU(): fail to convert mtu to int", "raw-mtu", strings.TrimSpace(string(data))) + return 0 + } + return mtu +} + +func (n *network) SetNetdevMTU(pciAddr string, mtu int) error { + log.Log.V(2).Info("SetNetdevMTU(): set MTU", "device", pciAddr, "mtu", mtu) + if mtu <= 0 { + log.Log.V(2).Info("SetNetdevMTU(): refusing to set MTU", "mtu", mtu) + return nil + } + b := backoff.NewConstantBackOff(1 * time.Second) + err := backoff.Retry(func() error { + ifaceName, err := dputils.GetNetNames(pciAddr) + if err != nil { + log.Log.Error(err, "SetNetdevMTU(): fail to get interface name", "device", pciAddr) + return err + } + if len(ifaceName) < 1 { + return fmt.Errorf("SetNetdevMTU(): interface name is empty") + } + mtuFile := "net/" + ifaceName[0] + "/mtu" + mtuFilePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, mtuFile) + return os.WriteFile(mtuFilePath, []byte(strconv.Itoa(mtu)), os.ModeAppend) + }, backoff.WithMaxRetries(b, 10)) + if err != nil { + log.Log.Error(err, "SetNetdevMTU(): fail to write mtu file after retrying") + return err + } + return nil +} + +func (n *network) GetNetDevMac(ifaceName string) string { + log.Log.V(2).Info("GetNetDevMac(): get Mac", "device", ifaceName) + macFilePath := filepath.Join(vars.FilesystemRoot, consts.SysClassNet, ifaceName, "address") + data, err := os.ReadFile(macFilePath) + if err != nil { + log.Log.Error(err, "GetNetDevMac(): fail to read Mac file", "path", macFilePath) + return "" + } + + return strings.TrimSpace(string(data)) +} + +func (n *network) GetNetDevLinkSpeed(ifaceName string) string { + log.Log.V(2).Info("GetNetDevLinkSpeed(): get LinkSpeed", "device", ifaceName) + speedFilePath := filepath.Join(vars.FilesystemRoot, consts.SysClassNet, ifaceName, "speed") + data, err := os.ReadFile(speedFilePath) + if err != nil { + log.Log.Error(err, "GetNetDevLinkSpeed(): fail to read Link Speed file", "path", speedFilePath) + return "" + } + + return fmt.Sprintf("%s Mb/s", strings.TrimSpace(string(data))) +} diff --git a/pkg/host/service.go b/pkg/host/service.go new file mode 100644 index 000000000..513542e66 --- /dev/null +++ b/pkg/host/service.go @@ -0,0 +1,313 @@ +package host + +import ( + "fmt" + "io" + "os" + "path" + "path/filepath" + "strings" + + "github.com/coreos/go-systemd/v22/unit" + "gopkg.in/yaml.v3" + "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" +) + +// TODO: handle this to support unit-tests +const systemdDir = "/usr/lib/systemd/system/" + +var ( + // Remove run condition form the service + ConditionOpt = &unit.UnitOption{ + Section: "Unit", + Name: "ConditionPathExists", + Value: "!/etc/ignition-machine-config-encapsulated.json", + } +) + +type ServiceInterface interface { + // IsServiceExist checks if the requested systemd service exist on the system + IsServiceExist(string) (bool, error) + // IsServiceEnabled checks if the requested systemd service is enabled on the system + IsServiceEnabled(string) (bool, error) + // ReadService reads a systemd servers and return it as a struct + ReadService(string) (*Service, error) + // EnableService enables a systemd server on the host + EnableService(service *Service) error + // ReadServiceManifestFile reads the systemd manifest for a specific service + ReadServiceManifestFile(path string) (*Service, error) + // RemoveFromService removes a systemd service from the host + RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) + // ReadScriptManifestFile reads the script manifest from a systemd service + ReadScriptManifestFile(path string) (*ScriptManifestFile, error) + // ReadServiceInjectionManifestFile reads the injection manifest file for the systemd service + ReadServiceInjectionManifestFile(path string) (*Service, error) + // CompareServices compare two servers and return true if they are equal + CompareServices(serviceA, serviceB *Service) (bool, error) + // UpdateSystemService updates a system service on the host + UpdateSystemService(serviceObj *Service) error +} + +type service struct { + utilsHelper utils.CmdInterface +} + +func newServiceInterface(utilsHelper utils.CmdInterface) ServiceInterface { + return &service{utilsHelper: utilsHelper} +} + +type Service struct { + Name string + Path string + Content string +} + +// ServiceInjectionManifestFile service injection manifest file structure +type ServiceInjectionManifestFile struct { + Name string + Dropins []struct { + Contents string + } +} + +// ServiceManifestFile service manifest file structure +type ServiceManifestFile struct { + Name string + Contents string +} + +// ScriptManifestFile script manifest file structure +type ScriptManifestFile struct { + Path string + Contents struct { + Inline string + } +} + +// IsServiceExist check if service unit exist +func (s *service) IsServiceExist(servicePath string) (bool, error) { + _, err := os.Stat(path.Join(consts.Chroot, servicePath)) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + + return true, nil +} + +// IsServiceEnabled check if service exist and enabled +func (s *service) IsServiceEnabled(servicePath string) (bool, error) { + exist, err := s.IsServiceExist(servicePath) + if err != nil || !exist { + return false, err + } + serviceName := filepath.Base(servicePath) + // Change root dir + exit, err := s.utilsHelper.Chroot(consts.Chroot) + if err != nil { + return false, err + } + defer exit() + + // TODO: add check for the output and logs + _, _, err = s.utilsHelper.RunCommand("systemctl", "is-enabled", serviceName) + return err == nil, nil +} + +// ReadService read service from given path +func (s *service) ReadService(servicePath string) (*Service, error) { + data, err := os.ReadFile(path.Join(consts.Chroot, servicePath)) + if err != nil { + return nil, err + } + + return &Service{ + Name: filepath.Base(servicePath), + Path: servicePath, + Content: string(data), + }, nil +} + +// EnableService creates service file and enables it with systemctl enable +func (s *service) EnableService(service *Service) error { + // Write service file + err := os.WriteFile(path.Join(consts.Chroot, service.Path), []byte(service.Content), 0644) + if err != nil { + return err + } + + // Change root dir + exit, err := s.utilsHelper.Chroot(consts.Chroot) + if err != nil { + return err + } + defer exit() + + // Enable service + _, _, err = s.utilsHelper.RunCommand("systemctl", "enable", service.Name) + return err +} + +// CompareServices compare 2 service and return true if serviceA has all the fields of serviceB +func (s *service) CompareServices(serviceA, serviceB *Service) (bool, error) { + optsA, err := unit.Deserialize(strings.NewReader(serviceA.Content)) + if err != nil { + return false, err + } + optsB, err := unit.Deserialize(strings.NewReader(serviceB.Content)) + if err != nil { + return false, err + } + +OUTER: + for _, optB := range optsB { + for _, optA := range optsA { + if optA.Match(optB) { + continue OUTER + } + } + log.Log.V(2).Info("CompareServices", "ServiceA", optsA, "ServiceB", *optB) + return true, nil + } + + return false, nil +} + +// RemoveFromService removes given fields from service +func (s *service) RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) { + opts, err := unit.Deserialize(strings.NewReader(service.Content)) + if err != nil { + return nil, err + } + + var newServiceOptions []*unit.UnitOption +OUTER: + for _, opt := range opts { + for _, optRemove := range options { + if opt.Match(optRemove) { + continue OUTER + } + } + + newServiceOptions = append(newServiceOptions, opt) + } + + data, err := io.ReadAll(unit.Serialize(newServiceOptions)) + if err != nil { + return nil, err + } + + return &Service{ + Name: service.Name, + Path: service.Path, + Content: string(data), + }, nil +} + +// ReadServiceInjectionManifestFile reads service injection file +func (s *service) ReadServiceInjectionManifestFile(path string) (*Service, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + var serviceContent ServiceInjectionManifestFile + if err := yaml.Unmarshal(data, &serviceContent); err != nil { + return nil, err + } + + return &Service{ + Name: serviceContent.Name, + Path: systemdDir + serviceContent.Name, + Content: serviceContent.Dropins[0].Contents, + }, nil +} + +// ReadServiceManifestFile reads service file +func (s *service) ReadServiceManifestFile(path string) (*Service, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + var serviceFile *ServiceManifestFile + if err := yaml.Unmarshal(data, &serviceFile); err != nil { + return nil, err + } + + return &Service{ + Name: serviceFile.Name, + Path: "/etc/systemd/system/" + serviceFile.Name, + Content: serviceFile.Contents, + }, nil +} + +// ReadScriptManifestFile reads script file +func (s *service) ReadScriptManifestFile(path string) (*ScriptManifestFile, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + var scriptFile *ScriptManifestFile + if err := yaml.Unmarshal(data, &scriptFile); err != nil { + return nil, err + } + + return scriptFile, nil +} + +func (s *service) UpdateSystemService(serviceObj *Service) error { + systemService, err := s.ReadService(serviceObj.Path) + if err != nil { + return err + } + if systemService == nil { + // Invalid case to reach here + return fmt.Errorf("can't update non-existing service %q", serviceObj.Name) + } + serviceOptions, err := unit.Deserialize(strings.NewReader(serviceObj.Content)) + if err != nil { + return err + } + updatedService, err := appendToService(systemService, serviceOptions...) + if err != nil { + return err + } + + return s.EnableService(updatedService) +} + +// appendToService appends given fields to service +func appendToService(service *Service, options ...*unit.UnitOption) (*Service, error) { + serviceOptions, err := unit.Deserialize(strings.NewReader(service.Content)) + if err != nil { + return nil, err + } + +OUTER: + for _, appendOpt := range options { + for _, opt := range serviceOptions { + if opt.Match(appendOpt) { + continue OUTER + } + } + serviceOptions = append(serviceOptions, appendOpt) + } + + data, err := io.ReadAll(unit.Serialize(serviceOptions)) + if err != nil { + return nil, err + } + + return &Service{ + Name: service.Name, + Path: service.Path, + Content: string(data), + }, nil +} diff --git a/pkg/host/sriov.go b/pkg/host/sriov.go new file mode 100644 index 000000000..7d6343771 --- /dev/null +++ b/pkg/host/sriov.go @@ -0,0 +1,629 @@ +package host + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + "github.com/jaypipes/ghw" + "github.com/vishvananda/netlink" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/controller-runtime/pkg/log" + + dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" +) + +type SriovInterface interface { + // SetSriovNumVfs changes the number of virtual functions allocated for a specific + // physical function base on pci address + SetSriovNumVfs(string, int) error + // GetVfInfo returns the virtual function information is the operator struct from the host information + GetVfInfo(string, []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction + // SetVfGUID sets the GUID for a virtual function + SetVfGUID(string, netlink.Link) error + // VFIsReady returns the interface virtual function if the device is ready + VFIsReady(string) (netlink.Link, error) + // SetVfAdminMac sets the virtual function administrative mac address via the physical function + SetVfAdminMac(string, netlink.Link, netlink.Link) error + // GetNicSriovMode returns the interface mode + // supported modes SR-IOV legacy and switchdev + GetNicSriovMode(string) (string, error) + // GetLinkType return the link type + // supported types are ethernet and infiniband + GetLinkType(sriovnetworkv1.InterfaceExt) string + // ResetSriovDevice resets the number of virtual function for the specific physical function to zero + ResetSriovDevice(sriovnetworkv1.InterfaceExt) error + // DiscoverSriovDevices returns a list of all the available SR-IOV capable network interfaces on the system + DiscoverSriovDevices(StoreManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) + // ConfigSriovDevice configure the request SR-IOV device with the desired configuration + ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error + // ConfigSriovInterfaces configure multiple SR-IOV devices with the desired configuration + ConfigSriovInterfaces(StoreManagerInterface, []sriovnetworkv1.Interface, []sriovnetworkv1.InterfaceExt, map[string]bool) error + // ConfigSriovInterfaces configure virtual functions for virtual environments with the desired configuration + ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error +} + +type sriov struct { + utilsHelper utils.CmdInterface + kernelHelper KernelInterface + networkHelper NetworkInterface + udevHelper UdevInterface +} + +func newSriovInterface(utilsHelper utils.CmdInterface, + kernelHelper KernelInterface, + networkHelper NetworkInterface, + udevHelper UdevInterface) SriovInterface { + return &sriov{utilsHelper: utilsHelper, kernelHelper: kernelHelper, networkHelper: networkHelper, udevHelper: udevHelper} +} + +func (s *sriov) SetSriovNumVfs(pciAddr string, numVfs int) error { + log.Log.V(2).Info("SetSriovNumVfs(): set NumVfs", "device", pciAddr, "numVfs", numVfs) + numVfsFilePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, consts.NumVfsFile) + bs := []byte(strconv.Itoa(numVfs)) + err := os.WriteFile(numVfsFilePath, []byte("0"), os.ModeAppend) + if err != nil { + log.Log.Error(err, "SetSriovNumVfs(): fail to reset NumVfs file", "path", numVfsFilePath) + return err + } + err = os.WriteFile(numVfsFilePath, bs, os.ModeAppend) + if err != nil { + log.Log.Error(err, "SetSriovNumVfs(): fail to set NumVfs file", "path", numVfsFilePath) + return err + } + return nil +} + +func (s *sriov) ResetSriovDevice(ifaceStatus sriovnetworkv1.InterfaceExt) error { + log.Log.V(2).Info("ResetSriovDevice(): reset SRIOV device", "address", ifaceStatus.PciAddress) + if err := s.SetSriovNumVfs(ifaceStatus.PciAddress, 0); err != nil { + return err + } + if ifaceStatus.LinkType == consts.LinkTypeETH { + var mtu int + is := sriovnetworkv1.InitialState.GetInterfaceStateByPciAddress(ifaceStatus.PciAddress) + if is != nil { + mtu = is.Mtu + } else { + mtu = 1500 + } + log.Log.V(2).Info("ResetSriovDevice(): reset mtu", "value", mtu) + if err := s.networkHelper.SetNetdevMTU(ifaceStatus.PciAddress, mtu); err != nil { + return err + } + } else if ifaceStatus.LinkType == consts.LinkTypeIB { + if err := s.networkHelper.SetNetdevMTU(ifaceStatus.PciAddress, 2048); err != nil { + return err + } + } + return nil +} + +func (s *sriov) GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction { + driver, err := dputils.GetDriverName(pciAddr) + if err != nil { + log.Log.Error(err, "getVfInfo(): unable to parse device driver", "device", pciAddr) + } + id, err := dputils.GetVFID(pciAddr) + if err != nil { + log.Log.Error(err, "getVfInfo(): unable to get VF index", "device", pciAddr) + } + vf := sriovnetworkv1.VirtualFunction{ + PciAddress: pciAddr, + Driver: driver, + VfID: id, + } + + if mtu := s.networkHelper.GetNetdevMTU(pciAddr); mtu > 0 { + vf.Mtu = mtu + } + if name := s.networkHelper.TryGetInterfaceName(pciAddr); name != "" { + vf.Name = name + vf.Mac = s.networkHelper.GetNetDevMac(name) + } + + for _, device := range devices { + if pciAddr == device.Address { + vf.Vendor = device.Vendor.ID + vf.DeviceID = device.Product.ID + break + } + continue + } + return vf +} + +func (s *sriov) SetVfGUID(vfAddr string, pfLink netlink.Link) error { + log.Log.Info("SetVfGUID()", "vf", vfAddr) + vfID, err := dputils.GetVFID(vfAddr) + if err != nil { + log.Log.Error(err, "SetVfGUID(): unable to get VF id", "address", vfAddr) + return err + } + guid := utils.GenerateRandomGUID() + if err := netlink.LinkSetVfNodeGUID(pfLink, vfID, guid); err != nil { + return err + } + if err := netlink.LinkSetVfPortGUID(pfLink, vfID, guid); err != nil { + return err + } + if err = s.kernelHelper.Unbind(vfAddr); err != nil { + return err + } + + return nil +} + +func (s *sriov) VFIsReady(pciAddr string) (netlink.Link, error) { + log.Log.Info("VFIsReady()", "device", pciAddr) + var err error + var vfLink netlink.Link + err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { + vfName := s.networkHelper.TryGetInterfaceName(pciAddr) + vfLink, err = netlink.LinkByName(vfName) + if err != nil { + log.Log.Error(err, "VFIsReady(): unable to get VF link", "device", pciAddr) + } + return err == nil, nil + }) + if err != nil { + return vfLink, err + } + return vfLink, nil +} + +func (s *sriov) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error { + log.Log.Info("SetVfAdminMac()", "vf", vfAddr) + + vfID, err := dputils.GetVFID(vfAddr) + if err != nil { + log.Log.Error(err, "SetVfAdminMac(): unable to get VF id", "address", vfAddr) + return err + } + + if err := netlink.LinkSetVfHardwareAddr(pfLink, vfID, vfLink.Attrs().HardwareAddr); err != nil { + return err + } + + return nil +} + +func (s *sriov) DiscoverSriovDevices(storeManager StoreManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) { + log.Log.V(2).Info("DiscoverSriovDevices") + pfList := []sriovnetworkv1.InterfaceExt{} + + pci, err := ghw.PCI() + if err != nil { + return nil, fmt.Errorf("DiscoverSriovDevices(): error getting PCI info: %v", err) + } + + devices := pci.ListDevices() + if len(devices) == 0 { + return nil, fmt.Errorf("DiscoverSriovDevices(): could not retrieve PCI devices") + } + + for _, device := range devices { + devClass, err := strconv.ParseInt(device.Class.ID, 16, 64) + if err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): unable to parse device class, skipping", + "device", device) + continue + } + if devClass != consts.NetClass { + // Not network device + continue + } + + // TODO: exclude devices used by host system + + if dputils.IsSriovVF(device.Address) { + continue + } + + driver, err := dputils.GetDriverName(device.Address) + if err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): unable to parse device driver for device, skipping", "device", device) + continue + } + + deviceNames, err := dputils.GetNetNames(device.Address) + if err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): unable to get device names for device, skipping", "device", device) + continue + } + + if len(deviceNames) == 0 { + // no network devices found, skipping device + continue + } + + if !vars.DevMode { + if !sriovnetworkv1.IsSupportedModel(device.Vendor.ID, device.Product.ID) { + log.Log.Info("DiscoverSriovDevices(): unsupported device", "device", device) + continue + } + } + + iface := sriovnetworkv1.InterfaceExt{ + PciAddress: device.Address, + Driver: driver, + Vendor: device.Vendor.ID, + DeviceID: device.Product.ID, + } + if mtu := s.networkHelper.GetNetdevMTU(device.Address); mtu > 0 { + iface.Mtu = mtu + } + if name := s.networkHelper.TryGetInterfaceName(device.Address); name != "" { + iface.Name = name + iface.Mac = s.networkHelper.GetNetDevMac(name) + iface.LinkSpeed = s.networkHelper.GetNetDevLinkSpeed(name) + } + iface.LinkType = s.GetLinkType(iface) + + pfStatus, exist, err := storeManager.LoadPfsStatus(iface.PciAddress) + if err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): failed to load PF status from disk") + } else { + if exist { + iface.ExternallyManaged = pfStatus.ExternallyManaged + } + } + + if dputils.IsSriovPF(device.Address) { + iface.TotalVfs = dputils.GetSriovVFcapacity(device.Address) + iface.NumVfs = dputils.GetVFconfigured(device.Address) + if iface.EswitchMode, err = s.GetNicSriovMode(device.Address); err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): warning, unable to get device eswitch mode", + "device", device.Address) + } + if dputils.SriovConfigured(device.Address) { + vfs, err := dputils.GetVFList(device.Address) + if err != nil { + log.Log.Error(err, "DiscoverSriovDevices(): unable to parse VFs for device, skipping", + "device", device) + continue + } + for _, vf := range vfs { + instance := s.GetVfInfo(vf, devices) + iface.VFs = append(iface.VFs, instance) + } + } + } + pfList = append(pfList, iface) + } + + return pfList, nil +} + +func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error { + log.Log.V(2).Info("configSriovDevice(): configure sriov device", + "device", iface.PciAddress, "config", iface) + var err error + if iface.NumVfs > ifaceStatus.TotalVfs { + err := fmt.Errorf("cannot config SRIOV device: NumVfs (%d) is larger than TotalVfs (%d)", iface.NumVfs, ifaceStatus.TotalVfs) + log.Log.Error(err, "configSriovDevice(): fail to set NumVfs for device", "device", iface.PciAddress) + return err + } + // set numVFs + if iface.NumVfs != ifaceStatus.NumVfs { + if iface.ExternallyManaged { + if iface.NumVfs > ifaceStatus.NumVfs { + errMsg := fmt.Sprintf("configSriovDevice(): number of request virtual functions %d is not equal to configured virtual functions %d but the policy is configured as ExternallyManaged for device %s", iface.NumVfs, ifaceStatus.NumVfs, iface.PciAddress) + log.Log.Error(nil, errMsg) + return fmt.Errorf(errMsg) + } + } else { + // create the udev rule to disable all the vfs from network manager as this vfs are managed by the operator + err = s.udevHelper.AddUdevRule(iface.PciAddress) + if err != nil { + return err + } + + err = s.SetSriovNumVfs(iface.PciAddress, iface.NumVfs) + if err != nil { + log.Log.Error(err, "configSriovDevice(): fail to set NumVfs for device", "device", iface.PciAddress) + errRemove := s.udevHelper.RemoveUdevRule(iface.PciAddress) + if errRemove != nil { + log.Log.Error(errRemove, "configSriovDevice(): fail to remove udev rule", "device", iface.PciAddress) + } + return err + } + } + } + // set PF mtu + if iface.Mtu > 0 && iface.Mtu > ifaceStatus.Mtu { + err = s.networkHelper.SetNetdevMTU(iface.PciAddress, iface.Mtu) + if err != nil { + log.Log.Error(err, "configSriovDevice(): fail to set mtu for PF", "device", iface.PciAddress) + return err + } + } + // Config VFs + if iface.NumVfs > 0 { + vfAddrs, err := dputils.GetVFList(iface.PciAddress) + if err != nil { + log.Log.Error(err, "configSriovDevice(): unable to parse VFs for device", "device", iface.PciAddress) + } + pfLink, err := netlink.LinkByName(iface.Name) + if err != nil { + log.Log.Error(err, "configSriovDevice(): unable to get PF link for device", "device", iface) + return err + } + + for _, addr := range vfAddrs { + var group *sriovnetworkv1.VfGroup + + vfID, err := dputils.GetVFID(addr) + if err != nil { + log.Log.Error(err, "configSriovDevice(): unable to get VF id", "device", iface.PciAddress) + return err + } + + for i := range iface.VfGroups { + if sriovnetworkv1.IndexInRange(vfID, iface.VfGroups[i].VfRange) { + group = &iface.VfGroups[i] + break + } + } + + // VF group not found. + if group == nil { + continue + } + + // only set GUID and MAC for VF with default driver + // for userspace drivers like vfio we configure the vf mac using the kernel nic mac address + // before we switch to the userspace driver + if yes, d := s.kernelHelper.HasDriver(addr); yes && !sriovnetworkv1.StringInArray(d, vars.DpdkDrivers) { + // LinkType is an optional field. Let's fallback to current link type + // if nothing is specified in the SriovNodePolicy + linkType := iface.LinkType + if linkType == "" { + linkType = ifaceStatus.LinkType + } + if strings.EqualFold(linkType, consts.LinkTypeIB) { + if err = s.SetVfGUID(addr, pfLink); err != nil { + return err + } + } else { + vfLink, err := s.VFIsReady(addr) + if err != nil { + log.Log.Error(err, "configSriovDevice(): VF link is not ready", "address", addr) + err = s.kernelHelper.RebindVfToDefaultDriver(addr) + if err != nil { + log.Log.Error(err, "configSriovDevice(): failed to rebind VF", "address", addr) + return err + } + + // Try to check the VF status again + vfLink, err = s.VFIsReady(addr) + if err != nil { + log.Log.Error(err, "configSriovDevice(): VF link is not ready", "address", addr) + return err + } + } + if err = s.SetVfAdminMac(addr, pfLink, vfLink); err != nil { + log.Log.Error(err, "configSriovDevice(): fail to configure VF admin mac", "device", addr) + return err + } + } + } + + if err = s.kernelHelper.UnbindDriverIfNeeded(addr, group.IsRdma); err != nil { + return err + } + + if !sriovnetworkv1.StringInArray(group.DeviceType, vars.DpdkDrivers) { + if err := s.kernelHelper.BindDefaultDriver(addr); err != nil { + log.Log.Error(err, "configSriovDevice(): fail to bind default driver for device", "device", addr) + return err + } + // only set MTU for VF with default driver + if group.Mtu > 0 { + if err := s.networkHelper.SetNetdevMTU(addr, group.Mtu); err != nil { + log.Log.Error(err, "configSriovDevice(): fail to set mtu for VF", "address", addr) + return err + } + } + } else { + if err := s.kernelHelper.BindDpdkDriver(addr, group.DeviceType); err != nil { + log.Log.Error(err, "configSriovDevice(): fail to bind driver for device", + "driver", group.DeviceType, "device", addr) + return err + } + } + } + } + // Set PF link up + pfLink, err := netlink.LinkByName(ifaceStatus.Name) + if err != nil { + return err + } + if pfLink.Attrs().OperState != netlink.OperUp { + err = netlink.LinkSetUp(pfLink) + if err != nil { + return err + } + } + return nil +} + +func (s *sriov) ConfigSriovInterfaces(storeManager StoreManagerInterface, interfaces []sriovnetworkv1.Interface, ifaceStatuses []sriovnetworkv1.InterfaceExt, pfsToConfig map[string]bool) error { + if s.kernelHelper.IsKernelLockdownMode() && mlx.HasMellanoxInterfacesInSpec(ifaceStatuses, interfaces) { + log.Log.Error(nil, "cannot use mellanox devices when in kernel lockdown mode") + return fmt.Errorf("cannot use mellanox devices when in kernel lockdown mode") + } + + for _, ifaceStatus := range ifaceStatuses { + configured := false + for _, iface := range interfaces { + if iface.PciAddress == ifaceStatus.PciAddress { + configured = true + + if skip := pfsToConfig[iface.PciAddress]; skip { + break + } + + if !sriovnetworkv1.NeedToUpdateSriov(&iface, &ifaceStatus) { + log.Log.V(2).Info("syncNodeState(): no need update interface", "address", iface.PciAddress) + + // Save the PF status to the host + err := storeManager.SaveLastPfAppliedStatus(&iface) + if err != nil { + log.Log.Error(err, "SyncNodeState(): failed to save PF applied config to host") + return err + } + + break + } + if err := s.ConfigSriovDevice(&iface, &ifaceStatus); err != nil { + log.Log.Error(err, "SyncNodeState(): fail to configure sriov interface. resetting interface.", "address", iface.PciAddress) + if iface.ExternallyManaged { + log.Log.Info("SyncNodeState(): skipping device reset as the nic is marked as externally created") + } else { + if resetErr := s.ResetSriovDevice(ifaceStatus); resetErr != nil { + log.Log.Error(resetErr, "SyncNodeState(): failed to reset on error SR-IOV interface") + } + } + return err + } + + // Save the PF status to the host + err := storeManager.SaveLastPfAppliedStatus(&iface) + if err != nil { + log.Log.Error(err, "SyncNodeState(): failed to save PF applied config to host") + return err + } + break + } + } + if !configured && ifaceStatus.NumVfs > 0 { + if skip := pfsToConfig[ifaceStatus.PciAddress]; skip { + continue + } + + // load the PF info + pfStatus, exist, err := storeManager.LoadPfsStatus(ifaceStatus.PciAddress) + if err != nil { + log.Log.Error(err, "SyncNodeState(): failed to load info about PF status for device", + "address", ifaceStatus.PciAddress) + return err + } + + if !exist { + log.Log.Info("SyncNodeState(): PF name with pci address has VFs configured but they weren't created by the sriov operator. Skipping the device reset", + "pf-name", ifaceStatus.Name, + "address", ifaceStatus.PciAddress) + continue + } + + if pfStatus.ExternallyManaged { + log.Log.Info("SyncNodeState(): PF name with pci address was externally created skipping the device reset", + "pf-name", ifaceStatus.Name, + "address", ifaceStatus.PciAddress) + continue + } else { + err = s.udevHelper.RemoveUdevRule(ifaceStatus.PciAddress) + if err != nil { + return err + } + } + + if err = s.ResetSriovDevice(ifaceStatus); err != nil { + return err + } + } + } + return nil +} + +func (s *sriov) ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error { + log.Log.V(2).Info("ConfigSriovDeviceVirtual(): config interface", "address", iface.PciAddress, "config", iface) + // Config VFs + if iface.NumVfs > 0 { + if iface.NumVfs > 1 { + log.Log.Error(nil, "ConfigSriovDeviceVirtual(): in a virtual environment, only one VF per interface", + "numVfs", iface.NumVfs) + return errors.New("NumVfs > 1") + } + if len(iface.VfGroups) != 1 { + log.Log.Error(nil, "ConfigSriovDeviceVirtual(): missing VFGroup") + return errors.New("NumVfs != 1") + } + addr := iface.PciAddress + log.Log.V(2).Info("ConfigSriovDeviceVirtual()", "address", addr) + driver := "" + vfID := 0 + for _, group := range iface.VfGroups { + log.Log.V(2).Info("ConfigSriovDeviceVirtual()", "group", group) + if sriovnetworkv1.IndexInRange(vfID, group.VfRange) { + log.Log.V(2).Info("ConfigSriovDeviceVirtual()", "indexInRange", vfID) + if sriovnetworkv1.StringInArray(group.DeviceType, vars.DpdkDrivers) { + log.Log.V(2).Info("ConfigSriovDeviceVirtual()", "driver", group.DeviceType) + driver = group.DeviceType + } + break + } + } + if driver == "" { + log.Log.V(2).Info("ConfigSriovDeviceVirtual(): bind default") + if err := s.kernelHelper.BindDefaultDriver(addr); err != nil { + log.Log.Error(err, "ConfigSriovDeviceVirtual(): fail to bind default driver", "device", addr) + return err + } + } else { + log.Log.V(2).Info("ConfigSriovDeviceVirtual(): bind driver", "driver", driver) + if err := s.kernelHelper.BindDpdkDriver(addr, driver); err != nil { + log.Log.Error(err, "ConfigSriovDeviceVirtual(): fail to bind driver for device", + "driver", driver, "device", addr) + return err + } + } + } + return nil +} + +func (s *sriov) GetNicSriovMode(pciAddress string) (string, error) { + log.Log.V(2).Info("GetNicSriovMode()", "device", pciAddress) + + devLink, err := netlink.DevLinkGetDeviceByName("pci", pciAddress) + if err != nil { + if errors.Is(err, syscall.ENODEV) { + // the device doesn't support devlink + return "", nil + } + return "", err + } + + return devLink.Attrs.Eswitch.Mode, nil +} + +func (s *sriov) GetLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string { + log.Log.V(2).Info("GetLinkType()", "device", ifaceStatus.PciAddress) + if ifaceStatus.Name != "" { + link, err := netlink.LinkByName(ifaceStatus.Name) + if err != nil { + log.Log.Error(err, "GetLinkType(): failed to get link", "device", ifaceStatus.Name) + return "" + } + linkType := link.Attrs().EncapType + if linkType == "ether" { + return consts.LinkTypeETH + } else if linkType == "infiniband" { + return consts.LinkTypeIB + } + } + + return "" +} diff --git a/pkg/utils/store.go b/pkg/host/store.go similarity index 55% rename from pkg/utils/store.go rename to pkg/host/store.go index dd1b44626..1bced8c9d 100644 --- a/pkg/utils/store.go +++ b/pkg/host/store.go @@ -1,20 +1,17 @@ -package utils +package host import ( "encoding/json" "fmt" "os" - "path" "path/filepath" "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" -) - -const ( - SriovConfBasePath = "/etc/sriov-operator" - PfAppliedConfig = SriovConfBasePath + "/pci" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // Contains all the file storing on the host @@ -24,27 +21,29 @@ type StoreManagerInterface interface { ClearPCIAddressFolder() error SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) + + GetCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNodeState, error) + WriteCheckpointFile(*sriovnetworkv1.SriovNetworkNodeState) error } -type StoreManager struct { - RunOnHost bool +type storeManager struct { } // NewStoreManager: create the initial folders needed to store the info about the PF // and return a storeManager struct that implements the StoreManagerInterface interface -func NewStoreManager(runOnHost bool) (StoreManagerInterface, error) { - if err := createOperatorConfigFolderIfNeeded(runOnHost); err != nil { +func NewStoreManager() (StoreManagerInterface, error) { + if err := createOperatorConfigFolderIfNeeded(); err != nil { return nil, err } - return &StoreManager{runOnHost}, nil + return &storeManager{}, nil } // createOperatorConfigFolderIfNeeded: create the operator base folder on the host // together with the pci folder to save the PF status objects as json files -func createOperatorConfigFolderIfNeeded(runOnHost bool) error { - hostExtension := getHostExtension(runOnHost) - SriovConfBasePathUse := filepath.Join(hostExtension, SriovConfBasePath) +func createOperatorConfigFolderIfNeeded() error { + hostExtension := utils.GetHostExtension() + SriovConfBasePathUse := filepath.Join(hostExtension, consts.SriovConfBasePath) _, err := os.Stat(SriovConfBasePathUse) if err != nil { if os.IsNotExist(err) { @@ -57,7 +56,7 @@ func createOperatorConfigFolderIfNeeded(runOnHost bool) error { } } - PfAppliedConfigUse := filepath.Join(hostExtension, PfAppliedConfig) + PfAppliedConfigUse := filepath.Join(hostExtension, consts.PfAppliedConfig) _, err = os.Stat(PfAppliedConfigUse) if err != nil { if os.IsNotExist(err) { @@ -74,9 +73,9 @@ func createOperatorConfigFolderIfNeeded(runOnHost bool) error { } // ClearPCIAddressFolder: removes all the PFs storage information -func (s *StoreManager) ClearPCIAddressFolder() error { - hostExtension := getHostExtension(s.RunOnHost) - PfAppliedConfigUse := filepath.Join(hostExtension, PfAppliedConfig) +func (s *storeManager) ClearPCIAddressFolder() error { + hostExtension := utils.GetHostExtension() + PfAppliedConfigUse := filepath.Join(hostExtension, consts.PfAppliedConfig) _, err := os.Stat(PfAppliedConfigUse) if err != nil { if os.IsNotExist(err) { @@ -100,24 +99,24 @@ func (s *StoreManager) ClearPCIAddressFolder() error { // SaveLastPfAppliedStatus will save the PF object as a json into the /etc/sriov-operator/pci/ // this function must be called after running the chroot function -func (s *StoreManager) SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error { +func (s *storeManager) SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error { data, err := json.Marshal(PfInfo) if err != nil { log.Log.Error(err, "failed to marshal PF status", "status", *PfInfo) return err } - hostExtension := getHostExtension(s.RunOnHost) - pathFile := filepath.Join(hostExtension, PfAppliedConfig, PfInfo.PciAddress) + hostExtension := utils.GetHostExtension() + pathFile := filepath.Join(hostExtension, consts.PfAppliedConfig, PfInfo.PciAddress) err = os.WriteFile(pathFile, data, 0644) return err } // LoadPfsStatus convert the /etc/sriov-operator/pci/ json to pfstatus // returns false if the file doesn't exist. -func (s *StoreManager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) { - hostExtension := getHostExtension(s.RunOnHost) - pathFile := filepath.Join(hostExtension, PfAppliedConfig, pciAddress) +func (s *storeManager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) { + hostExtension := utils.GetHostExtension() + pathFile := filepath.Join(hostExtension, consts.PfAppliedConfig, pciAddress) pfStatus := &sriovnetworkv1.Interface{} data, err := os.ReadFile(pathFile) if err != nil { @@ -137,9 +136,45 @@ func (s *StoreManager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interfa return pfStatus, true, nil } -func getHostExtension(runOnHost bool) string { - if !runOnHost { - return path.Join(FilesystemRoot, "/host") +func (s *storeManager) GetCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNodeState, error) { + log.Log.Info("getCheckPointNodeState()") + configdir := filepath.Join(vars.Destdir, consts.CheckpointFileName) + file, err := os.OpenFile(configdir, os.O_RDONLY, 0644) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + defer file.Close() + if err = json.NewDecoder(file).Decode(&sriovnetworkv1.InitialState); err != nil { + return nil, err + } + + return &sriovnetworkv1.InitialState, nil +} + +func (s *storeManager) WriteCheckpointFile(ns *sriovnetworkv1.SriovNetworkNodeState) error { + configdir := filepath.Join(vars.Destdir, consts.CheckpointFileName) + file, err := os.OpenFile(configdir, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + return err } - return FilesystemRoot + defer file.Close() + log.Log.Info("WriteCheckpointFile(): try to decode the checkpoint file") + if err = json.NewDecoder(file).Decode(&sriovnetworkv1.InitialState); err != nil { + log.Log.V(2).Error(err, "WriteCheckpointFile(): fail to decode, writing new file instead") + log.Log.Info("WriteCheckpointFile(): write checkpoint file") + if err = file.Truncate(0); err != nil { + return err + } + if _, err = file.Seek(0, 0); err != nil { + return err + } + if err = json.NewEncoder(file).Encode(*ns); err != nil { + return err + } + sriovnetworkv1.InitialState = *ns + } + return nil } diff --git a/pkg/host/udev.go b/pkg/host/udev.go new file mode 100644 index 000000000..5f4daee58 --- /dev/null +++ b/pkg/host/udev.go @@ -0,0 +1,190 @@ +package host + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path" + "path/filepath" + "strings" + + "sigs.k8s.io/controller-runtime/pkg/log" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" +) + +type UdevInterface interface { + // WriteSwitchdevConfFile writes the needed switchdev configuration files for HW offload support + WriteSwitchdevConfFile(*sriovnetworkv1.SriovNetworkNodeState, map[string]bool) (bool, error) + // PrepareNMUdevRule creates the needed udev rules to disable NetworkManager from + // our managed SR-IOV virtual functions + PrepareNMUdevRule([]string) error + // AddUdevRule adds a specific udev rule to the system + AddUdevRule(string) error + // RemoveUdevRule removes a udev rule from the system + RemoveUdevRule(string) error +} + +type udev struct { + utilsHelper utils.CmdInterface +} + +func newUdevInterface(utilsHelper utils.CmdInterface) UdevInterface { + return &udev{utilsHelper: utilsHelper} +} + +type config struct { + Interfaces []sriovnetworkv1.Interface `json:"interfaces"` +} + +func (u *udev) PrepareNMUdevRule(supportedVfIds []string) error { + log.Log.V(2).Info("PrepareNMUdevRule()") + filePath := filepath.Join(vars.FilesystemRoot, consts.HostUdevRulesFolder, "10-nm-unmanaged.rules") + + // remove the old unmanaged rules file + if _, err := os.Stat(filePath); err == nil { + err = os.Remove(filePath) + if err != nil { + log.Log.Error(err, "failed to remove the network manager global unmanaged rule", + "path", filePath) + } + } + + // create the pf finder script for udev rules + stdout, stderr, err := u.utilsHelper.RunCommand("/bin/bash", filepath.Join(vars.FilesystemRoot, consts.UdevDisableNM)) + if err != nil { + log.Log.Error(err, "PrepareNMUdevRule(): failed to prepare nmUdevRule", "stderr", stderr) + return err + } + log.Log.V(2).Info("PrepareNMUdevRule()", "stdout", stdout) + + //save the device list to use for udev rules + vars.SupportedVfIds = supportedVfIds + return nil +} + +func (u *udev) WriteSwitchdevConfFile(newState *sriovnetworkv1.SriovNetworkNodeState, pfsToSkip map[string]bool) (bool, error) { + cfg := config{} + for _, iface := range newState.Spec.Interfaces { + for _, ifaceStatus := range newState.Status.Interfaces { + if iface.PciAddress != ifaceStatus.PciAddress { + continue + } + + if skip := pfsToSkip[iface.PciAddress]; !skip { + continue + } + + if iface.NumVfs > 0 { + var vfGroups []sriovnetworkv1.VfGroup = nil + ifc, err := sriovnetworkv1.FindInterface(newState.Spec.Interfaces, iface.Name) + if err != nil { + log.Log.Error(err, "WriteSwitchdevConfFile(): fail find interface") + } else { + vfGroups = ifc.VfGroups + } + i := sriovnetworkv1.Interface{ + // Not passing all the contents, since only NumVfs and EswitchMode can be configured by configure-switchdev.sh currently. + Name: iface.Name, + PciAddress: iface.PciAddress, + NumVfs: iface.NumVfs, + Mtu: iface.Mtu, + VfGroups: vfGroups, + } + + if iface.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { + i.EswitchMode = iface.EswitchMode + } + cfg.Interfaces = append(cfg.Interfaces, i) + } + } + } + _, err := os.Stat(consts.SriovHostSwitchDevConfPath) + if err != nil { + if os.IsNotExist(err) { + if len(cfg.Interfaces) == 0 { + return false, nil + } + + // TODO: refactor this function to allow using vars.FilesystemRoot for unit-tests + // Create the sriov-operator folder on the host if it doesn't exist + if _, err := os.Stat(consts.Host + consts.SriovConfBasePath); os.IsNotExist(err) { + err = os.Mkdir(consts.Host+consts.SriovConfBasePath, os.ModeDir) + if err != nil { + log.Log.Error(err, "WriteConfFile(): failed to create sriov-operator folder") + return false, err + } + } + + log.Log.V(2).Info("WriteSwitchdevConfFile(): file not existed, create it") + _, err = os.Create(consts.SriovHostSwitchDevConfPath) + if err != nil { + log.Log.Error(err, "WriteSwitchdevConfFile(): failed to create file") + return false, err + } + } else { + return false, err + } + } + oldContent, err := os.ReadFile(consts.SriovHostSwitchDevConfPath) + if err != nil { + log.Log.Error(err, "WriteSwitchdevConfFile(): failed to read file") + return false, err + } + var newContent []byte + if len(cfg.Interfaces) != 0 { + newContent, err = json.Marshal(cfg) + if err != nil { + log.Log.Error(err, "WriteSwitchdevConfFile(): fail to marshal config") + return false, err + } + } + + if bytes.Equal(newContent, oldContent) { + log.Log.V(2).Info("WriteSwitchdevConfFile(): no update") + return false, nil + } + log.Log.V(2).Info("WriteSwitchdevConfFile(): write to switchdev.conf", "content", newContent) + err = os.WriteFile(consts.SriovHostSwitchDevConfPath, newContent, 0644) + if err != nil { + log.Log.Error(err, "WriteSwitchdevConfFile(): failed to write file") + return false, err + } + return true, nil +} + +func (u *udev) AddUdevRule(pfPciAddress string) error { + log.Log.V(2).Info("AddUdevRule()", "device", pfPciAddress) + pathFile := filepath.Join(vars.FilesystemRoot, consts.UdevRulesFolder) + udevRuleContent := fmt.Sprintf(consts.NMUdevRule, strings.Join(vars.SupportedVfIds, "|"), pfPciAddress) + + err := os.MkdirAll(pathFile, os.ModePerm) + if err != nil && !os.IsExist(err) { + log.Log.Error(err, "AddUdevRule(): failed to create dir", "path", pathFile) + return err + } + + filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) + // if the file does not exist or if oldContent != newContent + // write to file and create it if it doesn't exist + err = os.WriteFile(filePath, []byte(udevRuleContent), 0666) + if err != nil { + log.Log.Error(err, "AddUdevRule(): fail to write file", "path", filePath) + return err + } + return nil +} + +func (u *udev) RemoveUdevRule(pfPciAddress string) error { + pathFile := filepath.Join(vars.FilesystemRoot, consts.UdevRulesFolder) + filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) + err := os.Remove(filePath) + if err != nil && !os.IsNotExist(err) { + return err + } + return nil +} diff --git a/pkg/service/service.go b/pkg/service/service.go deleted file mode 100644 index 671d2e20a..000000000 --- a/pkg/service/service.go +++ /dev/null @@ -1,15 +0,0 @@ -package service - -type Service struct { - Name string - Path string - Content string -} - -func NewService(name, path, content string) *Service { - return &Service{ - Name: name, - Path: path, - Content: content, - } -} diff --git a/pkg/service/service_manager.go b/pkg/service/service_manager.go deleted file mode 100644 index 29653fe10..000000000 --- a/pkg/service/service_manager.go +++ /dev/null @@ -1,94 +0,0 @@ -package service - -import ( - "os" - "os/exec" - "path" - "path/filepath" - - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" -) - -type ServiceManager interface { - IsServiceExist(string) (bool, error) - IsServiceEnabled(string) (bool, error) - ReadService(string) (*Service, error) - EnableService(service *Service) error -} - -type serviceManager struct { - chroot string -} - -func NewServiceManager(chroot string) ServiceManager { - root := chroot - if root == "" { - root = "/" - } - return &serviceManager{root} -} - -// IsServiceExist check if service unit exist -func (sm *serviceManager) IsServiceExist(servicePath string) (bool, error) { - _, err := os.Stat(path.Join(sm.chroot, servicePath)) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - - return true, nil -} - -// IsServiceEnabled check if service exist and enabled -func (sm *serviceManager) IsServiceEnabled(servicePath string) (bool, error) { - exist, err := sm.IsServiceExist(servicePath) - if err != nil || !exist { - return false, err - } - serviceName := filepath.Base(servicePath) - // Change root dir - exit, err := utils.Chroot(sm.chroot) - if err != nil { - return false, err - } - defer exit() - - cmd := exec.Command("systemctl", "is-enabled", serviceName) - return cmd.Run() == nil, nil -} - -// ReadService read service from given path -func (sm *serviceManager) ReadService(servicePath string) (*Service, error) { - data, err := os.ReadFile(path.Join(sm.chroot, servicePath)) - if err != nil { - return nil, err - } - - return &Service{ - Name: filepath.Base(servicePath), - Path: servicePath, - Content: string(data), - }, nil -} - -// EnableService creates service file and enables it with systemctl enable -func (sm *serviceManager) EnableService(service *Service) error { - // Write service file - err := os.WriteFile(path.Join(sm.chroot, service.Path), []byte(service.Content), 0644) - if err != nil { - return err - } - - // Change root dir - exit, err := utils.Chroot(sm.chroot) - if err != nil { - return err - } - defer exit() - - // Enable service - cmd := exec.Command("systemctl", "enable", service.Name) - return cmd.Run() -} diff --git a/pkg/service/types.go b/pkg/service/types.go deleted file mode 100644 index aaa879a4d..000000000 --- a/pkg/service/types.go +++ /dev/null @@ -1,23 +0,0 @@ -package service - -// ServiceInjectionManifestFile service injection manifest file structure -type ServiceInjectionManifestFile struct { - Name string - Dropins []struct { - Contents string - } -} - -// ServiceManifestFile service manifest file structure -type ServiceManifestFile struct { - Name string - Contents string -} - -// ScriptManifestFile script manifest file structure -type ScriptManifestFile struct { - Path string - Contents struct { - Inline string - } -} diff --git a/pkg/service/utils.go b/pkg/service/utils.go deleted file mode 100644 index 4abeae553..000000000 --- a/pkg/service/utils.go +++ /dev/null @@ -1,151 +0,0 @@ -package service - -import ( - "io" - "os" - "strings" - - "github.com/coreos/go-systemd/v22/unit" - "gopkg.in/yaml.v2" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -const systemdDir = "/usr/lib/systemd/system/" - -// CompareServices compare 2 service and return true if serviceA has all the fields of serviceB -func CompareServices(serviceA, serviceB *Service) (bool, error) { - optsA, err := unit.Deserialize(strings.NewReader(serviceA.Content)) - if err != nil { - return false, err - } - optsB, err := unit.Deserialize(strings.NewReader(serviceB.Content)) - if err != nil { - return false, err - } - -OUTER: - for _, optB := range optsB { - for _, optA := range optsA { - if optA.Match(optB) { - continue OUTER - } - } - log.Log.V(2).Info("CompareServices", "ServiceA", optsA, "ServiceB", *optB) - return true, nil - } - - return false, nil -} - -// RemoveFromService removes given fields from service -func RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) { - opts, err := unit.Deserialize(strings.NewReader(service.Content)) - if err != nil { - return nil, err - } - - var newServiceOptions []*unit.UnitOption -OUTER: - for _, opt := range opts { - for _, optRemove := range options { - if opt.Match(optRemove) { - continue OUTER - } - } - - newServiceOptions = append(newServiceOptions, opt) - } - - data, err := io.ReadAll(unit.Serialize(newServiceOptions)) - if err != nil { - return nil, err - } - - return &Service{ - Name: service.Name, - Path: service.Path, - Content: string(data), - }, nil -} - -// AppendToService appends given fields to service -func AppendToService(service *Service, options ...*unit.UnitOption) (*Service, error) { - serviceOptions, err := unit.Deserialize(strings.NewReader(service.Content)) - if err != nil { - return nil, err - } - -OUTER: - for _, appendOpt := range options { - for _, opt := range serviceOptions { - if opt.Match(appendOpt) { - continue OUTER - } - } - serviceOptions = append(serviceOptions, appendOpt) - } - - data, err := io.ReadAll(unit.Serialize(serviceOptions)) - if err != nil { - return nil, err - } - - return &Service{ - Name: service.Name, - Path: service.Path, - Content: string(data), - }, nil -} - -// ReadServiceInjectionManifestFile reads service injection file -func ReadServiceInjectionManifestFile(path string) (*Service, error) { - data, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var serviceContent ServiceInjectionManifestFile - if err := yaml.Unmarshal(data, &serviceContent); err != nil { - return nil, err - } - - return &Service{ - Name: serviceContent.Name, - Path: systemdDir + serviceContent.Name, - Content: serviceContent.Dropins[0].Contents, - }, nil -} - -// ReadServiceManifestFile reads service file -func ReadServiceManifestFile(path string) (*Service, error) { - data, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var serviceFile *ServiceManifestFile - if err := yaml.Unmarshal(data, &serviceFile); err != nil { - return nil, err - } - - return &Service{ - Name: serviceFile.Name, - Path: "/etc/systemd/system/" + serviceFile.Name, - Content: serviceFile.Contents, - }, nil -} - -// ReadScriptManifestFile reads script file -func ReadScriptManifestFile(path string) (*ScriptManifestFile, error) { - data, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var scriptFile *ScriptManifestFile - if err := yaml.Unmarshal(data, &scriptFile); err != nil { - return nil, err - } - - return scriptFile, nil -} diff --git a/pkg/utils/cluster.go b/pkg/utils/cluster.go index 610bab415..13310347f 100644 --- a/pkg/utils/cluster.go +++ b/pkg/utils/cluster.go @@ -11,6 +11,8 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" ) const ( @@ -35,7 +37,7 @@ func getNodeRole(node corev1.Node) string { } func IsSingleNodeCluster(c client.Client) (bool, error) { - if os.Getenv("CLUSTER_TYPE") == ClusterTypeOpenshift { + if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeOpenshift { topo, err := openshiftControlPlaneTopologyStatus(c) if err != nil { return false, err @@ -53,7 +55,7 @@ func IsSingleNodeCluster(c client.Client) (bool, error) { // On kubernetes, it is determined by which node the sriov operator is scheduled on. If operator // pod is schedule on worker node, it is considered as external control plane. func IsExternalControlPlaneCluster(c client.Client) (bool, error) { - if os.Getenv("CLUSTER_TYPE") == ClusterTypeOpenshift { + if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeOpenshift { topo, err := openshiftControlPlaneTopologyStatus(c) if err != nil { return false, err @@ -61,7 +63,7 @@ func IsExternalControlPlaneCluster(c client.Client) (bool, error) { if topo == "External" { return true, nil } - } else if os.Getenv("CLUSTER_TYPE") == ClusterTypeKubernetes { + } else if os.Getenv("CLUSTER_TYPE") == consts.ClusterTypeKubernetes { role, err := operatorNodeRole(c) if err != nil { return false, err diff --git a/pkg/utils/command.go b/pkg/utils/command.go deleted file mode 100644 index 085cf5881..000000000 --- a/pkg/utils/command.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package utils - -import ( - "bytes" - "os/exec" -) - -// Interface to run commands -// -//go:generate ../../bin/mockgen -destination mock/mock_command.go -source command.go -type CommandInterface interface { - Run(string, ...string) (stdout bytes.Buffer, stderr bytes.Buffer, err error) -} - -type Command struct { -} - -func (c *Command) Run(name string, args ...string) (stdout bytes.Buffer, stderr bytes.Buffer, err error) { - var stdoutbuff, stderrbuff bytes.Buffer - cmd := exec.Command(name, args...) - cmd.Stdout = &stdoutbuff - cmd.Stderr = &stderrbuff - - err = cmd.Run() - return -} diff --git a/pkg/utils/driver.go b/pkg/utils/driver.go deleted file mode 100644 index c91c6448e..000000000 --- a/pkg/utils/driver.go +++ /dev/null @@ -1,119 +0,0 @@ -package utils - -import ( - "fmt" - "os" - "path/filepath" - - dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" - "sigs.k8s.io/controller-runtime/pkg/log" - - sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" -) - -var DpdkDrivers = []string{"igb_uio", "vfio-pci", "uio_pci_generic"} - -// Unbind unbind driver for one device -func Unbind(pciAddr string) error { - log.Log.V(2).Info("Unbind(): unbind device driver for device", "device", pciAddr) - yes, driver := hasDriver(pciAddr) - if !yes { - return nil - } - - filePath := filepath.Join(sysBusPciDrivers, driver, "unbind") - err := os.WriteFile(filePath, []byte(pciAddr), os.ModeAppend) - if err != nil { - log.Log.Error(err, "Unbind(): fail to unbind driver for device", "device", pciAddr) - return err - } - return nil -} - -// BindDpdkDriver bind dpdk driver for one device -// Bind the device given by "pciAddr" to the driver "driver" -func BindDpdkDriver(pciAddr, driver string) error { - log.Log.V(2).Info("BindDpdkDriver(): bind device to driver", - "device", pciAddr, "driver", driver) - - if yes, d := hasDriver(pciAddr); yes { - if driver == d { - log.Log.V(2).Info("BindDpdkDriver(): device already bound to driver", - "device", pciAddr, "driver", driver) - return nil - } - - if err := Unbind(pciAddr); err != nil { - return err - } - } - - driverOverridePath := filepath.Join(sysBusPciDevices, pciAddr, "driver_override") - err := os.WriteFile(driverOverridePath, []byte(driver), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): fail to write driver_override for device", - "device", pciAddr, "driver", driver) - return err - } - bindPath := filepath.Join(sysBusPciDrivers, driver, "bind") - err = os.WriteFile(bindPath, []byte(pciAddr), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): fail to bind driver for device", - "driver", driver, "device", pciAddr) - _, err := os.Readlink(filepath.Join(sysBusPciDevices, pciAddr, "iommu_group")) - if err != nil { - log.Log.Error(err, "Could not read IOMMU group for device", "device", pciAddr) - return fmt.Errorf( - "cannot bind driver %s to device %s, make sure IOMMU is enabled in BIOS. %w", driver, pciAddr, err) - } - return err - } - err = os.WriteFile(driverOverridePath, []byte(""), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): failed to clear driver_override for device", "device", pciAddr) - return err - } - - return nil -} - -// BindDefaultDriver bind driver for one device -// Bind the device given by "pciAddr" to the default driver -func BindDefaultDriver(pciAddr string) error { - log.Log.V(2).Info("BindDefaultDriver(): bind device to default driver", "device", pciAddr) - - if yes, d := hasDriver(pciAddr); yes { - if !sriovnetworkv1.StringInArray(d, DpdkDrivers) { - log.Log.V(2).Info("BindDefaultDriver(): device already bound to default driver", - "device", pciAddr, "driver", d) - return nil - } - if err := Unbind(pciAddr); err != nil { - return err - } - } - - driverOverridePath := filepath.Join(sysBusPciDevices, pciAddr, "driver_override") - err := os.WriteFile(driverOverridePath, []byte("\x00"), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDefaultDriver(): failed to write driver_override for device", "device", pciAddr) - return err - } - err = os.WriteFile(sysBusPciDriversProbe, []byte(pciAddr), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDefaultDriver(): failed to bind driver for device", "device", pciAddr) - return err - } - - return nil -} - -func hasDriver(pciAddr string) (bool, string) { - driver, err := dputils.GetDriverName(pciAddr) - if err != nil { - log.Log.V(2).Info("hasDriver(): device driver is empty for device", "device", pciAddr) - return false, "" - } - log.Log.V(2).Info("hasDriver(): device driver for device", "device", pciAddr, "driver", driver) - return true, driver -} diff --git a/pkg/utils/mock/mock_utils.go b/pkg/utils/mock/mock_utils.go new file mode 100644 index 000000000..636c7f4a1 --- /dev/null +++ b/pkg/utils/mock/mock_utils.go @@ -0,0 +1,70 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: utils.go + +// Package mock_utils is a generated GoMock package. +package mock_utils + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockCmdInterface is a mock of CmdInterface interface. +type MockCmdInterface struct { + ctrl *gomock.Controller + recorder *MockCmdInterfaceMockRecorder +} + +// MockCmdInterfaceMockRecorder is the mock recorder for MockCmdInterface. +type MockCmdInterfaceMockRecorder struct { + mock *MockCmdInterface +} + +// NewMockCmdInterface creates a new mock instance. +func NewMockCmdInterface(ctrl *gomock.Controller) *MockCmdInterface { + mock := &MockCmdInterface{ctrl: ctrl} + mock.recorder = &MockCmdInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCmdInterface) EXPECT() *MockCmdInterfaceMockRecorder { + return m.recorder +} + +// Chroot mocks base method. +func (m *MockCmdInterface) Chroot(arg0 string) (func() error, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Chroot", arg0) + ret0, _ := ret[0].(func() error) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Chroot indicates an expected call of Chroot. +func (mr *MockCmdInterfaceMockRecorder) Chroot(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Chroot", reflect.TypeOf((*MockCmdInterface)(nil).Chroot), arg0) +} + +// RunCommand mocks base method. +func (m *MockCmdInterface) RunCommand(arg0 string, arg1 ...string) (string, string, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RunCommand", varargs...) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// RunCommand indicates an expected call of RunCommand. +func (mr *MockCmdInterfaceMockRecorder) RunCommand(arg0 interface{}, arg1 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunCommand", reflect.TypeOf((*MockCmdInterface)(nil).RunCommand), varargs...) +} diff --git a/pkg/utils/shutdown.go b/pkg/utils/shutdown.go index 3700efa18..208e2073c 100644 --- a/pkg/utils/shutdown.go +++ b/pkg/utils/shutdown.go @@ -11,7 +11,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" ) var shutdownLog = ctrl.Log.WithName("shutdown") @@ -68,7 +68,7 @@ func updateWebhooks() { func updateValidatingWebhook(c *kubernetes.Clientset) { validatingWebhookClient := c.AdmissionregistrationV1().ValidatingWebhookConfigurations() - webhook, err := validatingWebhookClient.Get(context.TODO(), constants.OperatorWebHookName, metav1.GetOptions{}) + webhook, err := validatingWebhookClient.Get(context.TODO(), consts.OperatorWebHookName, metav1.GetOptions{}) if err != nil { shutdownLog.Error(err, "Error getting webhook") } @@ -81,7 +81,7 @@ func updateValidatingWebhook(c *kubernetes.Clientset) { func updateMutatingWebhooks(c *kubernetes.Clientset) { mutatingWebhookClient := c.AdmissionregistrationV1().MutatingWebhookConfigurations() - for _, name := range []string{constants.OperatorWebHookName, constants.InjectorWebHookName} { + for _, name := range []string{consts.OperatorWebHookName, consts.InjectorWebHookName} { mutatingWebhook, err := mutatingWebhookClient.Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { shutdownLog.Error(err, "Error getting webhook") diff --git a/pkg/utils/sriov.go b/pkg/utils/sriov.go deleted file mode 100644 index f0668494f..000000000 --- a/pkg/utils/sriov.go +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright 2021. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package utils - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - - "sigs.k8s.io/controller-runtime/pkg/log" - - sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" -) - -const ( - SriovSwitchDevConfPath = SriovConfBasePath + "/sriov_config.json" - SriovHostSwitchDevConfPath = "/host" + SriovSwitchDevConfPath -) - -type config struct { - Interfaces []sriovnetworkv1.Interface `json:"interfaces"` -} - -func IsSwitchdevModeSpec(spec sriovnetworkv1.SriovNetworkNodeStateSpec) bool { - for _, iface := range spec.Interfaces { - if iface.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { - return true - } - } - return false -} - -func findInterface(interfaces sriovnetworkv1.Interfaces, name string) (iface sriovnetworkv1.Interface, err error) { - for _, i := range interfaces { - if i.Name == name { - return i, nil - } - } - return sriovnetworkv1.Interface{}, fmt.Errorf("unable to find interface: %v", name) -} - -func WriteSwitchdevConfFile(newState *sriovnetworkv1.SriovNetworkNodeState) (update bool, err error) { - // Create a map with all the PFs we will need to SKIP for systemd configuration - pfsToSkip, err := GetPfsToSkip(newState) - if err != nil { - return false, err - } - cfg := config{} - for _, iface := range newState.Spec.Interfaces { - for _, ifaceStatus := range newState.Status.Interfaces { - if iface.PciAddress != ifaceStatus.PciAddress { - continue - } - - if skip := pfsToSkip[iface.PciAddress]; !skip { - continue - } - - i := sriovnetworkv1.Interface{} - if iface.NumVfs > 0 { - var vfGroups []sriovnetworkv1.VfGroup = nil - ifc, err := findInterface(newState.Spec.Interfaces, iface.Name) - if err != nil { - log.Log.Error(err, "WriteSwitchdevConfFile(): fail find interface") - } else { - vfGroups = ifc.VfGroups - } - i = sriovnetworkv1.Interface{ - // Not passing all the contents, since only NumVfs and EswitchMode can be configured by configure-switchdev.sh currently. - Name: iface.Name, - PciAddress: iface.PciAddress, - NumVfs: iface.NumVfs, - Mtu: iface.Mtu, - VfGroups: vfGroups, - } - - if iface.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { - i.EswitchMode = iface.EswitchMode - } - cfg.Interfaces = append(cfg.Interfaces, i) - } - } - } - _, err = os.Stat(SriovHostSwitchDevConfPath) - if err != nil { - if os.IsNotExist(err) { - if len(cfg.Interfaces) == 0 { - err = nil - return - } - - // Create the sriov-operator folder on the host if it doesn't exist - if _, err := os.Stat("/host" + SriovConfBasePath); os.IsNotExist(err) { - err = os.Mkdir("/host"+SriovConfBasePath, os.ModeDir) - if err != nil { - log.Log.Error(err, "WriteConfFile(): failed to create sriov-operator folder") - return false, err - } - } - - log.Log.V(2).Info("WriteSwitchdevConfFile(): file not existed, create it") - _, err = os.Create(SriovHostSwitchDevConfPath) - if err != nil { - log.Log.Error(err, "WriteSwitchdevConfFile(): failed to create file") - return - } - } else { - return - } - } - oldContent, err := os.ReadFile(SriovHostSwitchDevConfPath) - if err != nil { - log.Log.Error(err, "WriteSwitchdevConfFile(): failed to read file") - return - } - var newContent []byte - if len(cfg.Interfaces) != 0 { - newContent, err = json.Marshal(cfg) - if err != nil { - log.Log.Error(err, "WriteSwitchdevConfFile(): fail to marshal config") - return - } - } - - if bytes.Equal(newContent, oldContent) { - log.Log.V(2).Info("WriteSwitchdevConfFile(): no update") - return - } - update = true - log.Log.V(2).Info("WriteSwitchdevConfFile(): write to switchdev.conf", "content", newContent) - err = os.WriteFile(SriovHostSwitchDevConfPath, newContent, 0644) - if err != nil { - log.Log.Error(err, "WriteSwitchdevConfFile(): failed to write file") - return - } - return -} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 9452bce41..3a0bbdc4c 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -2,741 +2,38 @@ package utils import ( "bytes" - "errors" + "encoding/hex" "fmt" + "hash/fnv" "math/rand" "net" "os" "os/exec" - "path" "path/filepath" - "regexp" - "strconv" - "strings" - "syscall" - "time" - - "encoding/hex" - "hash/fnv" "sort" + "syscall" corev1 "k8s.io/api/core/v1" - - "github.com/cenkalti/backoff" - "github.com/jaypipes/ghw" - "github.com/vishvananda/netlink" - "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/log" - dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" - - sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) -const ( - sysBusPciDevices = "/sys/bus/pci/devices" - sysBusPciDrivers = "/sys/bus/pci/drivers" - sysBusPciDriversProbe = "/sys/bus/pci/drivers_probe" - sysClassNet = "/sys/class/net" - procKernelCmdLine = "/proc/cmdline" - netClass = 0x02 - numVfsFile = "sriov_numvfs" - - ClusterTypeOpenshift = "openshift" - ClusterTypeKubernetes = "kubernetes" - VendorMellanox = "15b3" - DeviceBF2 = "a2d6" - DeviceBF3 = "a2dc" - - udevFolder = "/etc/udev" - udevRulesFolder = udevFolder + "/rules.d" - udevDisableNM = "/bindata/scripts/udev-find-sriov-pf.sh" - nmUdevRule = "SUBSYSTEM==\"net\", ACTION==\"add|change|move\", ATTRS{device}==\"%s\", IMPORT{program}=\"/etc/udev/disable-nm-sriov.sh $env{INTERFACE} %s\"" - - KernelArgPciRealloc = "pci=realloc" - KernelArgIntelIommu = "intel_iommu=on" - KernelArgIommuPt = "iommu=pt" -) - -var InitialState sriovnetworkv1.SriovNetworkNodeState -var ClusterType string - -var pfPhysPortNameRe = regexp.MustCompile(`p\d+`) - -// FilesystemRoot used by test to mock interactions with filesystem -var FilesystemRoot = "" - -var SupportedVfIds []string - -func init() { - ClusterType = os.Getenv("CLUSTER_TYPE") -} - -// GetCurrentKernelArgs This retrieves the kernel cmd line arguments -func GetCurrentKernelArgs(chroot bool) (string, error) { - path := procKernelCmdLine - if !chroot { - path = "/host" + path - } - cmdLine, err := os.ReadFile(path) - if err != nil { - return "", fmt.Errorf("GetCurrentKernelArgs(): Error reading %s: %v", procKernelCmdLine, err) - } - return string(cmdLine), nil -} - -// IsKernelArgsSet This checks if the kernel cmd line is set properly. Please note that the same key could be repeated -// several times in the kernel cmd line. We can only ensure that the kernel cmd line has the key/val kernel arg that we set. -func IsKernelArgsSet(cmdLine string, karg string) bool { - elements := strings.Fields(cmdLine) - for _, element := range elements { - if element == karg { - return true - } - } - return false -} - -func DiscoverSriovDevices(withUnsupported bool, storeManager StoreManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) { - log.Log.V(2).Info("DiscoverSriovDevices") - pfList := []sriovnetworkv1.InterfaceExt{} - - pci, err := ghw.PCI() - if err != nil { - return nil, fmt.Errorf("DiscoverSriovDevices(): error getting PCI info: %v", err) - } - - devices := pci.ListDevices() - if len(devices) == 0 { - return nil, fmt.Errorf("DiscoverSriovDevices(): could not retrieve PCI devices") - } - - for _, device := range devices { - devClass, err := strconv.ParseInt(device.Class.ID, 16, 64) - if err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): unable to parse device class, skipping", - "device", device) - continue - } - if devClass != netClass { - // Not network device - continue - } - - // TODO: exclude devices used by host system - - if dputils.IsSriovVF(device.Address) { - continue - } - - driver, err := dputils.GetDriverName(device.Address) - if err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): unable to parse device driver for device, skipping", "device", device) - continue - } - - deviceNames, err := dputils.GetNetNames(device.Address) - if err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): unable to get device names for device, skipping", "device", device) - continue - } - - if len(deviceNames) == 0 { - // no network devices found, skipping device - continue - } - - if !withUnsupported { - if !sriovnetworkv1.IsSupportedModel(device.Vendor.ID, device.Product.ID) { - log.Log.Info("DiscoverSriovDevices(): unsupported device", "device", device) - continue - } - } - - iface := sriovnetworkv1.InterfaceExt{ - PciAddress: device.Address, - Driver: driver, - Vendor: device.Vendor.ID, - DeviceID: device.Product.ID, - } - if mtu := getNetdevMTU(device.Address); mtu > 0 { - iface.Mtu = mtu - } - if name := tryGetInterfaceName(device.Address); name != "" { - iface.Name = name - iface.Mac = getNetDevMac(name) - iface.LinkSpeed = getNetDevLinkSpeed(name) - } - iface.LinkType = getLinkType(iface) - - pfStatus, exist, err := storeManager.LoadPfsStatus(iface.PciAddress) - if err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): failed to load PF status from disk") - } else { - if exist { - iface.ExternallyManaged = pfStatus.ExternallyManaged - } - } - - if dputils.IsSriovPF(device.Address) { - iface.TotalVfs = dputils.GetSriovVFcapacity(device.Address) - iface.NumVfs = dputils.GetVFconfigured(device.Address) - if iface.EswitchMode, err = GetNicSriovMode(device.Address); err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): warning, unable to get device eswitch mode", - "device", device.Address) - } - if dputils.SriovConfigured(device.Address) { - vfs, err := dputils.GetVFList(device.Address) - if err != nil { - log.Log.Error(err, "DiscoverSriovDevices(): unable to parse VFs for device, skipping", - "device", device) - continue - } - for _, vf := range vfs { - instance := getVfInfo(vf, devices) - iface.VFs = append(iface.VFs, instance) - } - } - } - pfList = append(pfList, iface) - } - - return pfList, nil -} - -// SyncNodeState Attempt to update the node state to match the desired state -func SyncNodeState(newState *sriovnetworkv1.SriovNetworkNodeState, pfsToConfig map[string]bool) error { - return ConfigSriovInterfaces(newState.Spec.Interfaces, newState.Status.Interfaces, pfsToConfig) -} - -func ConfigSriovInterfaces(interfaces []sriovnetworkv1.Interface, ifaceStatuses []sriovnetworkv1.InterfaceExt, pfsToConfig map[string]bool) error { - if IsKernelLockdownMode(true) && hasMellanoxInterfacesInSpec(ifaceStatuses, interfaces) { - log.Log.Error(nil, "cannot use mellanox devices when in kernel lockdown mode") - return fmt.Errorf("cannot use mellanox devices when in kernel lockdown mode") - } - - // we are already inside chroot, so we initialize the store as running on host - storeManager, err := NewStoreManager(true) - if err != nil { - return fmt.Errorf("SyncNodeState(): error initializing storeManager: %v", err) - } - - for _, ifaceStatus := range ifaceStatuses { - configured := false - for _, iface := range interfaces { - if iface.PciAddress == ifaceStatus.PciAddress { - configured = true - - if skip := pfsToConfig[iface.PciAddress]; skip { - break - } - - if !NeedUpdate(&iface, &ifaceStatus) { - log.Log.V(2).Info("syncNodeState(): no need update interface", "address", iface.PciAddress) - - // Save the PF status to the host - err = storeManager.SaveLastPfAppliedStatus(&iface) - if err != nil { - log.Log.Error(err, "SyncNodeState(): failed to save PF applied config to host") - return err - } - - break - } - if err = configSriovDevice(&iface, &ifaceStatus); err != nil { - log.Log.Error(err, "SyncNodeState(): fail to configure sriov interface. resetting interface.", "address", iface.PciAddress) - if iface.ExternallyManaged { - log.Log.Info("SyncNodeState(): skipping device reset as the nic is marked as externally created") - } else { - if resetErr := resetSriovDevice(ifaceStatus); resetErr != nil { - log.Log.Error(resetErr, "SyncNodeState(): failed to reset on error SR-IOV interface") - } - } - return err - } - - // Save the PF status to the host - err = storeManager.SaveLastPfAppliedStatus(&iface) - if err != nil { - log.Log.Error(err, "SyncNodeState(): failed to save PF applied config to host") - return err - } - break - } - } - if !configured && ifaceStatus.NumVfs > 0 { - if skip := pfsToConfig[ifaceStatus.PciAddress]; skip { - continue - } - - // load the PF info - pfStatus, exist, err := storeManager.LoadPfsStatus(ifaceStatus.PciAddress) - if err != nil { - log.Log.Error(err, "SyncNodeState(): failed to load info about PF status for device", - "address", ifaceStatus.PciAddress) - return err - } - - if !exist { - log.Log.Info("SyncNodeState(): PF name with pci address has VFs configured but they weren't created by the sriov operator. Skipping the device reset", - "pf-name", ifaceStatus.Name, - "address", ifaceStatus.PciAddress) - continue - } - - if pfStatus.ExternallyManaged { - log.Log.Info("SyncNodeState(): PF name with pci address was externally created skipping the device reset", - "pf-name", ifaceStatus.Name, - "address", ifaceStatus.PciAddress) - continue - } else { - err = RemoveUdevRule(ifaceStatus.PciAddress) - if err != nil { - return err - } - } - - if err = resetSriovDevice(ifaceStatus); err != nil { - return err - } - } - } - return nil -} - -// skipConfigVf Use systemd service to configure switchdev mode or BF-2 NICs in OpenShift -func skipConfigVf(ifSpec sriovnetworkv1.Interface, ifStatus sriovnetworkv1.InterfaceExt) (bool, error) { - if ifSpec.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { - log.Log.V(2).Info("skipConfigVf(): skip config VF for switchdev device") - return true, nil - } - - // NVIDIA BlueField 2 and BlueField3 in OpenShift - if ClusterType == ClusterTypeOpenshift && ifStatus.Vendor == VendorMellanox && (ifStatus.DeviceID == DeviceBF2 || ifStatus.DeviceID == DeviceBF3) { - // TODO: remove this when switch to the systemd configuration support. - mode, err := mellanoxBlueFieldMode(ifStatus.PciAddress) - if err != nil { - return false, fmt.Errorf("failed to read Mellanox Bluefield card mode for %s,%v", ifStatus.PciAddress, err) - } - - if mode == bluefieldConnectXMode { - return false, nil - } - - log.Log.V(2).Info("skipConfigVf(): skip config VF for Bluefiled card on DPU mode") - return true, nil - } - - return false, nil -} - -// GetPfsToSkip return a map of devices pci addresses to should be configured via systemd instead if the legacy mode -// we skip devices in switchdev mode and Bluefield card in ConnectX mode -func GetPfsToSkip(ns *sriovnetworkv1.SriovNetworkNodeState) (map[string]bool, error) { - pfsToSkip := map[string]bool{} - for _, ifaceStatus := range ns.Status.Interfaces { - for _, iface := range ns.Spec.Interfaces { - if iface.PciAddress == ifaceStatus.PciAddress { - skip, err := skipConfigVf(iface, ifaceStatus) - if err != nil { - log.Log.Error(err, "GetPfsToSkip(): fail to check for skip VFs", "device", iface.PciAddress) - return pfsToSkip, err - } - pfsToSkip[iface.PciAddress] = skip - break - } - } - } - - return pfsToSkip, nil -} - -func NeedUpdate(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) bool { - if iface.Mtu > 0 { - mtu := iface.Mtu - if mtu != ifaceStatus.Mtu { - log.Log.V(2).Info("NeedUpdate(): MTU needs update", "desired", mtu, "current", ifaceStatus.Mtu) - return true - } - } - - if iface.NumVfs != ifaceStatus.NumVfs { - log.Log.V(2).Info("NeedUpdate(): NumVfs needs update", "desired", iface.NumVfs, "current", ifaceStatus.NumVfs) - return true - } - if iface.NumVfs > 0 { - for _, vf := range ifaceStatus.VFs { - ingroup := false - for _, group := range iface.VfGroups { - if sriovnetworkv1.IndexInRange(vf.VfID, group.VfRange) { - ingroup = true - if group.DeviceType != constants.DeviceTypeNetDevice { - if group.DeviceType != vf.Driver { - log.Log.V(2).Info("NeedUpdate(): Driver needs update", - "desired", group.DeviceType, "current", vf.Driver) - return true - } - } else { - if sriovnetworkv1.StringInArray(vf.Driver, DpdkDrivers) { - log.Log.V(2).Info("NeedUpdate(): Driver needs update", - "desired", group.DeviceType, "current", vf.Driver) - return true - } - if vf.Mtu != 0 && group.Mtu != 0 && vf.Mtu != group.Mtu { - log.Log.V(2).Info("NeedUpdate(): VF MTU needs update", - "vf", vf.VfID, "desired", group.Mtu, "current", vf.Mtu) - return true - } - - // this is needed to be sure the admin mac address is configured as expected - if iface.ExternallyManaged { - log.Log.V(2).Info("NeedUpdate(): need to update the device as it's externally manage", - "device", ifaceStatus.PciAddress) - return true - } - } - break - } - } - if !ingroup && sriovnetworkv1.StringInArray(vf.Driver, DpdkDrivers) { - // VF which has DPDK driver loaded but not in any group, needs to be reset to default driver. - return true - } - } - } - return false -} - -func configSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error { - log.Log.V(2).Info("configSriovDevice(): configure sriov device", - "device", iface.PciAddress, "config", iface) - var err error - if iface.NumVfs > ifaceStatus.TotalVfs { - err := fmt.Errorf("cannot config SRIOV device: NumVfs (%d) is larger than TotalVfs (%d)", iface.NumVfs, ifaceStatus.TotalVfs) - log.Log.Error(err, "configSriovDevice(): fail to set NumVfs for device", "device", iface.PciAddress) - return err - } - // set numVFs - if iface.NumVfs != ifaceStatus.NumVfs { - if iface.ExternallyManaged { - if iface.NumVfs > ifaceStatus.NumVfs { - errMsg := fmt.Sprintf("configSriovDevice(): number of request virtual functions %d is not equal to configured virtual functions %d but the policy is configured as ExternallyManaged for device %s", iface.NumVfs, ifaceStatus.NumVfs, iface.PciAddress) - log.Log.Error(nil, errMsg) - return fmt.Errorf(errMsg) - } - } else { - // create the udev rule to disable all the vfs from network manager as this vfs are managed by the operator - err = AddUdevRule(iface.PciAddress) - if err != nil { - return err - } - - err = setSriovNumVfs(iface.PciAddress, iface.NumVfs) - if err != nil { - log.Log.Error(err, "configSriovDevice(): fail to set NumVfs for device", "device", iface.PciAddress) - errRemove := RemoveUdevRule(iface.PciAddress) - if errRemove != nil { - log.Log.Error(errRemove, "configSriovDevice(): fail to remove udev rule", "device", iface.PciAddress) - } - return err - } - } - } - // set PF mtu - if iface.Mtu > 0 && iface.Mtu > ifaceStatus.Mtu { - err = setNetdevMTU(iface.PciAddress, iface.Mtu) - if err != nil { - log.Log.Error(err, "configSriovDevice(): fail to set mtu for PF", "device", iface.PciAddress) - return err - } - } - // Config VFs - if iface.NumVfs > 0 { - vfAddrs, err := dputils.GetVFList(iface.PciAddress) - if err != nil { - log.Log.Error(err, "configSriovDevice(): unable to parse VFs for device", "device", iface.PciAddress) - } - pfLink, err := netlink.LinkByName(iface.Name) - if err != nil { - log.Log.Error(err, "configSriovDevice(): unable to get PF link for device", "device", iface) - return err - } - - for _, addr := range vfAddrs { - var group *sriovnetworkv1.VfGroup - - vfID, err := dputils.GetVFID(addr) - if err != nil { - log.Log.Error(err, "configSriovDevice(): unable to get VF id", "device", iface.PciAddress) - return err - } - - for i := range iface.VfGroups { - if sriovnetworkv1.IndexInRange(vfID, iface.VfGroups[i].VfRange) { - group = &iface.VfGroups[i] - break - } - } - - // VF group not found. - if group == nil { - continue - } - - // only set GUID and MAC for VF with default driver - // for userspace drivers like vfio we configure the vf mac using the kernel nic mac address - // before we switch to the userspace driver - if yes, d := hasDriver(addr); yes && !sriovnetworkv1.StringInArray(d, DpdkDrivers) { - // LinkType is an optional field. Let's fallback to current link type - // if nothing is specified in the SriovNodePolicy - linkType := iface.LinkType - if linkType == "" { - linkType = ifaceStatus.LinkType - } - if strings.EqualFold(linkType, constants.LinkTypeIB) { - if err = setVfGUID(addr, pfLink); err != nil { - return err - } - } else { - vfLink, err := vfIsReady(addr) - if err != nil { - log.Log.Error(err, "configSriovDevice(): VF link is not ready", "address", addr) - err = RebindVfToDefaultDriver(addr) - if err != nil { - log.Log.Error(err, "configSriovDevice(): failed to rebind VF", "address", addr) - return err - } - - // Try to check the VF status again - vfLink, err = vfIsReady(addr) - if err != nil { - log.Log.Error(err, "configSriovDevice(): VF link is not ready", "address", addr) - return err - } - } - if err = setVfAdminMac(addr, pfLink, vfLink); err != nil { - log.Log.Error(err, "configSriovDevice(): fail to configure VF admin mac", "device", addr) - return err - } - } - } - - if err = unbindDriverIfNeeded(addr, group.IsRdma); err != nil { - return err - } - - if !sriovnetworkv1.StringInArray(group.DeviceType, DpdkDrivers) { - if err := BindDefaultDriver(addr); err != nil { - log.Log.Error(err, "configSriovDevice(): fail to bind default driver for device", "device", addr) - return err - } - // only set MTU for VF with default driver - if group.Mtu > 0 { - if err := setNetdevMTU(addr, group.Mtu); err != nil { - log.Log.Error(err, "configSriovDevice(): fail to set mtu for VF", "address", addr) - return err - } - } - } else { - if err := BindDpdkDriver(addr, group.DeviceType); err != nil { - log.Log.Error(err, "configSriovDevice(): fail to bind driver for device", - "driver", group.DeviceType, "device", addr) - return err - } - } - } - } - // Set PF link up - pfLink, err := netlink.LinkByName(ifaceStatus.Name) - if err != nil { - return err - } - if pfLink.Attrs().OperState != netlink.OperUp { - err = netlink.LinkSetUp(pfLink) - if err != nil { - return err - } - } - return nil -} - -func setSriovNumVfs(pciAddr string, numVfs int) error { - log.Log.V(2).Info("setSriovNumVfs(): set NumVfs", "device", pciAddr, "numVfs", numVfs) - numVfsFilePath := filepath.Join(sysBusPciDevices, pciAddr, numVfsFile) - bs := []byte(strconv.Itoa(numVfs)) - err := os.WriteFile(numVfsFilePath, []byte("0"), os.ModeAppend) - if err != nil { - log.Log.Error(err, "setSriovNumVfs(): fail to reset NumVfs file", "path", numVfsFilePath) - return err - } - err = os.WriteFile(numVfsFilePath, bs, os.ModeAppend) - if err != nil { - log.Log.Error(err, "setSriovNumVfs(): fail to set NumVfs file", "path", numVfsFilePath) - return err - } - return nil -} - -func setNetdevMTU(pciAddr string, mtu int) error { - log.Log.V(2).Info("setNetdevMTU(): set MTU", "device", pciAddr, "mtu", mtu) - if mtu <= 0 { - log.Log.V(2).Info("setNetdevMTU(): refusing to set MTU", "mtu", mtu) - return nil - } - b := backoff.NewConstantBackOff(1 * time.Second) - err := backoff.Retry(func() error { - ifaceName, err := dputils.GetNetNames(pciAddr) - if err != nil { - log.Log.Error(err, "setNetdevMTU(): fail to get interface name", "device", pciAddr) - return err - } - if len(ifaceName) < 1 { - return fmt.Errorf("setNetdevMTU(): interface name is empty") - } - mtuFile := "net/" + ifaceName[0] + "/mtu" - mtuFilePath := filepath.Join(sysBusPciDevices, pciAddr, mtuFile) - return os.WriteFile(mtuFilePath, []byte(strconv.Itoa(mtu)), os.ModeAppend) - }, backoff.WithMaxRetries(b, 10)) - if err != nil { - log.Log.Error(err, "setNetdevMTU(): fail to write mtu file after retrying") - return err - } - return nil -} - -func tryGetInterfaceName(pciAddr string) string { - names, err := dputils.GetNetNames(pciAddr) - if err != nil || len(names) < 1 { - return "" - } - netDevName := names[0] - - // Switchdev PF and their VFs representors are existing under the same PCI address since kernel 5.8 - // if device is switchdev then return PF name - for _, name := range names { - if !isSwitchdev(name) { - continue - } - // Try to get the phys port name, if not exists then fallback to check without it - // phys_port_name should be in formant p e.g p0,p1,p2 ...etc. - if physPortName, err := GetPhysPortName(name); err == nil { - if !pfPhysPortNameRe.MatchString(physPortName) { - continue - } - } - return name - } - - log.Log.V(2).Info("tryGetInterfaceName()", "name", netDevName) - return netDevName -} - -func getNetdevMTU(pciAddr string) int { - log.Log.V(2).Info("getNetdevMTU(): get MTU", "device", pciAddr) - ifaceName := tryGetInterfaceName(pciAddr) - if ifaceName == "" { - return 0 - } - mtuFile := "net/" + ifaceName + "/mtu" - mtuFilePath := filepath.Join(sysBusPciDevices, pciAddr, mtuFile) - data, err := os.ReadFile(mtuFilePath) - if err != nil { - log.Log.Error(err, "getNetdevMTU(): fail to read mtu file", "path", mtuFilePath) - return 0 - } - mtu, err := strconv.Atoi(strings.TrimSpace(string(data))) - if err != nil { - log.Log.Error(err, "getNetdevMTU(): fail to convert mtu to int", "raw-mtu", strings.TrimSpace(string(data))) - return 0 - } - return mtu -} - -func getNetDevMac(ifaceName string) string { - log.Log.V(2).Info("getNetDevMac(): get Mac", "device", ifaceName) - macFilePath := filepath.Join(sysClassNet, ifaceName, "address") - data, err := os.ReadFile(macFilePath) - if err != nil { - log.Log.Error(err, "getNetDevMac(): fail to read Mac file", "path", macFilePath) - return "" - } - - return strings.TrimSpace(string(data)) -} - -func getNetDevLinkSpeed(ifaceName string) string { - log.Log.V(2).Info("getNetDevLinkSpeed(): get LinkSpeed", "device", ifaceName) - speedFilePath := filepath.Join(sysClassNet, ifaceName, "speed") - data, err := os.ReadFile(speedFilePath) - if err != nil { - log.Log.Error(err, "getNetDevLinkSpeed(): fail to read Link Speed file", "path", speedFilePath) - return "" - } - - return fmt.Sprintf("%s Mb/s", strings.TrimSpace(string(data))) +//go:generate ../../bin/mockgen -destination mock/mock_utils.go -source utils.go +type CmdInterface interface { + Chroot(string) (func() error, error) + RunCommand(string, ...string) (string, string, error) } -func resetSriovDevice(ifaceStatus sriovnetworkv1.InterfaceExt) error { - log.Log.V(2).Info("resetSriovDevice(): reset SRIOV device", "address", ifaceStatus.PciAddress) - if err := setSriovNumVfs(ifaceStatus.PciAddress, 0); err != nil { - return err - } - if ifaceStatus.LinkType == constants.LinkTypeETH { - var mtu int - is := InitialState.GetInterfaceStateByPciAddress(ifaceStatus.PciAddress) - if is != nil { - mtu = is.Mtu - } else { - mtu = 1500 - } - log.Log.V(2).Info("resetSriovDevice(): reset mtu", "value", mtu) - if err := setNetdevMTU(ifaceStatus.PciAddress, mtu); err != nil { - return err - } - } else if ifaceStatus.LinkType == constants.LinkTypeIB { - if err := setNetdevMTU(ifaceStatus.PciAddress, 2048); err != nil { - return err - } - } - return nil +type utilsHelper struct { } -func getVfInfo(pciAddr string, devices []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction { - driver, err := dputils.GetDriverName(pciAddr) - if err != nil { - log.Log.Error(err, "getVfInfo(): unable to parse device driver", "device", pciAddr) - } - id, err := dputils.GetVFID(pciAddr) - if err != nil { - log.Log.Error(err, "getVfInfo(): unable to get VF index", "device", pciAddr) - } - vf := sriovnetworkv1.VirtualFunction{ - PciAddress: pciAddr, - Driver: driver, - VfID: id, - } - - if mtu := getNetdevMTU(pciAddr); mtu > 0 { - vf.Mtu = mtu - } - if name := tryGetInterfaceName(pciAddr); name != "" { - vf.Name = name - vf.Mac = getNetDevMac(name) - } - - for _, device := range devices { - if pciAddr == device.Address { - vf.Vendor = device.Vendor.ID - vf.DeviceID = device.Product.ID - break - } - continue - } - return vf +func New() CmdInterface { + return &utilsHelper{} } -func Chroot(path string) (func() error, error) { +func (u *utilsHelper) Chroot(path string) (func() error, error) { root, err := os.Open("/") if err != nil { return nil, err @@ -746,101 +43,33 @@ func Chroot(path string) (func() error, error) { root.Close() return nil, err } + vars.InChroot = true return func() error { defer root.Close() if err := root.Chdir(); err != nil { return err } + vars.InChroot = false return syscall.Chroot(".") }, nil } -func vfIsReady(pciAddr string) (netlink.Link, error) { - log.Log.Info("vfIsReady()", "device", pciAddr) - var err error - var vfLink netlink.Link - err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { - vfName := tryGetInterfaceName(pciAddr) - vfLink, err = netlink.LinkByName(vfName) - if err != nil { - log.Log.Error(err, "vfIsReady(): unable to get VF link", "device", pciAddr) - } - return err == nil, nil - }) - if err != nil { - return vfLink, err - } - return vfLink, nil -} - -func setVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error { - log.Log.Info("setVfAdminMac()", "vf", vfAddr) - - vfID, err := dputils.GetVFID(vfAddr) - if err != nil { - log.Log.Error(err, "setVfAdminMac(): unable to get VF id", "address", vfAddr) - return err - } - - if err := netlink.LinkSetVfHardwareAddr(pfLink, vfID, vfLink.Attrs().HardwareAddr); err != nil { - return err - } - - return nil -} - -func unbindDriverIfNeeded(vfAddr string, isRdma bool) error { - if isRdma { - log.Log.Info("unbindDriverIfNeeded(): unbind driver", "device", vfAddr) - if err := Unbind(vfAddr); err != nil { - return err - } - } - return nil -} - -func getLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string { - log.Log.V(2).Info("getLinkType()", "device", ifaceStatus.PciAddress) - if ifaceStatus.Name != "" { - link, err := netlink.LinkByName(ifaceStatus.Name) - if err != nil { - log.Log.Error(err, "getLinkType(): failed to get link", "device", ifaceStatus.Name) - return "" - } - linkType := link.Attrs().EncapType - if linkType == "ether" { - return constants.LinkTypeETH - } else if linkType == "infiniband" { - return constants.LinkTypeIB - } - } - - return "" -} +// RunCommand runs a command +func (u *utilsHelper) RunCommand(command string, args ...string) (string, string, error) { + log.Log.Info("RunCommand()", "command", command, "args", args) + var stdout, stderr bytes.Buffer -func setVfGUID(vfAddr string, pfLink netlink.Link) error { - log.Log.Info("setVfGuid()", "vf", vfAddr) - vfID, err := dputils.GetVFID(vfAddr) - if err != nil { - log.Log.Error(err, "setVfGuid(): unable to get VF id", "address", vfAddr) - return err - } - guid := generateRandomGUID() - if err := netlink.LinkSetVfNodeGUID(pfLink, vfID, guid); err != nil { - return err - } - if err := netlink.LinkSetVfPortGUID(pfLink, vfID, guid); err != nil { - return err - } - if err = Unbind(vfAddr); err != nil { - return err - } + cmd := exec.Command(command, args...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr - return nil + err := cmd.Run() + log.Log.V(2).Info("RunCommand()", "output", stdout.String(), "error", err) + return stdout.String(), stderr.String(), err } -func generateRandomGUID() net.HardwareAddr { +func GenerateRandomGUID() net.HardwareAddr { guid := make(net.HardwareAddr, 8) // First field is 0x01 - xfe to avoid all zero and all F invalid guids @@ -853,82 +82,6 @@ func generateRandomGUID() net.HardwareAddr { return guid } -func GetNicSriovMode(pciAddress string) (string, error) { - log.Log.V(2).Info("GetNicSriovMode()", "device", pciAddress) - - devLink, err := netlink.DevLinkGetDeviceByName("pci", pciAddress) - if err != nil { - if errors.Is(err, syscall.ENODEV) { - // the device doesn't support devlink - return "", nil - } - return "", err - } - - return devLink.Attrs.Eswitch.Mode, nil -} - -func GetPhysSwitchID(name string) (string, error) { - swIDFile := filepath.Join(sysClassNet, name, "phys_switch_id") - physSwitchID, err := os.ReadFile(swIDFile) - if err != nil { - return "", err - } - if physSwitchID != nil { - return strings.TrimSpace(string(physSwitchID)), nil - } - return "", nil -} - -func GetPhysPortName(name string) (string, error) { - devicePortNameFile := filepath.Join(sysClassNet, name, "phys_port_name") - physPortName, err := os.ReadFile(devicePortNameFile) - if err != nil { - return "", err - } - if physPortName != nil { - return strings.TrimSpace(string(physPortName)), nil - } - return "", nil -} - -func isSwitchdev(name string) bool { - switchID, err := GetPhysSwitchID(name) - if err != nil || switchID == "" { - return false - } - - return true -} - -// IsKernelLockdownMode returns true when kernel lockdown mode is enabled -func IsKernelLockdownMode(chroot bool) bool { - path := "/sys/kernel/security/lockdown" - if !chroot { - path = "/host" + path - } - out, err := RunCommand("cat", path) - log.Log.V(2).Info("IsKernelLockdownMode()", "output", out, "error", err) - if err != nil { - return false - } - return strings.Contains(out, "[integrity]") || strings.Contains(out, "[confidentiality]") -} - -// RunCommand runs a command -func RunCommand(command string, args ...string) (string, error) { - log.Log.Info("RunCommand()", "command", command, "args", args) - var stdout, stderr bytes.Buffer - - cmd := exec.Command(command, args...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - err := cmd.Run() - log.Log.V(2).Info("RunCommand()", "output", stdout.String(), "error", err) - return stdout.String(), err -} - func HashConfigMap(cm *corev1.ConfigMap) string { var keys []string for k := range cm.Data { @@ -945,97 +98,25 @@ func HashConfigMap(cm *corev1.ConfigMap) string { return hex.EncodeToString(hashed) } -func hasMellanoxInterfacesInSpec(ifaceStatuses sriovnetworkv1.InterfaceExts, ifaceSpecs sriovnetworkv1.Interfaces) bool { - for _, ifaceStatus := range ifaceStatuses { - if ifaceStatus.Vendor == VendorMellanox { - for _, iface := range ifaceSpecs { - if iface.PciAddress == ifaceStatus.PciAddress { - log.Log.V(2).Info("hasMellanoxInterfacesInSpec(): Mellanox device specified in SriovNetworkNodeState spec", - "name", ifaceStatus.Name, - "address", ifaceStatus.PciAddress) - return true - } - } +func IsCommandNotFound(err error) bool { + if exitErr, ok := err.(*exec.ExitError); ok { + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok && status.ExitStatus() == 127 { + return true } } return false } -// Workaround function to handle a case where the vf default driver is stuck and not able to create the vf kernel interface. -// This function unbind the VF from the default driver and try to bind it again -// bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2045087 -func RebindVfToDefaultDriver(vfAddr string) error { - log.Log.Info("RebindVfToDefaultDriver()", "vf", vfAddr) - if err := Unbind(vfAddr); err != nil { - return err - } - if err := BindDefaultDriver(vfAddr); err != nil { - log.Log.Error(err, "RebindVfToDefaultDriver(): fail to bind default driver", "device", vfAddr) - return err - } - - log.Log.Info("RebindVfToDefaultDriver(): workaround implemented", "vf", vfAddr) - return nil -} - -func PrepareNMUdevRule(supportedVfIds []string) error { - log.Log.V(2).Info("PrepareNMUdevRule()") - dirPath := path.Join(FilesystemRoot, "/host/etc/udev/rules.d") - filePath := path.Join(dirPath, "10-nm-unmanaged.rules") - - // remove the old unmanaged rules file - if _, err := os.Stat(filePath); err == nil { - err = os.Remove(filePath) - if err != nil { - log.Log.Error(err, "failed to remove the network manager global unmanaged rule", - "path", filePath) - } - } - - // create the pf finder script for udev rules - var stdout, stderr bytes.Buffer - cmd := exec.Command("/bin/bash", path.Join(FilesystemRoot, udevDisableNM)) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - log.Log.Error(err, "PrepareNMUdevRule(): failed to prepare nmUdevRule", "stderr", stderr.String()) - return err - } - log.Log.V(2).Info("PrepareNMUdevRule()", "stdout", stdout.String()) - - //save the device list to use for udev rules - SupportedVfIds = supportedVfIds - return nil -} - -func AddUdevRule(pfPciAddress string) error { - log.Log.V(2).Info("AddUdevRule()", "device", pfPciAddress) - pathFile := udevRulesFolder - udevRuleContent := fmt.Sprintf(nmUdevRule, strings.Join(SupportedVfIds, "|"), pfPciAddress) - - err := os.MkdirAll(pathFile, os.ModePerm) - if err != nil && !os.IsExist(err) { - log.Log.Error(err, "AddUdevRule(): failed to create dir", "path", pathFile) - return err - } - - filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) - // if the file does not exist or if oldContent != newContent - // write to file and create it if it doesn't exist - err = os.WriteFile(filePath, []byte(udevRuleContent), 0666) - if err != nil { - log.Log.Error(err, "AddUdevRule(): fail to write file", "path", filePath) - return err +func GetHostExtension() string { + if vars.InChroot { + return vars.FilesystemRoot } - return nil + return filepath.Join(vars.FilesystemRoot, consts.Host) } -func RemoveUdevRule(pfPciAddress string) error { - pathFile := udevRulesFolder - filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) - err := os.Remove(filePath) - if err != nil && !os.IsNotExist(err) { - return err +func GetChrootExtension() string { + if vars.InChroot { + return vars.FilesystemRoot } - return nil + return fmt.Sprintf("chroot %s%s", vars.FilesystemRoot, consts.Host) } diff --git a/pkg/utils/utils_mlx.go b/pkg/utils/utils_mlx.go deleted file mode 100644 index ace265c79..000000000 --- a/pkg/utils/utils_mlx.go +++ /dev/null @@ -1,118 +0,0 @@ -package utils - -import ( - "fmt" - "regexp" - "strings" - - "sigs.k8s.io/controller-runtime/pkg/log" -) - -// BlueField mode representation -type BlueFieldMode int - -const ( - bluefieldDpu BlueFieldMode = iota - bluefieldConnectXMode - - internalCPUPageSupplier = "INTERNAL_CPU_PAGE_SUPPLIER" - internalCPUEswitchManager = "INTERNAL_CPU_ESWITCH_MANAGER" - internalCPUIbVporto = "INTERNAL_CPU_IB_VPORT0" - internalCPUOffloadEngine = "INTERNAL_CPU_OFFLOAD_ENGINE" - internalCPUModel = "INTERNAL_CPU_MODEL" - - ecpf = "ECPF" - extHostPf = "EXT_HOST_PF" - embeddedCPU = "EMBEDDED_CPU" - - disabled = "DISABLED" - enabled = "ENABLED" -) - -func MstConfigReadData(pciAddress string) (string, error) { - log.Log.Info("MstConfigReadData()", "device", pciAddress) - args := []string{"-e", "-d", pciAddress, "q"} - out, err := RunCommand("mstconfig", args...) - return out, err -} - -func ParseMstconfigOutput(mstOutput string, attributes []string) (fwCurrent, fwNext map[string]string) { - log.Log.Info("ParseMstconfigOutput()", "attributes", attributes) - fwCurrent = map[string]string{} - fwNext = map[string]string{} - formatRegex := regexp.MustCompile(`(?P\w+)\s+(?P\S+)\s+(?P\S+)\s+(?P\S+)`) - mstOutputLines := strings.Split(mstOutput, "\n") - for _, attr := range attributes { - for _, line := range mstOutputLines { - if strings.Contains(line, attr) { - regexResult := formatRegex.FindStringSubmatch(line) - fwCurrent[attr] = regexResult[3] - fwNext[attr] = regexResult[4] - break - } - } - } - return -} - -func mellanoxBlueFieldMode(PciAddress string) (BlueFieldMode, error) { - log.Log.V(2).Info("MellanoxBlueFieldMode(): checking mode for device", "device", PciAddress) - out, err := MstConfigReadData(PciAddress) - if err != nil { - log.Log.Error(err, "MellanoxBlueFieldMode(): failed to get mlx nic fw data") - return -1, fmt.Errorf("failed to get mlx nic fw data %w", err) - } - - attrs := []string{internalCPUPageSupplier, - internalCPUEswitchManager, - internalCPUIbVporto, - internalCPUOffloadEngine, - internalCPUModel} - mstCurrentData, _ := ParseMstconfigOutput(out, attrs) - - internalCPUPageSupplierstatus, exist := mstCurrentData[internalCPUPageSupplier] - if !exist { - return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUPageSupplier) - } - - internalCPUEswitchManagerStatus, exist := mstCurrentData[internalCPUEswitchManager] - if !exist { - return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUEswitchManager) - } - - internalCPUIbVportoStatus, exist := mstCurrentData[internalCPUIbVporto] - if !exist { - return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUIbVporto) - } - - internalCPUOffloadEngineStatus, exist := mstCurrentData[internalCPUOffloadEngine] - if !exist { - return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUOffloadEngine) - } - - internalCPUModelStatus, exist := mstCurrentData[internalCPUModel] - if !exist { - return 0, fmt.Errorf("failed to find %s in the mstconfig output command", internalCPUModel) - } - - // check for DPU - if strings.Contains(internalCPUPageSupplierstatus, ecpf) && - strings.Contains(internalCPUEswitchManagerStatus, ecpf) && - strings.Contains(internalCPUIbVportoStatus, ecpf) && - strings.Contains(internalCPUOffloadEngineStatus, enabled) && - strings.Contains(internalCPUModelStatus, embeddedCPU) { - log.Log.V(2).Info("MellanoxBlueFieldMode(): device in DPU mode", "device", PciAddress) - return bluefieldDpu, nil - } else if strings.Contains(internalCPUPageSupplierstatus, extHostPf) && - strings.Contains(internalCPUEswitchManagerStatus, extHostPf) && - strings.Contains(internalCPUIbVportoStatus, extHostPf) && - strings.Contains(internalCPUOffloadEngineStatus, disabled) && - strings.Contains(internalCPUModelStatus, embeddedCPU) { - log.Log.V(2).Info("MellanoxBlueFieldMode(): device in ConnectX mode", "device", PciAddress) - return bluefieldConnectXMode, nil - } - - log.Log.Error(err, "MellanoxBlueFieldMode(): unknown device status", - "device", PciAddress, "mstconfig-output", out) - return -1, fmt.Errorf("MellanoxBlueFieldMode(): unknown device status for %s", PciAddress) -} From e428647864b1a34da542e5315acf35401d4f58c4 Mon Sep 17 00:00:00 2001 From: ianb-mp <151477169+ianb-mp@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:46:44 +1000 Subject: [PATCH 07/61] Update Chart.yaml - kubeVersion check Change the `kubeVersion` constraint to permit pre-release versions as per: https://helm.sh/docs/chart_template_guide/function_list/#working-with-prerelease-versions --- deployment/sriov-network-operator/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/sriov-network-operator/Chart.yaml b/deployment/sriov-network-operator/Chart.yaml index 16ca4b1e0..8c7a62e95 100644 --- a/deployment/sriov-network-operator/Chart.yaml +++ b/deployment/sriov-network-operator/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: sriov-network-operator version: 0.1.0 -kubeVersion: '>= 1.16.0' +kubeVersion: '>= 1.16.0-0' appVersion: 1.2.0 description: SR-IOV network operator configures and manages SR-IOV networks in the kubernetes cluster type: application From 5887e7522ca8e1ebb13587bce6dafe43d000a992 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 18:29:07 +0200 Subject: [PATCH 08/61] update all the needed packages with the new global imports and interfaces Signed-off-by: Sebastian Sch --- api/v1/helper.go | 78 +++++ cmd/sriov-network-config-daemon/service.go | 93 +++--- cmd/sriov-network-config-daemon/start.go | 107 +++--- .../sriovnetworkpoolconfig_controller.go | 15 +- controllers/sriovoperatorconfig_controller.go | 45 +-- controllers/suite_test.go | 34 +- main.go | 31 +- pkg/daemon/daemon.go | 218 ++++++------- pkg/daemon/daemon_test.go | 96 ++---- pkg/daemon/event_recorder.go | 9 +- pkg/daemon/plugin.go | 25 +- pkg/daemon/writer.go | 98 +++--- pkg/plugins/generic/generic_plugin.go | 131 +++++--- pkg/plugins/generic/generic_plugin_test.go | 15 +- pkg/plugins/intel/intel_plugin.go | 3 +- pkg/plugins/k8s/k8s_plugin.go | 146 +++------ pkg/plugins/mellanox/mellanox_plugin.go | 308 ++---------------- pkg/plugins/mock/mock_plugin.go | 93 ++++++ pkg/plugins/plugin.go | 1 + pkg/plugins/virtual/virtual_plugin.go | 79 ++++- pkg/systemd/systemd.go | 31 +- pkg/webhook/validate.go | 22 +- test/util/cluster/cluster.go | 3 +- 23 files changed, 820 insertions(+), 861 deletions(-) create mode 100644 pkg/plugins/mock/mock_plugin.go diff --git a/api/v1/helper.go b/api/v1/helper.go index ba2429caf..664531260 100644 --- a/api/v1/helper.go +++ b/api/v1/helper.go @@ -20,7 +20,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) const ( @@ -47,6 +49,8 @@ var log = logf.Log.WithName("sriovnetwork") // Vendor ID, Physical Function Device ID, Virtual Function Device ID var NicIDMap = []string{} +var InitialState SriovNetworkNodeState + // NetFilterType Represents the NetFilter tags to be used type NetFilterType int @@ -211,6 +215,80 @@ func GetVfDeviceID(deviceID string) string { return "" } +func IsSwitchdevModeSpec(spec SriovNetworkNodeStateSpec) bool { + for _, iface := range spec.Interfaces { + if iface.EswitchMode == ESwithModeSwitchDev { + return true + } + } + return false +} + +func FindInterface(interfaces Interfaces, name string) (iface Interface, err error) { + for _, i := range interfaces { + if i.Name == name { + return i, nil + } + } + return Interface{}, fmt.Errorf("unable to find interface: %v", name) +} + +func NeedToUpdateSriov(ifaceSpec *Interface, ifaceStatus *InterfaceExt) bool { + if ifaceSpec.Mtu > 0 { + mtu := ifaceSpec.Mtu + if mtu != ifaceStatus.Mtu { + log.V(2).Info("NeedToUpdateSriov(): MTU needs update", "desired", mtu, "current", ifaceStatus.Mtu) + return true + } + } + + if ifaceSpec.NumVfs != ifaceStatus.NumVfs { + log.V(2).Info("NeedToUpdateSriov(): NumVfs needs update", "desired", ifaceSpec.NumVfs, "current", ifaceStatus.NumVfs) + return true + } + if ifaceSpec.NumVfs > 0 { + for _, vfStatus := range ifaceStatus.VFs { + ingroup := false + for _, groupSpec := range ifaceSpec.VfGroups { + if IndexInRange(vfStatus.VfID, groupSpec.VfRange) { + ingroup = true + if groupSpec.DeviceType != consts.DeviceTypeNetDevice { + if groupSpec.DeviceType != vfStatus.Driver { + log.V(2).Info("NeedToUpdateSriov(): Driver needs update", + "desired", groupSpec.DeviceType, "current", vfStatus.Driver) + return true + } + } else { + if StringInArray(vfStatus.Driver, vars.DpdkDrivers) { + log.V(2).Info("NeedToUpdateSriov(): Driver needs update", + "desired", groupSpec.DeviceType, "current", vfStatus.Driver) + return true + } + if vfStatus.Mtu != 0 && groupSpec.Mtu != 0 && vfStatus.Mtu != groupSpec.Mtu { + log.V(2).Info("NeedToUpdateSriov(): VF MTU needs update", + "vf", vfStatus.VfID, "desired", groupSpec.Mtu, "current", vfStatus.Mtu) + return true + } + + // this is needed to be sure the admin mac address is configured as expected + if ifaceSpec.ExternallyManaged { + log.V(2).Info("NeedToUpdateSriov(): need to update the device as it's externally manage", + "device", ifaceStatus.PciAddress) + return true + } + } + break + } + } + if !ingroup && StringInArray(vfStatus.Driver, vars.DpdkDrivers) { + // VF which has DPDK driver loaded but not in any group, needs to be reset to default driver. + return true + } + } + } + return false +} + type ByPriority []SriovNetworkNodePolicy func (a ByPriority) Len() int { diff --git a/cmd/sriov-network-config-daemon/service.go b/cmd/sriov-network-config-daemon/service.go index fc9cfc6d9..3305d7e8e 100644 --- a/cmd/sriov-network-config-daemon/service.go +++ b/cmd/sriov-network-config-daemon/service.go @@ -24,15 +24,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" + snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/generic" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/virtual" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/systemd" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/version" - - snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log" ) var ( @@ -57,11 +58,16 @@ func runServiceCmd(cmd *cobra.Command, args []string) error { setupLog.V(2).Info("sriov-config-service", "version", version.Version) setupLog.V(0).Info("Starting sriov-config-service") + + // Mark that we are running on host + vars.UsingSystemdMode = true + vars.InChroot = true + supportedNicIds, err := systemd.ReadSriovSupportedNics() if err != nil { setupLog.Error(err, "failed to read list of supported nic ids") sriovResult := &systemd.SriovResult{ - SyncStatus: "Failed", + SyncStatus: consts.SyncStatusFailed, LastSyncError: fmt.Sprintf("failed to read list of supported nic ids: %v", err), } err = systemd.WriteSriovResult(sriovResult) @@ -78,7 +84,7 @@ func runServiceCmd(cmd *cobra.Command, args []string) error { if _, err := os.Stat(systemd.SriovSystemdConfigPath); !errors.Is(err, os.ErrNotExist) { setupLog.Error(err, "failed to read the sriov configuration file", "path", systemd.SriovSystemdConfigPath) sriovResult := &systemd.SriovResult{ - SyncStatus: "Failed", + SyncStatus: consts.SyncStatusFailed, LastSyncError: fmt.Sprintf("failed to read the sriov configuration file in path %s: %v", systemd.SriovSystemdConfigPath, err), } err = systemd.WriteSriovResult(sriovResult) @@ -91,67 +97,64 @@ func runServiceCmd(cmd *cobra.Command, args []string) error { nodeStateSpec = &systemd.SriovConfig{ Spec: sriovv1.SriovNetworkNodeStateSpec{}, UnsupportedNics: false, - PlatformType: utils.Baremetal, + PlatformType: consts.Baremetal, } } setupLog.V(2).Info("sriov-config-service", "config", nodeStateSpec) - - storeManager, err := utils.NewStoreManager(true) + hostHelpers, err := helper.NewDefaultHostHelpers() if err != nil { - setupLog.Error(err, "failed to create store manager") - return err + setupLog.Error(err, "failed to create hostHelpers") + return updateSriovResultErr("failed to create hostHelpers") } - // Load kernel modules - hostManager := host.NewHostManager(true) - _, err = hostManager.TryEnableRdma() + platformHelper, err := platforms.NewDefaultPlatformHelper() + if err != nil { + setupLog.Error(err, "failed to create platformHelpers") + return updateSriovResultErr("failed to create platformHelpers") + } + + _, err = hostHelpers.TryEnableRdma() if err != nil { setupLog.Error(err, "warning, failed to enable RDMA") } - hostManager.TryEnableTun() - hostManager.TryEnableVhostNet() + hostHelpers.TryEnableTun() + hostHelpers.TryEnableVhostNet() var configPlugin plugin.VendorPlugin var ifaceStatuses []sriovv1.InterfaceExt - if nodeStateSpec.PlatformType == utils.Baremetal { + if nodeStateSpec.PlatformType == consts.Baremetal { // Bare metal support - ifaceStatuses, err = utils.DiscoverSriovDevices(nodeStateSpec.UnsupportedNics, storeManager) + vars.DevMode = nodeStateSpec.UnsupportedNics + ifaceStatuses, err = hostHelpers.DiscoverSriovDevices(hostHelpers) if err != nil { setupLog.Error(err, "failed to discover sriov devices on the host") - return fmt.Errorf("sriov-config-service: failed to discover sriov devices on the host: %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service: failed to discover sriov devices on the host: %v", err)) } // Create the generic plugin - configPlugin, err = generic.NewGenericPlugin(true, hostManager, storeManager) + configPlugin, err = generic.NewGenericPlugin(hostHelpers) if err != nil { setupLog.Error(err, "failed to create generic plugin") - return fmt.Errorf("sriov-config-service failed to create generic plugin %v", err) - } - } else if nodeStateSpec.PlatformType == utils.VirtualOpenStack { - // Openstack support - metaData, networkData, err := utils.GetOpenstackData(false) - if err != nil { - setupLog.Error(err, "failed to read OpenStack data") - return fmt.Errorf("sriov-config-service failed to read OpenStack data: %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service failed to create generic plugin %v", err)) } - - openStackDevicesInfo, err := utils.CreateOpenstackDevicesInfo(metaData, networkData) + } else if nodeStateSpec.PlatformType == consts.VirtualOpenStack { + err = platformHelper.CreateOpenstackDevicesInfo() if err != nil { setupLog.Error(err, "failed to read OpenStack data") - return fmt.Errorf("sriov-config-service failed to read OpenStack data: %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service failed to read OpenStack data: %v", err)) } - ifaceStatuses, err = utils.DiscoverSriovDevicesVirtual(openStackDevicesInfo) + ifaceStatuses, err = platformHelper.DiscoverSriovDevicesVirtual() if err != nil { setupLog.Error(err, "failed to read OpenStack data") - return fmt.Errorf("sriov-config-service: failed to read OpenStack data: %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service: failed to read OpenStack data: %v", err)) } // Create the virtual plugin - configPlugin, err = virtual.NewVirtualPlugin(true) + configPlugin, err = virtual.NewVirtualPlugin(hostHelpers) if err != nil { setupLog.Error(err, "failed to create virtual plugin") - return fmt.Errorf("sriov-config-service: failed to create virtual plugin %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service: failed to create virtual plugin %v", err)) } } @@ -163,18 +166,18 @@ func runServiceCmd(cmd *cobra.Command, args []string) error { _, _, err = configPlugin.OnNodeStateChange(nodeState) if err != nil { setupLog.Error(err, "failed to run OnNodeStateChange to update the generic plugin status") - return fmt.Errorf("sriov-config-service: failed to run OnNodeStateChange to update the generic plugin status %v", err) + return updateSriovResultErr(fmt.Sprintf("sriov-config-service: failed to run OnNodeStateChange to update the generic plugin status %v", err)) } sriovResult := &systemd.SriovResult{ - SyncStatus: "Succeeded", + SyncStatus: consts.SyncStatusSucceeded, LastSyncError: "", } err = configPlugin.Apply() if err != nil { setupLog.Error(err, "failed to run apply node configuration") - sriovResult.SyncStatus = "Failed" + sriovResult.SyncStatus = consts.SyncStatusFailed sriovResult.LastSyncError = err.Error() } @@ -187,3 +190,17 @@ func runServiceCmd(cmd *cobra.Command, args []string) error { setupLog.V(0).Info("shutting down sriov-config-service") return nil } + +func updateSriovResultErr(errMsg string) error { + sriovResult := &systemd.SriovResult{ + SyncStatus: consts.SyncStatusFailed, + LastSyncError: errMsg, + } + + err := systemd.WriteSriovResult(sriovResult) + if err != nil { + log.Log.Error(err, "failed to write sriov result file", "content", *sriovResult) + return fmt.Errorf("sriov-config-service failed to write sriov result file with content %v error: %v", *sriovResult, err) + } + return nil +} diff --git a/cmd/sriov-network-config-daemon/start.go b/cmd/sriov-network-config-daemon/start.go index a7feffbde..1d7d4d00c 100644 --- a/cmd/sriov-network-config-daemon/start.go +++ b/cmd/sriov-network-config-daemon/start.go @@ -24,8 +24,6 @@ import ( "strings" "time" - configv1 "github.com/openshift/api/config/v1" - mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" "github.com/spf13/cobra" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -35,12 +33,17 @@ import ( "k8s.io/client-go/util/connrotation" "sigs.k8s.io/controller-runtime/pkg/log" + configv1 "github.com/openshift/api/config/v1" + mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/daemon" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/version" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var ( @@ -70,8 +73,11 @@ func runStartCmd(cmd *cobra.Command, args []string) error { snolog.InitLog() setupLog := log.Log.WithName("sriov-network-config-daemon") - // To help debugging, immediately log version - setupLog.V(2).Info("sriov-network-config-daemon", "version", version.Version) + // Mark that we are running inside a container + vars.UsingSystemdMode = false + if startOpts.systemd { + vars.UsingSystemdMode = true + } if startOpts.nodeName == "" { name, ok := os.LookupEnv("NODE_NAME") @@ -80,6 +86,7 @@ func runStartCmd(cmd *cobra.Command, args []string) error { } startOpts.nodeName = name } + vars.NodeName = startOpts.nodeName // This channel is used to ensure all spawned goroutines exit when we exit. stopCh := make(chan struct{}) @@ -102,7 +109,9 @@ func runStartCmd(cmd *cobra.Command, args []string) error { var config *rest.Config var err error - if os.Getenv("CLUSTER_TYPE") == utils.ClusterTypeOpenshift { + // On openshift we use the kubeconfig from kubelet on the node where the daemon is running + // this allow us to improve security as every daemon has access only to its own node + if vars.ClusterType == consts.ClusterTypeOpenshift { kubeconfig, err := clientcmd.LoadFromFile("/host/etc/kubernetes/kubeconfig") if err != nil { setupLog.Error(err, "failed to load kubelet kubeconfig") @@ -110,7 +119,7 @@ func runStartCmd(cmd *cobra.Command, args []string) error { clusterName := kubeconfig.Contexts[kubeconfig.CurrentContext].Cluster apiURL := kubeconfig.Clusters[clusterName].Server - url, err := url.Parse(apiURL) + urlPath, err := url.Parse(apiURL) if err != nil { setupLog.Error(err, "failed to parse api url from kubelet kubeconfig") } @@ -118,8 +127,14 @@ func runStartCmd(cmd *cobra.Command, args []string) error { // The kubernetes in-cluster functions don't let you override the apiserver // directly; gotta "pass" it via environment vars. setupLog.V(0).Info("overriding kubernetes api", "new-url", apiURL) - os.Setenv("KUBERNETES_SERVICE_HOST", url.Hostname()) - os.Setenv("KUBERNETES_SERVICE_PORT", url.Port()) + err = os.Setenv("KUBERNETES_SERVICE_HOST", urlPath.Hostname()) + if err != nil { + setupLog.Error(err, "failed to set KUBERNETES_SERVICE_HOST environment variable") + } + err = os.Setenv("KUBERNETES_SERVICE_PORT", urlPath.Port()) + if err != nil { + setupLog.Error(err, "failed to set KUBERNETES_SERVICE_PORT environment variable") + } } kubeconfig := os.Getenv("KUBECONFIG") @@ -134,57 +149,72 @@ func runStartCmd(cmd *cobra.Command, args []string) error { return err } + vars.Config = config + vars.Scheme = scheme.Scheme + closeAllConns, err := updateDialer(config) if err != nil { return err } - sriovnetworkv1.AddToScheme(scheme.Scheme) - mcfgv1.AddToScheme(scheme.Scheme) - configv1.Install(scheme.Scheme) + err = sriovnetworkv1.AddToScheme(scheme.Scheme) + if err != nil { + setupLog.Error(err, "failed to load sriov network CRDs to scheme") + return err + } + + err = mcfgv1.AddToScheme(scheme.Scheme) + if err != nil { + setupLog.Error(err, "failed to load machine config CRDs to scheme") + return err + } + + err = configv1.Install(scheme.Scheme) + if err != nil { + setupLog.Error(err, "failed to load openshift config CRDs to scheme") + return err + } snclient := snclientset.NewForConfigOrDie(config) kubeclient := kubernetes.NewForConfigOrDie(config) - openshiftContext, err := utils.NewOpenshiftContext(config, scheme.Scheme) + + hostHelpers, err := helper.NewDefaultHostHelpers() + if err != nil { + setupLog.Error(err, "failed to create hostHelpers") + return err + } + + platformHelper, err := platforms.NewDefaultPlatformHelper() if err != nil { + setupLog.Error(err, "failed to create platformHelper") return err } config.Timeout = 5 * time.Second writerclient := snclientset.NewForConfigOrDie(config) - mode := os.Getenv("DEV_MODE") - devMode := false - if mode == "TRUE" { - devMode = true - setupLog.V(0).Info("dev mode enabled") - } - - eventRecorder := daemon.NewEventRecorder(writerclient, startOpts.nodeName, kubeclient) + eventRecorder := daemon.NewEventRecorder(writerclient, kubeclient) defer eventRecorder.Shutdown() setupLog.V(0).Info("starting node writer") - nodeWriter := daemon.NewNodeStateStatusWriter(writerclient, startOpts.nodeName, closeAllConns, eventRecorder, devMode) - - destdir := os.Getenv("DEST_DIR") - if destdir == "" { - destdir = "/host/tmp" - } - - platformType := utils.Baremetal + nodeWriter := daemon.NewNodeStateStatusWriter(writerclient, + closeAllConns, + eventRecorder, + hostHelpers, + platformHelper) nodeInfo, err := kubeclient.CoreV1().Nodes().Get(context.Background(), startOpts.nodeName, v1.GetOptions{}) if err == nil { - for key, pType := range utils.PlatformMap { + for key, pType := range vars.PlatformsMap { if strings.Contains(strings.ToLower(nodeInfo.Spec.ProviderID), strings.ToLower(key)) { - platformType = pType + vars.PlatformType = pType } } } else { setupLog.Error(err, "failed to fetch node state, exiting", "node-name", startOpts.nodeName) return err } - setupLog.Info("Running on", "platform", platformType.String()) + setupLog.Info("Running on", "platform", vars.PlatformType.String()) var namespace = os.Getenv("NAMESPACE") if err := sriovnetworkv1.InitNicIDMapFromConfigMap(kubeclient, namespace); err != nil { @@ -195,27 +225,24 @@ func runStartCmd(cmd *cobra.Command, args []string) error { eventRecorder.SendEvent("ConfigDaemonStart", "Config Daemon starting") // block the deamon process until nodeWriter finish first its run - err = nodeWriter.RunOnce(destdir, platformType) + err = nodeWriter.RunOnce() if err != nil { setupLog.Error(err, "failed to run writer") return err } - go nodeWriter.Run(stopCh, refreshCh, syncCh, platformType) + go nodeWriter.Run(stopCh, refreshCh, syncCh) setupLog.V(0).Info("Starting SriovNetworkConfigDaemon") err = daemon.New( - startOpts.nodeName, snclient, kubeclient, - openshiftContext, + hostHelpers, + platformHelper, exitCh, stopCh, syncCh, refreshCh, - platformType, - startOpts.systemd, eventRecorder, - devMode, ).Run(stopCh, exitCh) if err != nil { setupLog.Error(err, "failed to run daemon") diff --git a/controllers/sriovnetworkpoolconfig_controller.go b/controllers/sriovnetworkpoolconfig_controller.go index de8fb32b2..fd4643476 100644 --- a/controllers/sriovnetworkpoolconfig_controller.go +++ b/controllers/sriovnetworkpoolconfig_controller.go @@ -17,15 +17,16 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // SriovNetworkPoolConfigReconciler reconciles a SriovNetworkPoolConfig object type SriovNetworkPoolConfigReconciler struct { client.Client - Scheme *runtime.Scheme - OpenshiftContext *utils.OpenshiftContext + Scheme *runtime.Scheme + PlatformHelper platforms.Interface } //+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs,verbs=get;list;watch;create;update;patch;delete @@ -44,8 +45,8 @@ type SriovNetworkPoolConfigReconciler struct { func (r *SriovNetworkPoolConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx).WithValues("sriovnetworkpoolconfig", req.NamespacedName) isHypershift := false - if r.OpenshiftContext.IsOpenshiftCluster() { - if r.OpenshiftContext.IsHypershift() { + if r.PlatformHelper.IsOpenshiftCluster() { + if r.PlatformHelper.IsHypershift() { isHypershift = true } logger = logger.WithValues("isHypershift", isHypershift) @@ -78,7 +79,7 @@ func (r *SriovNetworkPoolConfigReconciler) Reconcile(ctx context.Context, req ct return reconcile.Result{}, err } } - if utils.ClusterType == utils.ClusterTypeOpenshift { + if vars.ClusterType == constants.ClusterTypeOpenshift { if !isHypershift { if err = r.syncOvsHardwareOffloadMachineConfigs(ctx, instance, false); err != nil { return reconcile.Result{}, err @@ -92,7 +93,7 @@ func (r *SriovNetworkPoolConfigReconciler) Reconcile(ctx context.Context, req ct if sriovnetworkv1.StringInArray(sriovnetworkv1.POOLCONFIGFINALIZERNAME, instance.ObjectMeta.Finalizers) { // our finalizer is present, so lets handle any external dependency logger.Info("delete SriovNetworkPoolConfig CR", "Namespace", instance.Namespace, "Name", instance.Name) - if utils.ClusterType == utils.ClusterTypeOpenshift && !isHypershift { + if vars.ClusterType == constants.ClusterTypeOpenshift && !isHypershift { if err = r.syncOvsHardwareOffloadMachineConfigs(ctx, instance, true); err != nil { // if fail to delete the external dependency here, return with error // so that it can be retried diff --git a/controllers/sriovoperatorconfig_controller.go b/controllers/sriovoperatorconfig_controller.go index 4c453b6de..1e4c7728b 100644 --- a/controllers/sriovoperatorconfig_controller.go +++ b/controllers/sriovoperatorconfig_controller.go @@ -39,17 +39,19 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" apply "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apply" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + consts "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" render "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // SriovOperatorConfigReconciler reconciles a SriovOperatorConfig object type SriovOperatorConfigReconciler struct { client.Client - Scheme *runtime.Scheme - OpenshiftContext *utils.OpenshiftContext + Scheme *runtime.Scheme + PlatformHelper platforms.Interface } //+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovoperatorconfigs,verbs=get;list;watch;create;update;patch;delete @@ -70,13 +72,12 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. logger.Info("Reconciling SriovOperatorConfig") - enableAdmissionController := os.Getenv("ADMISSION_CONTROLLERS_ENABLED") == trueString - if !enableAdmissionController { + if !vars.EnableAdmissionController { logger.Info("SR-IOV Network Resource Injector and Operator Webhook are disabled.") } defaultConfig := &sriovnetworkv1.SriovOperatorConfig{} err := r.Get(ctx, types.NamespacedName{ - Name: constants.DefaultConfigName, Namespace: namespace}, defaultConfig) + Name: consts.DefaultConfigName, Namespace: namespace}, defaultConfig) if err != nil { if apierrors.IsNotFound(err) { singleNode, err := utils.IsSingleNodeCluster(r.Client) @@ -86,10 +87,10 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. // Default Config object not found, create it. defaultConfig.SetNamespace(namespace) - defaultConfig.SetName(constants.DefaultConfigName) + defaultConfig.SetName(consts.DefaultConfigName) defaultConfig.Spec = sriovnetworkv1.SriovOperatorConfigSpec{ - EnableInjector: func() *bool { b := enableAdmissionController; return &b }(), - EnableOperatorWebhook: func() *bool { b := enableAdmissionController; return &b }(), + EnableInjector: func() *bool { b := vars.EnableAdmissionController; return &b }(), + EnableOperatorWebhook: func() *bool { b := vars.EnableAdmissionController; return &b }(), ConfigDaemonNodeSelector: map[string]string{}, LogLevel: 2, DisableDrain: singleNode, @@ -99,7 +100,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. err = r.Create(ctx, defaultConfig) if err != nil { logger.Error(err, "Failed to create default Operator Config", "Namespace", - namespace, "Name", constants.DefaultConfigName) + namespace, "Name", consts.DefaultConfigName) return reconcile.Result{}, err } return reconcile.Result{}, nil @@ -129,9 +130,9 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. snolog.SetLogLevel(defaultConfig.Spec.LogLevel) // For Openshift we need to create the systemd files using a machine config - if utils.ClusterType == utils.ClusterTypeOpenshift { + if vars.ClusterType == consts.ClusterTypeOpenshift { // TODO: add support for hypershift as today there is no MCO on hypershift clusters - if r.OpenshiftContext.IsHypershift() { + if r.PlatformHelper.IsHypershift() { return ctrl.Result{}, fmt.Errorf("systemd mode is not supported on hypershift") } @@ -139,7 +140,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. return reconcile.Result{}, err } } - return reconcile.Result{RequeueAfter: constants.ResyncPeriod}, nil + return reconcile.Result{RequeueAfter: consts.ResyncPeriod}, nil } // SetupWithManager sets up the controller with the Manager. @@ -192,7 +193,7 @@ func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(ctx context.Context, data.Data["SRIOVCNIImage"] = os.Getenv("SRIOV_CNI_IMAGE") data.Data["SRIOVInfiniBandCNIImage"] = os.Getenv("SRIOV_INFINIBAND_CNI_IMAGE") data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") - data.Data["ClusterType"] = utils.ClusterType + data.Data["ClusterType"] = vars.ClusterType data.Data["DevMode"] = os.Getenv("DEV_MODE") data.Data["ImagePullSecrets"] = GetImagePullSecrets() if dc.Spec.ConfigurationMode == sriovnetworkv1.SystemdConfigurationMode { @@ -208,7 +209,7 @@ func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(ctx context.Context, logger.V(1).Info("New cni bin found", "CNIBinPath", envCniBinPath) data.Data["CNIBinPath"] = envCniBinPath } - objs, err := render.RenderDir(constants.ConfigDaemonPath, &data) + objs, err := render.RenderDir(consts.ConfigDaemonPath, &data) if err != nil { logger.Error(err, "Fail to render config daemon manifests") return err @@ -251,7 +252,7 @@ func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc data.Data["NetworkResourcesInjectorImage"] = os.Getenv("NETWORK_RESOURCES_INJECTOR_IMAGE") data.Data["SriovNetworkWebhookImage"] = os.Getenv("SRIOV_NETWORK_WEBHOOK_IMAGE") data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") - data.Data["ClusterType"] = utils.ClusterType + data.Data["ClusterType"] = vars.ClusterType data.Data["DevMode"] = os.Getenv("DEV_MODE") data.Data["ImagePullSecrets"] = GetImagePullSecrets() data.Data["CertManagerEnabled"] = strings.ToLower(os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_CERT_MANAGER_ENABLED")) == trueString @@ -261,8 +262,8 @@ func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc data.Data["InjectorWebhookCA"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_CA_CRT") data.Data["ExternalControlPlane"] = false - if r.OpenshiftContext.IsOpenshiftCluster() { - external := r.OpenshiftContext.IsHypershift() + if r.PlatformHelper.IsOpenshiftCluster() { + external := r.PlatformHelper.IsHypershift() data.Data["ExternalControlPlane"] = external } @@ -273,7 +274,7 @@ func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc } // Delete injector webhook - if !*dc.Spec.EnableInjector && path == constants.InjectorWebHookPath { + if !*dc.Spec.EnableInjector && path == consts.InjectorWebHookPath { for _, obj := range objs { err = r.deleteWebhookObject(ctx, obj) if err != nil { @@ -286,7 +287,7 @@ func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc continue } // Delete operator webhook - if !*dc.Spec.EnableOperatorWebhook && path == constants.OperatorWebHookPath { + if !*dc.Spec.EnableOperatorWebhook && path == consts.OperatorWebHookPath { for _, obj := range objs { err = r.deleteWebhookObject(ctx, obj) if err != nil { @@ -347,7 +348,7 @@ func (r *SriovOperatorConfigReconciler) syncOpenShiftSystemdService(ctx context. if cr.Spec.ConfigurationMode != sriovnetworkv1.SystemdConfigurationMode { obj := &machinev1.MachineConfig{} - err := r.Get(context.TODO(), types.NamespacedName{Name: constants.SystemdServiceOcpMachineConfigName}, obj) + err := r.Get(context.TODO(), types.NamespacedName{Name: consts.SystemdServiceOcpMachineConfigName}, obj) if err != nil { if apierrors.IsNotFound(err) { return nil @@ -370,7 +371,7 @@ func (r *SriovOperatorConfigReconciler) syncOpenShiftSystemdService(ctx context. logger.Info("Start to sync config systemd machine config for openshift") data := render.MakeRenderData() data.Data["LogLevel"] = cr.Spec.LogLevel - objs, err := render.RenderDir(constants.SystemdServiceOcpPath, &data) + objs, err := render.RenderDir(consts.SystemdServiceOcpPath, &data) if err != nil { logger.Error(err, "Fail to render config daemon manifests") return err diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 4fe8a3eb8..0493ab7c6 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -23,13 +23,11 @@ import ( "testing" "time" - netattdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - openshiftconfigv1 "github.com/openshift/api/config/v1" - mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" - "go.uber.org/zap/zapcore" + "go.uber.org/zap/zapcore" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/scheme" @@ -39,10 +37,15 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + netattdefv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + openshiftconfigv1 "github.com/openshift/api/config/v1" + mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" + + //+kubebuilder:scaffold:imports sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" - //+kubebuilder:scaffold:imports + mock_platforms "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/mock" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -129,17 +132,24 @@ var _ = BeforeSuite(func(done Done) { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + t := GinkgoT() + mockCtrl := gomock.NewController(t) + platformHelper := mock_platforms.NewMockInterface(mockCtrl) + platformHelper.EXPECT().GetFlavor().Return(openshift.OpenshiftFlavorDefault).AnyTimes() + platformHelper.EXPECT().IsOpenshiftCluster().Return(false).AnyTimes() + platformHelper.EXPECT().IsHypershift().Return(false).AnyTimes() + err = (&SriovOperatorConfigReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - OpenshiftContext: &utils.OpenshiftContext{OpenshiftFlavor: utils.OpenshiftFlavorDefault}, + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + PlatformHelper: platformHelper, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) err = (&SriovNetworkPoolConfigReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - OpenshiftContext: &utils.OpenshiftContext{OpenshiftFlavor: utils.OpenshiftFlavorDefault}, + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + PlatformHelper: platformHelper, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index 7d62af130..07f3f70be 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,9 @@ import ( mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" "k8s.io/apimachinery/pkg/api/errors" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -90,12 +93,6 @@ func main() { os.Exit(1) } - openshiftContext, err := utils.NewOpenshiftContext(restConfig, scheme) - if err != nil { - setupLog.Error(err, "couldn't create openshift context") - os.Exit(1) - } - le := leaderelection.GetLeaderElectionConfig(kubeClient, enableLeaderElection) namespace := os.Getenv("NAMESPACE") @@ -137,6 +134,16 @@ func main() { os.Exit(1) } + // Initial global info + vars.Config = restConfig + vars.Scheme = mgrGlobal.GetScheme() + + platformsHelper, err := platforms.NewDefaultPlatformHelper() + if err != nil { + setupLog.Error(err, "couldn't create openshift context") + os.Exit(1) + } + if err = (&controllers.SriovNetworkReconciler{ Client: mgrGlobal.GetClient(), Scheme: mgrGlobal.GetScheme(), @@ -159,17 +166,17 @@ func main() { os.Exit(1) } if err = (&controllers.SriovOperatorConfigReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - OpenshiftContext: openshiftContext, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + PlatformHelper: platformsHelper, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SriovOperatorConfig") os.Exit(1) } if err = (&controllers.SriovNetworkPoolConfigReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - OpenshiftContext: openshiftContext, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + PlatformHelper: platformsHelper, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SriovNetworkPoolConfig") os.Exit(1) diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 913cad805..290b4400e 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -39,12 +39,13 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" sninformer "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/informers/externalversions" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/service" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/systemd" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) const ( @@ -62,26 +63,17 @@ type Message struct { } type Daemon struct { - // name is the node name. - name string - - platform utils.PlatformType - - useSystemdService bool - - devMode bool - client snclientset.Interface // kubeClient allows interaction with Kubernetes, including the node we are running on. kubeClient kubernetes.Interface - openshiftContext *utils.OpenshiftContext - nodeState *sriovnetworkv1.SriovNetworkNodeState enabledPlugins map[string]plugin.VendorPlugin - serviceManager service.ServiceManager + HostHelpers helper.HostHelpersInterface + + platformHelpers platforms.Interface // channel used by callbacks to signal Run() of an error exitCh chan<- error @@ -109,22 +101,15 @@ type Daemon struct { mcpName string - storeManager utils.StoreManagerInterface - - hostManager host.HostManagerInterface - eventRecorder *EventRecorder } const ( - udevScriptsPath = "/bindata/scripts/load-udev.sh" - annoKey = "sriovnetwork.openshift.io/state" - annoIdle = "Idle" - annoDraining = "Draining" - annoMcpPaused = "Draining_MCP_Paused" - syncStatusSucceeded = "Succeeded" - syncStatusFailed = "Failed" - syncStatusInProgress = "InProgress" + udevScriptsPath = "/bindata/scripts/load-udev.sh" + annoKey = "sriovnetwork.openshift.io/state" + annoIdle = "Idle" + annoDraining = "Draining" + annoMcpPaused = "Draining_MCP_Paused" ) var namespace = os.Getenv("NAMESPACE") @@ -141,33 +126,26 @@ func (w writer) Write(p []byte) (n int, err error) { } func New( - nodeName string, client snclientset.Interface, kubeClient kubernetes.Interface, - openshiftContext *utils.OpenshiftContext, + hostHelpers helper.HostHelpersInterface, + platformHelper platforms.Interface, exitCh chan<- error, stopCh <-chan struct{}, syncCh <-chan struct{}, refreshCh chan<- Message, - platformType utils.PlatformType, - useSystemdService bool, er *EventRecorder, - devMode bool, ) *Daemon { return &Daemon{ - name: nodeName, - platform: platformType, - useSystemdService: useSystemdService, - devMode: devMode, - client: client, - kubeClient: kubeClient, - openshiftContext: openshiftContext, - serviceManager: service.NewServiceManager("/host"), - exitCh: exitCh, - stopCh: stopCh, - syncCh: syncCh, - refreshCh: refreshCh, - nodeState: &sriovnetworkv1.SriovNetworkNodeState{}, + client: client, + kubeClient: kubeClient, + HostHelpers: hostHelpers, + platformHelpers: platformHelper, + exitCh: exitCh, + stopCh: stopCh, + syncCh: syncCh, + refreshCh: refreshCh, + nodeState: &sriovnetworkv1.SriovNetworkNodeState{}, drainer: &drain.Helper{ Client: kubeClient, Force: true, @@ -195,38 +173,30 @@ func New( // Run the config daemon func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { - log.Log.V(0).Info("Run()", "node", dn.name) + log.Log.V(0).Info("Run()", "node", vars.NodeName) - if utils.ClusterType == utils.ClusterTypeOpenshift { - log.Log.V(0).Info("Run(): start daemon.", "openshiftFlavor", dn.openshiftContext.OpenshiftFlavor) + if vars.ClusterType == consts.ClusterTypeOpenshift { + log.Log.V(0).Info("Run(): start daemon.", "openshiftFlavor", dn.platformHelpers.GetFlavor()) } else { log.Log.V(0).Info("Run(): start daemon.") } - if dn.useSystemdService { - log.Log.V(0).Info("Run(): daemon running in systemd mode") - } - // Only watch own SriovNetworkNodeState CR - defer utilruntime.HandleCrash() - defer dn.workqueue.ShutDown() - - hostManager := host.NewHostManager(dn.useSystemdService) - dn.hostManager = hostManager - if !dn.useSystemdService { - dn.hostManager.TryEnableRdma() - dn.hostManager.TryEnableTun() - dn.hostManager.TryEnableVhostNet() - err := systemd.CleanSriovFilesFromHost(utils.ClusterType == utils.ClusterTypeOpenshift) + if !vars.UsingSystemdMode { + log.Log.V(0).Info("Run(): daemon running in daemon mode") + dn.HostHelpers.TryEnableRdma() + dn.HostHelpers.TryEnableTun() + dn.HostHelpers.TryEnableVhostNet() + err := systemd.CleanSriovFilesFromHost(vars.ClusterType == consts.ClusterTypeOpenshift) if err != nil { log.Log.Error(err, "failed to remove all the systemd sriov files") } + } else { + log.Log.V(0).Info("Run(): daemon running in systemd mode") } - storeManager, err := utils.NewStoreManager(false) - if err != nil { - return err - } - dn.storeManager = storeManager + // Only watch own SriovNetworkNodeState CR + defer utilruntime.HandleCrash() + defer dn.workqueue.ShutDown() if err := dn.prepareNMUdevRule(); err != nil { log.Log.Error(err, "failed to prepare udev files to disable network manager on requested VFs") @@ -241,7 +211,7 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { time.Second*15, namespace, func(lo *metav1.ListOptions) { - lo.FieldSelector = "metadata.name=" + dn.name + lo.FieldSelector = "metadata.name=" + vars.NodeName lo.TimeoutSeconds = &timeout }, ) @@ -300,7 +270,7 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { log.Log.Error(err, "got an error") if more { dn.refreshCh <- Message{ - syncStatus: syncStatusFailed, + syncStatus: consts.SyncStatusFailed, lastSyncError: err.Error(), } } @@ -358,7 +328,7 @@ func (dn *Daemon) processNextWorkItem() bool { if err != nil { // Ereport error message, and put the item back to work queue for retry. dn.refreshCh <- Message{ - syncStatus: syncStatusFailed, + syncStatus: consts.SyncStatusFailed, lastSyncError: err.Error(), } <-dn.syncCh @@ -384,9 +354,9 @@ func (dn *Daemon) nodeAddHandler(obj interface{}) { } func (dn *Daemon) nodeUpdateHandler(old, new interface{}) { - node, err := dn.nodeLister.Get(dn.name) + node, err := dn.nodeLister.Get(vars.NodeName) if errors.IsNotFound(err) { - log.Log.V(2).Info("nodeUpdateHandler(): node has been deleted", "name", dn.name) + log.Log.V(2).Info("nodeUpdateHandler(): node has been deleted", "name", vars.NodeName) return } dn.node = node.DeepCopy() @@ -399,7 +369,7 @@ func (dn *Daemon) nodeUpdateHandler(old, new interface{}) { // Checking if other nodes are draining for _, otherNode := range nodes { - if otherNode.GetName() == dn.name { + if otherNode.GetName() == vars.NodeName { continue } @@ -438,24 +408,24 @@ func (dn *Daemon) nodeStateSyncHandler() error { var err error // Get the latest NodeState var latestState *sriovnetworkv1.SriovNetworkNodeState - var sriovResult = &systemd.SriovResult{SyncStatus: syncStatusSucceeded, LastSyncError: ""} - latestState, err = dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), dn.name, metav1.GetOptions{}) + var sriovResult = &systemd.SriovResult{SyncStatus: consts.SyncStatusSucceeded, LastSyncError: ""} + latestState, err = dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { - log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", dn.name) + log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", vars.NodeName) return err } latest := latestState.GetGeneration() log.Log.V(0).Info("nodeStateSyncHandler(): new generation", "generation", latest) - if utils.ClusterType == utils.ClusterTypeOpenshift && !dn.openshiftContext.IsHypershift() { + if vars.ClusterType == consts.ClusterTypeOpenshift && !dn.platformHelpers.IsHypershift() { if err = dn.getNodeMachinePool(); err != nil { return err } } if dn.nodeState.GetGeneration() == latest { - if dn.useSystemdService { - serviceEnabled, err := dn.serviceManager.IsServiceEnabled(systemd.SriovServicePath) + if vars.UsingSystemdMode { + serviceEnabled, err := dn.HostHelpers.IsServiceEnabled(systemd.SriovServicePath) if err != nil { log.Log.Error(err, "nodeStateSyncHandler(): failed to check if sriov-config service exist on host") return err @@ -465,7 +435,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { // this is only for k8s base environments, for openshift the sriov-operator creates a machine config to will apply // the system service and reboot the node the config-daemon doesn't need to do anything. if !serviceEnabled { - sriovResult = &systemd.SriovResult{SyncStatus: syncStatusFailed, + sriovResult = &systemd.SriovResult{SyncStatus: consts.SyncStatusFailed, LastSyncError: "sriov-config systemd service is not available on node"} } else { sriovResult, err = systemd.ReadSriovResult() @@ -474,12 +444,12 @@ func (dn *Daemon) nodeStateSyncHandler() error { return err } } - if sriovResult.LastSyncError != "" || sriovResult.SyncStatus == syncStatusFailed { + if sriovResult.LastSyncError != "" || sriovResult.SyncStatus == consts.SyncStatusFailed { log.Log.Info("nodeStateSyncHandler(): sync failed systemd service error", "last-sync-error", sriovResult.LastSyncError) // add the error but don't requeue dn.refreshCh <- Message{ - syncStatus: syncStatusFailed, + syncStatus: consts.SyncStatusFailed, lastSyncError: sriovResult.LastSyncError, } <-dn.syncCh @@ -488,9 +458,9 @@ func (dn *Daemon) nodeStateSyncHandler() error { } log.Log.V(0).Info("nodeStateSyncHandler(): Interface not changed") if latestState.Status.LastSyncError != "" || - latestState.Status.SyncStatus != syncStatusSucceeded { + latestState.Status.SyncStatus != consts.SyncStatusSucceeded { dn.refreshCh <- Message{ - syncStatus: syncStatusSucceeded, + syncStatus: consts.SyncStatusSucceeded, lastSyncError: "", } // wait for writer to refresh the status @@ -501,7 +471,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } if latestState.GetGeneration() == 1 && len(latestState.Spec.Interfaces) == 0 { - err = dn.storeManager.ClearPCIAddressFolder() + err = dn.HostHelpers.ClearPCIAddressFolder() if err != nil { log.Log.Error(err, "failed to clear the PCI address configuration") return err @@ -522,7 +492,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } dn.refreshCh <- Message{ - syncStatus: syncStatusInProgress, + syncStatus: consts.SyncStatusInProgress, lastSyncError: "", } // wait for writer to refresh status then pull again the latest node state @@ -531,16 +501,16 @@ func (dn *Daemon) nodeStateSyncHandler() error { // we need to load the latest status to our object // if we don't do it we can have a race here where the user remove the virtual functions but the operator didn't // trigger the refresh - updatedState, err := dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), dn.name, metav1.GetOptions{}) + updatedState, err := dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { - log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", dn.name) + log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", vars.NodeName) return err } latestState.Status = updatedState.Status // load plugins if it has not loaded if len(dn.enabledPlugins) == 0 { - dn.enabledPlugins, err = enablePlugins(dn.platform, dn.useSystemdService, latestState, dn.hostManager, dn.storeManager) + dn.enabledPlugins, err = enablePlugins(latestState, dn.HostHelpers) if err != nil { log.Log.Error(err, "nodeStateSyncHandler(): failed to enable vendor plugins") return err @@ -571,8 +541,9 @@ func (dn *Daemon) nodeStateSyncHandler() error { // When running using systemd check if the applied configuration is the latest one // or there is a new config we need to apply // When using systemd configuration we write the file - if dn.useSystemdService { - systemdConfModified, err := systemd.WriteConfFile(latestState, dn.devMode, dn.platform) + if vars.UsingSystemdMode { + log.Log.V(0).Info("nodeStateSyncHandler(): writing systemd config file to host") + systemdConfModified, err := systemd.WriteConfFile(latestState) if err != nil { log.Log.Error(err, "nodeStateSyncHandler(): failed to write configuration file for systemd mode") return err @@ -610,7 +581,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } } } - if dn.openshiftContext.IsOpenshiftCluster() && !dn.openshiftContext.IsHypershift() { + if dn.platformHelpers.IsOpenshiftCluster() && !dn.platformHelpers.IsHypershift() { if err = dn.getNodeMachinePool(); err != nil { return err } @@ -628,7 +599,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } } - if dn.openshiftContext.IsOpenshiftCluster() && !dn.openshiftContext.IsHypershift() { + if dn.platformHelpers.IsOpenshiftCluster() && !dn.platformHelpers.IsHypershift() { log.Log.Info("nodeStateSyncHandler(): pause MCP") if err := dn.pauseMCP(); err != nil { return err @@ -645,7 +616,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } } - if !reqReboot && !dn.useSystemdService { + if !reqReboot && !vars.UsingSystemdMode { // For BareMetal machines apply the generic plugin selectedPlugin, ok := dn.enabledPlugins[GenericPluginName] if ok { @@ -672,7 +643,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { if reqReboot { log.Log.Info("nodeStateSyncHandler(): reboot node") dn.eventRecorder.SendEvent("RebootNode", "Reboot node has been initiated") - rebootNode() + dn.rebootNode() return nil } @@ -689,7 +660,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { } } else { if !dn.nodeHasAnnotation(annoKey, annoIdle) { - if err := dn.annotateNode(dn.name, annoIdle); err != nil { + if err := dn.annotateNode(vars.NodeName, annoIdle); err != nil { log.Log.Error(err, "nodeStateSyncHandler(): failed to annotate node") return err } @@ -697,14 +668,14 @@ func (dn *Daemon) nodeStateSyncHandler() error { } log.Log.Info("nodeStateSyncHandler(): sync succeeded") dn.nodeState = latestState.DeepCopy() - if dn.useSystemdService { + if vars.UsingSystemdMode { dn.refreshCh <- Message{ syncStatus: sriovResult.SyncStatus, lastSyncError: sriovResult.LastSyncError, } } else { dn.refreshCh <- Message{ - syncStatus: syncStatusSucceeded, + syncStatus: consts.SyncStatusSucceeded, lastSyncError: "", } } @@ -739,16 +710,16 @@ func (dn *Daemon) completeDrain() error { } } - if dn.openshiftContext.IsOpenshiftCluster() && !dn.openshiftContext.IsHypershift() { + if dn.platformHelpers.IsOpenshiftCluster() && !dn.platformHelpers.IsHypershift() { log.Log.Info("completeDrain(): resume MCP", "mcp-name", dn.mcpName) pausePatch := []byte("{\"spec\":{\"paused\":false}}") - if _, err := dn.openshiftContext.McClient.MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}); err != nil { + if _, err := dn.platformHelpers.GetMcClient().MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}); err != nil { log.Log.Error(err, "completeDrain(): failed to resume MCP", "mcp-name", dn.mcpName) return err } } - if err := dn.annotateNode(dn.name, annoIdle); err != nil { + if err := dn.annotateNode(vars.NodeName, annoIdle); err != nil { log.Log.Error(err, "completeDrain(): failed to annotate node") return err } @@ -763,7 +734,7 @@ func (dn *Daemon) restartDevicePluginPod() error { var podToDelete string pods, err := dn.kubeClient.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{ LabelSelector: "app=sriov-device-plugin", - FieldSelector: "spec.nodeName=" + dn.name, + FieldSelector: "spec.nodeName=" + vars.NodeName, }) if err != nil { if errors.IsNotFound(err) { @@ -812,9 +783,9 @@ func (dn *Daemon) restartDevicePluginPod() error { return nil } -func rebootNode() { +func (dn *Daemon) rebootNode() { log.Log.Info("rebootNode(): trigger node reboot") - exit, err := utils.Chroot("/host") + exit, err := dn.HostHelpers.Chroot(consts.Host) if err != nil { log.Log.Error(err, "rebootNode(): chroot command failed") } @@ -837,7 +808,7 @@ func rebootNode() { func (dn *Daemon) annotateNode(node, value string) error { log.Log.Info("annotateNode(): Annotate node", "name", node, "value", value) - oldNode, err := dn.kubeClient.CoreV1().Nodes().Get(context.Background(), dn.name, metav1.GetOptions{}) + oldNode, err := dn.kubeClient.CoreV1().Nodes().Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { log.Log.Error(err, "annotateNode(): Failed to get node, retrying", "name", node) return err @@ -863,7 +834,7 @@ func (dn *Daemon) annotateNode(node, value string) error { return err } _, err = dn.kubeClient.CoreV1().Nodes().Patch(context.Background(), - dn.name, + vars.NodeName, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) @@ -881,7 +852,7 @@ func (dn *Daemon) getNodeMachinePool() error { log.Log.Error(nil, "getNodeMachinePool(): Failed to find the the desiredConfig Annotation") return fmt.Errorf("getNodeMachinePool(): Failed to find the the desiredConfig Annotation") } - mc, err := dn.openshiftContext.McClient.MachineconfigurationV1().MachineConfigs().Get(context.TODO(), desiredConfig, metav1.GetOptions{}) + mc, err := dn.platformHelpers.GetMcClient().MachineconfigurationV1().MachineConfigs().Get(context.TODO(), desiredConfig, metav1.GetOptions{}) if err != nil { log.Log.Error(err, "getNodeMachinePool(): Failed to get the desired Machine Config") return err @@ -907,7 +878,7 @@ func (dn *Daemon) getDrainLock(ctx context.Context, done chan bool) { }, Client: dn.kubeClient.CoordinationV1(), LockConfig: resourcelock.ResourceLockConfig{ - Identity: dn.name, + Identity: vars.NodeName, }, } @@ -930,7 +901,7 @@ func (dn *Daemon) getDrainLock(ctx context.Context, done chan bool) { } if dn.drainable { log.Log.V(2).Info("getDrainLock(): no other node is draining") - err = dn.annotateNode(dn.name, annoDraining) + err = dn.annotateNode(vars.NodeName, annoDraining) if err != nil { log.Log.Error(err, "getDrainLock(): failed to annotate node") continue @@ -952,7 +923,7 @@ func (dn *Daemon) pauseMCP() error { log.Log.Info("pauseMCP(): pausing MCP") var err error - mcpInformerFactory := mcfginformers.NewSharedInformerFactory(dn.openshiftContext.McClient, + mcpInformerFactory := mcfginformers.NewSharedInformerFactory(dn.platformHelpers.GetMcClient(), time.Second*30, ) mcpInformer := mcpInformerFactory.Machineconfiguration().V1().MachineConfigPools().Informer() @@ -967,7 +938,7 @@ func (dn *Daemon) pauseMCP() error { return } // Always get the latest object - newMcp, err := dn.openshiftContext.McClient.MachineconfigurationV1().MachineConfigPools().Get(ctx, dn.mcpName, metav1.GetOptions{}) + newMcp, err := dn.platformHelpers.GetMcClient().MachineconfigurationV1().MachineConfigPools().Get(ctx, dn.mcpName, metav1.GetOptions{}) if err != nil { log.Log.V(2).Error(err, "pauseMCP(): Failed to get MCP", "mcp-name", dn.mcpName) return @@ -987,12 +958,12 @@ func (dn *Daemon) pauseMCP() error { } log.Log.Info("pauseMCP(): pause MCP", "mcp-name", dn.mcpName) pausePatch := []byte("{\"spec\":{\"paused\":true}}") - _, err = dn.openshiftContext.McClient.MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}) + _, err = dn.platformHelpers.GetMcClient().MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}) if err != nil { log.Log.V(2).Error(err, "pauseMCP(): failed to pause MCP", "mcp-name", dn.mcpName) return } - err = dn.annotateNode(dn.name, annoMcpPaused) + err = dn.annotateNode(vars.NodeName, annoMcpPaused) if err != nil { log.Log.V(2).Error(err, "pauseMCP(): Failed to annotate node") return @@ -1003,12 +974,12 @@ func (dn *Daemon) pauseMCP() error { if paused { log.Log.Info("pauseMCP(): MCP is processing, resume MCP", "mcp-name", dn.mcpName) pausePatch := []byte("{\"spec\":{\"paused\":false}}") - _, err = dn.openshiftContext.McClient.MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}) + _, err = dn.platformHelpers.GetMcClient().MachineconfigurationV1().MachineConfigPools().Patch(context.Background(), dn.mcpName, types.MergePatchType, pausePatch, metav1.PatchOptions{}) if err != nil { log.Log.V(2).Error(err, "pauseMCP(): fail to resume MCP", "mcp-name", dn.mcpName) return } - err = dn.annotateNode(dn.name, annoDraining) + err = dn.annotateNode(vars.NodeName, annoDraining) if err != nil { log.Log.V(2).Error(err, "pauseMCP(): Failed to annotate node") return @@ -1057,7 +1028,7 @@ func (dn *Daemon) drainNode() error { log.Log.Error(err, "cordon failed, retrying") return false, nil } - err = drain.RunNodeDrain(dn.drainer, dn.name) + err = drain.RunNodeDrain(dn.drainer, vars.NodeName) if err == nil { return true, nil } @@ -1077,28 +1048,29 @@ func (dn *Daemon) drainNode() error { return nil } +// TODO: move this to host interface func (dn *Daemon) tryCreateSwitchdevUdevRule() error { log.Log.V(2).Info("tryCreateSwitchdevUdevRule()") nodeState, nodeStateErr := dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get( context.Background(), - dn.name, + vars.NodeName, metav1.GetOptions{}, ) if nodeStateErr != nil { - log.Log.Error(nodeStateErr, "could not fetch node state, skip updating switchdev udev rules", "name", dn.name) + log.Log.Error(nodeStateErr, "could not fetch node state, skip updating switchdev udev rules", "name", vars.NodeName) return nil } var newContent string - filePath := path.Join(utils.FilesystemRoot, "/host/etc/udev/rules.d/20-switchdev.rules") + filePath := path.Join(vars.FilesystemRoot, "/host/etc/udev/rules.d/20-switchdev.rules") for _, ifaceStatus := range nodeState.Status.Interfaces { if ifaceStatus.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { - switchID, err := utils.GetPhysSwitchID(ifaceStatus.Name) + switchID, err := dn.HostHelpers.GetPhysSwitchID(ifaceStatus.Name) if err != nil { return err } - portName, err := utils.GetPhysPortName(ifaceStatus.Name) + portName, err := dn.HostHelpers.GetPhysPortName(ifaceStatus.Name) if err != nil { return err } @@ -1126,7 +1098,7 @@ func (dn *Daemon) tryCreateSwitchdevUdevRule() error { } var stdout, stderr bytes.Buffer - cmd := exec.Command("/bin/bash", path.Join(utils.FilesystemRoot, udevScriptsPath)) + cmd := exec.Command("/bin/bash", path.Join(vars.FilesystemRoot, udevScriptsPath)) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { @@ -1158,5 +1130,5 @@ func (dn *Daemon) prepareNMUdevRule() error { supportedVfIds = append(supportedVfIds, vfID) } - return utils.PrepareNMUdevRule(supportedVfIds) + return dn.HostHelpers.PrepareNMUdevRule(supportedVfIds) } diff --git a/pkg/daemon/daemon_test.go b/pkg/daemon/daemon_test.go index 5300a1a65..b804888fa 100644 --- a/pkg/daemon/daemon_test.go +++ b/pkg/daemon/daemon_test.go @@ -5,6 +5,7 @@ import ( "flag" "testing" + "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -12,14 +13,18 @@ import ( fakek8s "k8s.io/client-go/kubernetes/fake" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + mock_platforms "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/mock" "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" fakesnclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned/fake" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + mock_helper "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper/mock" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/fake" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/generic" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var FakeSupportedNicIDs corev1.ConfigMap = corev1.ConfigMap{ @@ -95,29 +100,44 @@ var _ = Describe("Config Daemon", func() { } var err error - utils.FilesystemRoot, cleanFakeFs, err = fakeFs.Use() + vars.FilesystemRoot, cleanFakeFs, err = fakeFs.Use() Expect(err).ToNot(HaveOccurred()) + vars.UsingSystemdMode = false + vars.NodeName = "test-node" + vars.PlatformType = consts.Baremetal + kubeClient := fakek8s.NewSimpleClientset(&FakeSupportedNicIDs, &SriovDevicePluginPod) client := fakesnclientset.NewSimpleClientset() err = sriovnetworkv1.InitNicIDMapFromConfigMap(kubeClient, namespace) Expect(err).ToNot(HaveOccurred()) - er := NewEventRecorder(client, "test-node", kubeClient) + er := NewEventRecorder(client, kubeClient) + + t := GinkgoT() + mockCtrl := gomock.NewController(t) + platformHelper := mock_platforms.NewMockInterface(mockCtrl) + platformHelper.EXPECT().GetFlavor().Return(openshift.OpenshiftFlavorDefault).AnyTimes() + platformHelper.EXPECT().IsOpenshiftCluster().Return(false).AnyTimes() + platformHelper.EXPECT().IsHypershift().Return(false).AnyTimes() - sut = New("test-node", + vendorHelper := mock_helper.NewMockHostHelpersInterface(mockCtrl) + vendorHelper.EXPECT().TryEnableRdma().Return(true, nil).AnyTimes() + vendorHelper.EXPECT().TryEnableVhostNet().AnyTimes() + vendorHelper.EXPECT().TryEnableTun().AnyTimes() + vendorHelper.EXPECT().PrepareNMUdevRule([]string{"0x1014", "0x154c"}).Return(nil).AnyTimes() + + sut = New( client, kubeClient, - &utils.OpenshiftContext{IsOpenShiftCluster: false, OpenshiftFlavor: ""}, + vendorHelper, + platformHelper, exitCh, stopCh, syncCh, refreshCh, - utils.Baremetal, - false, er, - false, ) sut.enabledPlugins = map[string]plugin.VendorPlugin{generic.PluginName: &fake.FakePlugin{}} @@ -236,66 +256,6 @@ var _ = Describe("Config Daemon", func() { Expect(sut.nodeState.GetGeneration()).To(BeNumerically("==", 777)) }) }) - - Context("isNodeDraining", func() { - - It("for a non-Openshift cluster", func() { - sut.openshiftContext = &utils.OpenshiftContext{IsOpenShiftCluster: false} - - sut.node = &corev1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-node", - Annotations: map[string]string{}}} - - Expect(sut.isNodeDraining()).To(BeFalse()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining" - Expect(sut.isNodeDraining()).To(BeTrue()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining_MCP_Paused" - Expect(sut.isNodeDraining()).To(BeTrue()) - }) - - It("for an Openshift cluster", func() { - sut.openshiftContext = &utils.OpenshiftContext{ - IsOpenShiftCluster: true, - OpenshiftFlavor: utils.OpenshiftFlavorDefault, - } - - sut.node = &corev1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-node", - Annotations: map[string]string{}}} - - Expect(sut.isNodeDraining()).To(BeFalse()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining" - Expect(sut.isNodeDraining()).To(BeTrue()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining_MCP_Paused" - Expect(sut.isNodeDraining()).To(BeTrue()) - }) - - It("for an Openshift Hypershift cluster", func() { - sut.openshiftContext = &utils.OpenshiftContext{ - IsOpenShiftCluster: true, - OpenshiftFlavor: utils.OpenshiftFlavorHypershift, - } - - sut.node = &corev1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-node", - Annotations: map[string]string{}}} - - Expect(sut.isNodeDraining()).To(BeFalse()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining" - Expect(sut.isNodeDraining()).To(BeTrue()) - - sut.node.Annotations["sriovnetwork.openshift.io/state"] = "Draining_MCP_Paused" - Expect(sut.isNodeDraining()).To(BeTrue()) - }) - }) }) func createSriovNetworkNodeState(c snclientset.Interface, nodeState *sriovnetworkv1.SriovNetworkNodeState) error { diff --git a/pkg/daemon/event_recorder.go b/pkg/daemon/event_recorder.go index 2860cf84a..ed9b34ee7 100644 --- a/pkg/daemon/event_recorder.go +++ b/pkg/daemon/event_recorder.go @@ -12,24 +12,23 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) type EventRecorder struct { client snclientset.Interface - node string eventRecorder record.EventRecorder eventBroadcaster record.EventBroadcaster } // NewEventRecorder Create a new EventRecorder -func NewEventRecorder(c snclientset.Interface, n string, kubeclient kubernetes.Interface) *EventRecorder { +func NewEventRecorder(c snclientset.Interface, kubeclient kubernetes.Interface) *EventRecorder { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartStructuredLogging(4) eventBroadcaster.StartRecordingToSink(&typedv1core.EventSinkImpl{Interface: kubeclient.CoreV1().Events("")}) eventRecorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "config-daemon"}) return &EventRecorder{ client: c, - node: n, eventRecorder: eventRecorder, eventBroadcaster: eventBroadcaster, } @@ -37,9 +36,9 @@ func NewEventRecorder(c snclientset.Interface, n string, kubeclient kubernetes.I // SendEvent Send an Event on the NodeState object func (e *EventRecorder) SendEvent(eventType string, msg string) { - nodeState, err := e.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), e.node, metav1.GetOptions{}) + nodeState, err := e.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { - log.Log.V(2).Error(err, "SendEvent(): Failed to fetch node state, skip SendEvent", "name", e.node) + log.Log.V(2).Error(err, "SendEvent(): Failed to fetch node state, skip SendEvent", "name", vars.NodeName) return } e.eventRecorder.Event(nodeState, corev1.EventTypeNormal, eventType, msg) diff --git a/pkg/daemon/plugin.go b/pkg/daemon/plugin.go index 09c69271c..38e1d9d73 100644 --- a/pkg/daemon/plugin.go +++ b/pkg/daemon/plugin.go @@ -6,17 +6,18 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" genericplugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/generic" intelplugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/intel" k8splugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/k8s" mellanoxplugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/mellanox" virtualplugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/virtual" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) -var VendorPluginMap = map[string]func() (plugin.VendorPlugin, error){ +var VendorPluginMap = map[string]func(helpers helper.HostHelpersInterface) (plugin.VendorPlugin, error){ "8086": intelplugin.NewIntelPlugin, "15b3": mellanoxplugin.NewMellanoxPlugin, } @@ -29,33 +30,33 @@ var ( K8sPlugin = k8splugin.NewK8sPlugin ) -func enablePlugins(platform utils.PlatformType, useSystemdService bool, ns *sriovnetworkv1.SriovNetworkNodeState, hostManager host.HostManagerInterface, storeManager utils.StoreManagerInterface) (map[string]plugin.VendorPlugin, error) { +func enablePlugins(ns *sriovnetworkv1.SriovNetworkNodeState, helpers helper.HostHelpersInterface) (map[string]plugin.VendorPlugin, error) { log.Log.Info("enableVendorPlugins(): enabling plugins") enabledPlugins := map[string]plugin.VendorPlugin{} - if platform == utils.VirtualOpenStack { - virtualPlugin, err := VirtualPlugin(false) + if vars.PlatformType == consts.VirtualOpenStack { + virtualPlugin, err := VirtualPlugin(helpers) if err != nil { log.Log.Error(err, "enableVendorPlugins(): failed to load the virtual plugin") return nil, err } enabledPlugins[virtualPlugin.Name()] = virtualPlugin } else { - enabledVendorPlugins, err := registerVendorPlugins(ns) + enabledVendorPlugins, err := registerVendorPlugins(ns, helpers) if err != nil { return nil, err } enabledPlugins = enabledVendorPlugins - if utils.ClusterType != utils.ClusterTypeOpenshift { - k8sPlugin, err := K8sPlugin(useSystemdService) + if vars.ClusterType != consts.ClusterTypeOpenshift { + k8sPlugin, err := K8sPlugin(helpers) if err != nil { log.Log.Error(err, "enableVendorPlugins(): failed to load the k8s plugin") return nil, err } enabledPlugins[k8sPlugin.Name()] = k8sPlugin } - genericPlugin, err := GenericPlugin(false, hostManager, storeManager) + genericPlugin, err := GenericPlugin(helpers) if err != nil { log.Log.Error(err, "enableVendorPlugins(): failed to load the generic plugin") return nil, err @@ -71,12 +72,12 @@ func enablePlugins(platform utils.PlatformType, useSystemdService bool, ns *srio return enabledPlugins, nil } -func registerVendorPlugins(ns *sriovnetworkv1.SriovNetworkNodeState) (map[string]plugin.VendorPlugin, error) { +func registerVendorPlugins(ns *sriovnetworkv1.SriovNetworkNodeState, helpers helper.HostHelpersInterface) (map[string]plugin.VendorPlugin, error) { vendorPlugins := map[string]plugin.VendorPlugin{} for _, iface := range ns.Status.Interfaces { if val, ok := VendorPluginMap[iface.Vendor]; ok { - plug, err := val() + plug, err := val(helpers) if err != nil { log.Log.Error(err, "registerVendorPlugins(): failed to load plugin", "plugin-name", plug.Name()) return vendorPlugins, fmt.Errorf("registerVendorPlugins(): failed to load the %s plugin error: %v", plug.Name(), err) diff --git a/pkg/daemon/writer.go b/pkg/daemon/writer.go index a9e65a417..1a83c77d8 100644 --- a/pkg/daemon/writer.go +++ b/pkg/daemon/writer.go @@ -16,7 +16,10 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" snclientset "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/client/clientset/versioned" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) const ( @@ -25,62 +28,51 @@ const ( ) type NodeStateStatusWriter struct { - client snclientset.Interface - node string - status sriovnetworkv1.SriovNetworkNodeStateStatus - OnHeartbeatFailure func() - openStackDevicesInfo utils.OSPDevicesInfo - withUnsupportedDevices bool - storeManager utils.StoreManagerInterface - eventRecorder *EventRecorder + client snclientset.Interface + status sriovnetworkv1.SriovNetworkNodeStateStatus + OnHeartbeatFailure func() + platformHelper platforms.Interface + hostHelper helper.HostHelpersInterface + eventRecorder *EventRecorder } // NewNodeStateStatusWriter Create a new NodeStateStatusWriter -func NewNodeStateStatusWriter(c snclientset.Interface, n string, f func(), er *EventRecorder, devMode bool) *NodeStateStatusWriter { +func NewNodeStateStatusWriter(c snclientset.Interface, + f func(), er *EventRecorder, + hostHelper helper.HostHelpersInterface, + platformHelper platforms.Interface) *NodeStateStatusWriter { return &NodeStateStatusWriter{ - client: c, - node: n, - OnHeartbeatFailure: f, - eventRecorder: er, - withUnsupportedDevices: devMode, + client: c, + OnHeartbeatFailure: f, + eventRecorder: er, + hostHelper: hostHelper, + platformHelper: platformHelper, } } // RunOnce initial the interface status for both baremetal and virtual environments -func (w *NodeStateStatusWriter) RunOnce(destDir string, platformType utils.PlatformType) error { +func (w *NodeStateStatusWriter) RunOnce() error { log.Log.V(0).Info("RunOnce()") msg := Message{} - storeManager, err := utils.NewStoreManager(false) - if err != nil { - log.Log.Error(err, "failed to create store manager") - return err - } - w.storeManager = storeManager - - if platformType == utils.VirtualOpenStack { - ns, err := w.getCheckPointNodeState(destDir) + if vars.PlatformType == consts.VirtualOpenStack { + ns, err := w.getCheckPointNodeState() if err != nil { return err } if ns == nil { - metaData, networkData, err := utils.GetOpenstackData(true) - if err != nil { - log.Log.Error(err, "RunOnce(): failed to read OpenStack data") - } - - w.openStackDevicesInfo, err = utils.CreateOpenstackDevicesInfo(metaData, networkData) + err = w.platformHelper.CreateOpenstackDevicesInfo() if err != nil { return err } } else { - w.openStackDevicesInfo = utils.CreateOpenstackDevicesInfoFromNodeStatus(ns) + w.platformHelper.CreateOpenstackDevicesInfoFromNodeStatus(ns) } } log.Log.V(0).Info("RunOnce(): first poll for nic status") - if err := w.pollNicStatus(platformType); err != nil { + if err := w.pollNicStatus(); err != nil { log.Log.Error(err, "RunOnce(): first poll failed") } @@ -88,12 +80,12 @@ func (w *NodeStateStatusWriter) RunOnce(destDir string, platformType utils.Platf if err != nil { log.Log.Error(err, "RunOnce(): first writing to node status failed") } - return w.writeCheckpointFile(ns, destDir) + return w.writeCheckpointFile(ns) } // Run reads from the writer channel and sets the interface status. It will // return if the stop channel is closed. Intended to be run via a goroutine. -func (w *NodeStateStatusWriter) Run(stop <-chan struct{}, refresh <-chan Message, syncCh chan<- struct{}, platformType utils.PlatformType) error { +func (w *NodeStateStatusWriter) Run(stop <-chan struct{}, refresh <-chan Message, syncCh chan<- struct{}) error { log.Log.V(0).Info("Run(): start writer") msg := Message{} @@ -104,7 +96,7 @@ func (w *NodeStateStatusWriter) Run(stop <-chan struct{}, refresh <-chan Message return nil case msg = <-refresh: log.Log.V(0).Info("Run(): refresh trigger") - if err := w.pollNicStatus(platformType); err != nil { + if err := w.pollNicStatus(); err != nil { continue } _, err := w.setNodeStateStatus(msg) @@ -114,7 +106,7 @@ func (w *NodeStateStatusWriter) Run(stop <-chan struct{}, refresh <-chan Message syncCh <- struct{}{} case <-time.After(30 * time.Second): log.Log.V(2).Info("Run(): period refresh") - if err := w.pollNicStatus(platformType); err != nil { + if err := w.pollNicStatus(); err != nil { continue } w.setNodeStateStatus(msg) @@ -122,15 +114,15 @@ func (w *NodeStateStatusWriter) Run(stop <-chan struct{}, refresh <-chan Message } } -func (w *NodeStateStatusWriter) pollNicStatus(platformType utils.PlatformType) error { +func (w *NodeStateStatusWriter) pollNicStatus() error { log.Log.V(2).Info("pollNicStatus()") var iface []sriovnetworkv1.InterfaceExt var err error - if platformType == utils.VirtualOpenStack { - iface, err = utils.DiscoverSriovDevicesVirtual(w.openStackDevicesInfo) + if vars.PlatformType == consts.VirtualOpenStack { + iface, err = w.platformHelper.DiscoverSriovDevicesVirtual() } else { - iface, err = utils.DiscoverSriovDevices(w.withUnsupportedDevices, w.storeManager) + iface, err = w.hostHelper.DiscoverSriovDevices(w.hostHelper) } if err != nil { return err @@ -177,7 +169,7 @@ func (w *NodeStateStatusWriter) updateNodeStateStatusRetry(f func(*sriovnetworkv func (w *NodeStateStatusWriter) setNodeStateStatus(msg Message) (*sriovnetworkv1.SriovNetworkNodeState, error) { nodeState, err := w.updateNodeStateStatusRetry(func(nodeState *sriovnetworkv1.SriovNetworkNodeState) { nodeState.Status.Interfaces = w.status.Interfaces - if msg.lastSyncError != "" || msg.syncStatus == syncStatusSucceeded { + if msg.lastSyncError != "" || msg.syncStatus == consts.SyncStatusSucceeded { // clear lastSyncError when sync Succeeded nodeState.Status.LastSyncError = msg.lastSyncError } @@ -215,33 +207,33 @@ func (w *NodeStateStatusWriter) getNodeState() (*sriovnetworkv1.SriovNetworkNode var lastErr error var n *sriovnetworkv1.SriovNetworkNodeState err := wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) { - n, lastErr = w.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), w.node, metav1.GetOptions{}) + n, lastErr = w.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if lastErr == nil { return true, nil } - log.Log.Error(lastErr, "getNodeState(): Failed to fetch node state, close all connections and retry...", "name", w.node) + log.Log.Error(lastErr, "getNodeState(): Failed to fetch node state, close all connections and retry...", "name", vars.NodeName) // Use the Get() also as an client-go keepalive indicator for the TCP connection. w.OnHeartbeatFailure() return false, nil }) if err != nil { if err == wait.ErrWaitTimeout { - return nil, errors.Wrapf(lastErr, "Timed out trying to fetch node %s", w.node) + return nil, errors.Wrapf(lastErr, "Timed out trying to fetch node %s", vars.NodeName) } return nil, err } return n, nil } -func (w *NodeStateStatusWriter) writeCheckpointFile(ns *sriovnetworkv1.SriovNetworkNodeState, destDir string) error { - configdir := filepath.Join(destDir, CheckpointFileName) +func (w *NodeStateStatusWriter) writeCheckpointFile(ns *sriovnetworkv1.SriovNetworkNodeState) error { + configdir := filepath.Join(vars.Destdir, CheckpointFileName) file, err := os.OpenFile(configdir, os.O_RDWR|os.O_CREATE, 0644) if err != nil { return err } defer file.Close() log.Log.Info("writeCheckpointFile(): try to decode the checkpoint file") - if err = json.NewDecoder(file).Decode(&utils.InitialState); err != nil { + if err = json.NewDecoder(file).Decode(&sriovnetworkv1.InitialState); err != nil { log.Log.V(2).Error(err, "writeCheckpointFile(): fail to decode, writing new file instead") log.Log.Info("writeCheckpointFile(): write checkpoint file") if err = file.Truncate(0); err != nil { @@ -253,14 +245,14 @@ func (w *NodeStateStatusWriter) writeCheckpointFile(ns *sriovnetworkv1.SriovNetw if err = json.NewEncoder(file).Encode(*ns); err != nil { return err } - utils.InitialState = *ns + sriovnetworkv1.InitialState = *ns } return nil } -func (w *NodeStateStatusWriter) getCheckPointNodeState(destDir string) (*sriovnetworkv1.SriovNetworkNodeState, error) { +func (w *NodeStateStatusWriter) getCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNodeState, error) { log.Log.Info("getCheckPointNodeState()") - configdir := filepath.Join(destDir, CheckpointFileName) + configdir := filepath.Join(vars.Destdir, CheckpointFileName) file, err := os.OpenFile(configdir, os.O_RDONLY, 0644) if err != nil { if os.IsNotExist(err) { @@ -269,9 +261,9 @@ func (w *NodeStateStatusWriter) getCheckPointNodeState(destDir string) (*sriovne return nil, err } defer file.Close() - if err = json.NewDecoder(file).Decode(&utils.InitialState); err != nil { + if err = json.NewDecoder(file).Decode(&sriovnetworkv1.InitialState); err != nil { return nil, err } - return &utils.InitialState, nil + return &sriovnetworkv1.InitialState, nil } diff --git a/pkg/plugins/generic/generic_plugin.go b/pkg/plugins/generic/generic_plugin.go index 44069407e..88aa38549 100644 --- a/pkg/plugins/generic/generic_plugin.go +++ b/pkg/plugins/generic/generic_plugin.go @@ -3,6 +3,7 @@ package generic import ( "bytes" "errors" + "fmt" "os/exec" "reflect" "strconv" @@ -12,10 +13,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" ) var PluginName = "generic_plugin" @@ -54,34 +57,33 @@ type GenericPlugin struct { LastState *sriovnetworkv1.SriovNetworkNodeState DriverStateMap DriverStateMapType DesiredKernelArgs map[string]bool - RunningOnHost bool - HostManager host.HostManagerInterface - StoreManager utils.StoreManagerInterface + pfsToSkip map[string]bool + helpers helper.HostHelpersInterface } const scriptsPath = "bindata/scripts/enable-kargs.sh" // Initialize our plugin and set up initial values -func NewGenericPlugin(runningOnHost bool, hostManager host.HostManagerInterface, storeManager utils.StoreManagerInterface) (plugin.VendorPlugin, error) { +func NewGenericPlugin(helpers helper.HostHelpersInterface) (plugin.VendorPlugin, error) { driverStateMap := make(map[uint]*DriverState) driverStateMap[Vfio] = &DriverState{ DriverName: vfioPciDriver, - DeviceType: constants.DeviceTypeVfioPci, + DeviceType: consts.DeviceTypeVfioPci, VdpaType: "", NeedDriverFunc: needDriverCheckDeviceType, DriverLoaded: false, } driverStateMap[VirtioVdpa] = &DriverState{ DriverName: virtioVdpaDriver, - DeviceType: constants.DeviceTypeNetDevice, - VdpaType: constants.VdpaTypeVirtio, + DeviceType: consts.DeviceTypeNetDevice, + VdpaType: consts.VdpaTypeVirtio, NeedDriverFunc: needDriverCheckVdpaType, DriverLoaded: false, } driverStateMap[VhostVdpa] = &DriverState{ DriverName: vhostVdpaDriver, - DeviceType: constants.DeviceTypeNetDevice, - VdpaType: constants.VdpaTypeVhost, + DeviceType: consts.DeviceTypeNetDevice, + VdpaType: consts.VdpaTypeVhost, NeedDriverFunc: needDriverCheckVdpaType, DriverLoaded: false, } @@ -90,9 +92,8 @@ func NewGenericPlugin(runningOnHost bool, hostManager host.HostManagerInterface, SpecVersion: "1.0", DriverStateMap: driverStateMap, DesiredKernelArgs: make(map[string]bool), - RunningOnHost: runningOnHost, - HostManager: hostManager, - StoreManager: storeManager, + pfsToSkip: make(map[string]bool), + helpers: helpers, }, nil } @@ -109,9 +110,6 @@ func (p *GenericPlugin) Spec() string { // OnNodeStateChange Invoked when SriovNetworkNodeState CR is created or updated, return if need drain and/or reboot node func (p *GenericPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeState) (needDrain bool, needReboot bool, err error) { log.Log.Info("generic-plugin OnNodeStateChange()") - needDrain = false - needReboot = false - err = nil p.DesireState = new needDrain = p.needDrainNode(new.Spec.Interfaces, new.Status.Interfaces) @@ -130,7 +128,7 @@ func (p *GenericPlugin) syncDriverState() error { for _, driverState := range p.DriverStateMap { if !driverState.DriverLoaded && driverState.NeedDriverFunc(p.DesireState, driverState) { log.Log.V(2).Info("loading driver", "name", driverState.DriverName) - if err := p.HostManager.LoadKernelModule(driverState.DriverName); err != nil { + if err := p.helpers.LoadKernelModule(driverState.DriverName); err != nil { log.Log.Error(err, "generic-plugin syncDriverState(): fail to load kmod", "name", driverState.DriverName) return err } @@ -156,27 +154,19 @@ func (p *GenericPlugin) Apply() error { return err } - // Create a map with all the PFs we will need to configure - // we need to create it here before we access the host file system using the chroot function - // because the skipConfigVf needs the mstconfig package that exist only inside the sriov-config-daemon file system - pfsToSkip, err := utils.GetPfsToSkip(p.DesireState) - if err != nil { - return err - } - // When calling from systemd do not try to chroot - if !p.RunningOnHost { - exit, err := utils.Chroot("/host") + if !vars.UsingSystemdMode { + exit, err := p.helpers.Chroot(consts.Host) if err != nil { return err } defer exit() } - if err := utils.SyncNodeState(p.DesireState, pfsToSkip); err != nil { + if err := p.helpers.ConfigSriovInterfaces(p.helpers, p.DesireState.Spec.Interfaces, p.DesireState.Status.Interfaces, p.pfsToSkip); err != nil { // Catch the "cannot allocate memory" error and try to use PCI realloc if errors.Is(err, syscall.ENOMEM) { - p.addToDesiredKernelArgs(utils.KernelArgPciRealloc) + p.addToDesiredKernelArgs(consts.KernelArgPciRealloc) } return err } @@ -217,7 +207,7 @@ func setKernelArg(karg string) (bool, error) { if err := cmd.Run(); err != nil { // if grubby is not there log and assume kernel args are set correctly. - if isCommandNotFound(err) { + if utils.IsCommandNotFound(err) { log.Log.Error(err, "generic-plugin setKernelArg(): grubby or ostree command not found. Please ensure that kernel arg are set", "kargs", karg) return false, nil @@ -236,15 +226,6 @@ func setKernelArg(karg string) (bool, error) { return false, err } -func isCommandNotFound(err error) bool { - if exitErr, ok := err.(*exec.ExitError); ok { - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok && status.ExitStatus() == 127 { - return true - } - } - return false -} - // addToDesiredKernelArgs Should be called to queue a kernel arg to be added to the node. func (p *GenericPlugin) addToDesiredKernelArgs(karg string) { if _, ok := p.DesiredKernelArgs[karg]; !ok { @@ -259,12 +240,12 @@ func (p *GenericPlugin) syncDesiredKernelArgs() (bool, error) { if len(p.DesiredKernelArgs) == 0 { return false, nil } - kargs, err := utils.GetCurrentKernelArgs(false) + kargs, err := p.helpers.GetCurrentKernelArgs() if err != nil { return false, err } for desiredKarg, attempted := range p.DesiredKernelArgs { - set := utils.IsKernelArgsSet(kargs, desiredKarg) + set := p.helpers.IsKernelArgsSet(kargs, desiredKarg) if !set { if attempted { log.Log.V(2).Info("generic-plugin syncDesiredKernelArgs(): previously attempted to set kernel arg", @@ -302,7 +283,7 @@ func (p *GenericPlugin) needDrainNode(desired sriovnetworkv1.Interfaces, current "address", iface.PciAddress) break } - if utils.NeedUpdate(&iface, &ifaceStatus) { + if sriovnetworkv1.NeedToUpdateSriov(&iface, &ifaceStatus) { log.Log.V(2).Info("generic-plugin needDrainNode(): need drain, for PCI address request update", "address", iface.PciAddress) needDrain = true @@ -314,7 +295,7 @@ func (p *GenericPlugin) needDrainNode(desired sriovnetworkv1.Interfaces, current } if !configured && ifaceStatus.NumVfs > 0 { // load the PF info - pfStatus, exist, err := p.StoreManager.LoadPfsStatus(ifaceStatus.PciAddress) + pfStatus, exist, err := p.helpers.LoadPfsStatus(ifaceStatus.PciAddress) if err != nil { log.Log.Error(err, "generic-plugin needDrainNode(): failed to load info about PF status for pci device", "address", ifaceStatus.PciAddress) @@ -347,8 +328,8 @@ func (p *GenericPlugin) needDrainNode(desired sriovnetworkv1.Interfaces, current func (p *GenericPlugin) addVfioDesiredKernelArg(state *sriovnetworkv1.SriovNetworkNodeState) { driverState := p.DriverStateMap[Vfio] if !driverState.DriverLoaded && driverState.NeedDriverFunc(state, driverState) { - p.addToDesiredKernelArgs(utils.KernelArgIntelIommu) - p.addToDesiredKernelArgs(utils.KernelArgIommuPt) + p.addToDesiredKernelArgs(consts.KernelArgIntelIommu) + p.addToDesiredKernelArgs(consts.KernelArgIommuPt) } } @@ -366,7 +347,16 @@ func (p *GenericPlugin) needRebootNode(state *sriovnetworkv1.SriovNetworkNodeSta needReboot = true } - updateNode, err = utils.WriteSwitchdevConfFile(state) + // Create a map with all the PFs we will need to configure + // we need to create it here before we access the host file system using the chroot function + // because the skipConfigVf needs the mstconfig package that exist only inside the sriov-config-daemon file system + pfsToSkip, err := getPfsToSkip(p.DesireState, p.helpers) + if err != nil { + return false, err + } + p.pfsToSkip = pfsToSkip + + updateNode, err = p.helpers.WriteSwitchdevConfFile(state, p.pfsToSkip) if err != nil { log.Log.Error(err, "generic-plugin needRebootNode(): fail to write switchdev device config file") return false, err @@ -379,6 +369,53 @@ func (p *GenericPlugin) needRebootNode(state *sriovnetworkv1.SriovNetworkNodeSta return needReboot, nil } +// getPfsToSkip return a map of devices pci addresses to should be configured via systemd instead if the legacy mode +// we skip devices in switchdev mode and Bluefield card in ConnectX mode +func getPfsToSkip(ns *sriovnetworkv1.SriovNetworkNodeState, mlxHelper mlx.MellanoxInterface) (map[string]bool, error) { + pfsToSkip := map[string]bool{} + for _, ifaceStatus := range ns.Status.Interfaces { + for _, iface := range ns.Spec.Interfaces { + if iface.PciAddress == ifaceStatus.PciAddress { + skip, err := skipConfigVf(iface, ifaceStatus, mlxHelper) + if err != nil { + log.Log.Error(err, "GetPfsToSkip(): fail to check for skip VFs", "device", iface.PciAddress) + return pfsToSkip, err + } + pfsToSkip[iface.PciAddress] = skip + break + } + } + } + + return pfsToSkip, nil +} + +// skipConfigVf Use systemd service to configure switchdev mode or BF-2 NICs in OpenShift +func skipConfigVf(ifSpec sriovnetworkv1.Interface, ifStatus sriovnetworkv1.InterfaceExt, mlxHelper mlx.MellanoxInterface) (bool, error) { + if ifSpec.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev { + log.Log.V(2).Info("skipConfigVf(): skip config VF for switchdev device") + return true, nil + } + + // NVIDIA BlueField 2 and BlueField3 in OpenShift + if vars.ClusterType == consts.ClusterTypeOpenshift && ifStatus.Vendor == mlx.VendorMellanox && (ifStatus.DeviceID == mlx.DeviceBF2 || ifStatus.DeviceID == mlx.DeviceBF3) { + // TODO: remove this when switch to the systemd configuration support. + mode, err := mlxHelper.GetMellanoxBlueFieldMode(ifStatus.PciAddress) + if err != nil { + return false, fmt.Errorf("failed to read Mellanox Bluefield card mode for %s,%v", ifStatus.PciAddress, err) + } + + if mode == mlx.BluefieldConnectXMode { + return false, nil + } + + log.Log.V(2).Info("skipConfigVf(): skip config VF for Bluefiled card on DPU mode") + return true, nil + } + + return false, nil +} + // ////////////// for testing purposes only /////////////////////// func (p *GenericPlugin) getDriverStateMap() DriverStateMapType { return p.DriverStateMap diff --git a/pkg/plugins/generic/generic_plugin_test.go b/pkg/plugins/generic/generic_plugin_test.go index e1211b392..881fc87d4 100644 --- a/pkg/plugins/generic/generic_plugin_test.go +++ b/pkg/plugins/generic/generic_plugin_test.go @@ -8,9 +8,8 @@ import ( . "github.com/onsi/gomega" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - mock_host "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/mock" + mock_helper "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper/mock" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" - mock_utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils/mock" ) func TestGenericPlugin(t *testing.T) { @@ -24,16 +23,16 @@ var _ = Describe("Generic plugin", func() { genericPlugin plugin.VendorPlugin err error ctrl *gomock.Controller - mockHost *mock_host.MockHostManagerInterface - mockStore *mock_utils.MockStoreManagerInterface + hostHelper *mock_helper.MockHostHelpersInterface ) BeforeEach(func() { t = GinkgoT() ctrl = gomock.NewController(t) - mockHost = mock_host.NewMockHostManagerInterface(ctrl) - mockStore = mock_utils.NewMockStoreManagerInterface(ctrl) - genericPlugin, err = NewGenericPlugin(false, mockHost, mockStore) + + hostHelper = mock_helper.NewMockHostHelpersInterface(ctrl) + + genericPlugin, err = NewGenericPlugin(hostHelper) Expect(err).ToNot(HaveOccurred()) }) @@ -79,6 +78,7 @@ var _ = Describe("Generic plugin", func() { }, } + hostHelper.EXPECT().WriteSwitchdevConfFile(networkNodeState, map[string]bool{"0000:00:00.0": false}).Return(false, nil) needDrain, needReboot, err := genericPlugin.OnNodeStateChange(networkNodeState) Expect(err).ToNot(HaveOccurred()) Expect(needReboot).To(BeFalse()) @@ -134,6 +134,7 @@ var _ = Describe("Generic plugin", func() { }, } + hostHelper.EXPECT().WriteSwitchdevConfFile(networkNodeState, map[string]bool{"0000:00:00.0": false}).Return(false, nil) needDrain, needReboot, err := genericPlugin.OnNodeStateChange(networkNodeState) Expect(err).ToNot(HaveOccurred()) Expect(needReboot).To(BeFalse()) diff --git a/pkg/plugins/intel/intel_plugin.go b/pkg/plugins/intel/intel_plugin.go index bf032652e..1c64a47fb 100644 --- a/pkg/plugins/intel/intel_plugin.go +++ b/pkg/plugins/intel/intel_plugin.go @@ -4,6 +4,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" ) @@ -16,7 +17,7 @@ type IntelPlugin struct { LastState *sriovnetworkv1.SriovNetworkNodeState } -func NewIntelPlugin() (plugin.VendorPlugin, error) { +func NewIntelPlugin(helpers helper.HostHelpersInterface) (plugin.VendorPlugin, error) { return &IntelPlugin{ PluginName: PluginName, SpecVersion: "1.0", diff --git a/pkg/plugins/k8s/k8s_plugin.go b/pkg/plugins/k8s/k8s_plugin.go index 4cbcc818e..1bf70eab1 100644 --- a/pkg/plugins/k8s/k8s_plugin.go +++ b/pkg/plugins/k8s/k8s_plugin.go @@ -6,13 +6,14 @@ import ( "path" "strings" - "github.com/coreos/go-systemd/v22/unit" "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" plugins "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/service" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var PluginName = "k8s_plugin" @@ -20,17 +21,16 @@ var PluginName = "k8s_plugin" type K8sPlugin struct { PluginName string SpecVersion string - serviceManager service.ServiceManager - switchdevBeforeNMRunScript *service.ScriptManifestFile - switchdevAfterNMRunScript *service.ScriptManifestFile - switchdevUdevScript *service.ScriptManifestFile - switchdevBeforeNMService *service.Service - switchdevAfterNMService *service.Service - openVSwitchService *service.Service - networkManagerService *service.Service - sriovService *service.Service + switchdevBeforeNMRunScript *host.ScriptManifestFile + switchdevAfterNMRunScript *host.ScriptManifestFile + switchdevUdevScript *host.ScriptManifestFile + switchdevBeforeNMService *host.Service + switchdevAfterNMService *host.Service + openVSwitchService *host.Service + networkManagerService *host.Service + sriovService *host.Service updateTarget *k8sUpdateTarget - useSystemdService bool + hostHelper helper.HostHelpersInterface } type k8sUpdateTarget struct { @@ -40,7 +40,7 @@ type k8sUpdateTarget struct { switchdevAfterNMRunScript bool switchdevUdevScript bool sriovScript bool - systemServices []*service.Service + systemServices []*host.Service } func (u *k8sUpdateTarget) needUpdate() bool { @@ -58,7 +58,7 @@ func (u *k8sUpdateTarget) reset() { u.switchdevAfterNMRunScript = false u.switchdevUdevScript = false u.sriovScript = false - u.systemServices = []*service.Service{} + u.systemServices = []*host.Service{} } func (u *k8sUpdateTarget) String() string { @@ -92,18 +92,15 @@ const ( configuresSwitchdevBeforeNMScript = switchdevManifestPath + "files/switchdev-configuration-before-nm.sh.yaml" configuresSwitchdevAfterNMScript = switchdevManifestPath + "files/switchdev-configuration-after-nm.sh.yaml" switchdevRenamingUdevScript = switchdevManifestPath + "files/switchdev-vf-link-name.sh.yaml" - - chroot = "/host" ) // Initialize our plugin and set up initial values -func NewK8sPlugin(useSystemdService bool) (plugins.VendorPlugin, error) { +func NewK8sPlugin(helper helper.HostHelpersInterface) (plugins.VendorPlugin, error) { k8sPluging := &K8sPlugin{ - PluginName: PluginName, - SpecVersion: "1.0", - serviceManager: service.NewServiceManager(chroot), - updateTarget: &k8sUpdateTarget{}, - useSystemdService: useSystemdService, + PluginName: PluginName, + SpecVersion: "1.0", + hostHelper: helper, + updateTarget: &k8sUpdateTarget{}, } return k8sPluging, k8sPluging.readManifestFiles() @@ -128,11 +125,11 @@ func (p *K8sPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeState) p.updateTarget.reset() // TODO add check for enableOvsOffload in OperatorConfig later // Update services if switchdev required - if !p.useSystemdService && !utils.IsSwitchdevModeSpec(new.Spec) { + if !vars.UsingSystemdMode && !sriovnetworkv1.IsSwitchdevModeSpec(new.Spec) { return } - if utils.IsSwitchdevModeSpec(new.Spec) { + if sriovnetworkv1.IsSwitchdevModeSpec(new.Spec) { // Check services err = p.switchDevServicesStateUpdate() if err != nil { @@ -141,7 +138,7 @@ func (p *K8sPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeState) } } - if p.useSystemdService { + if vars.UsingSystemdMode { // Check sriov service err = p.sriovServiceStateUpdate() if err != nil { @@ -170,14 +167,14 @@ func (p *K8sPlugin) Apply() error { return err } - if p.useSystemdService { + if vars.UsingSystemdMode { if err := p.updateSriovService(); err != nil { return err } } for _, systemService := range p.updateTarget.systemServices { - if err := p.updateSystemService(systemService); err != nil { + if err := p.hostHelper.UpdateSystemService(systemService); err != nil { return err } } @@ -187,26 +184,20 @@ func (p *K8sPlugin) Apply() error { func (p *K8sPlugin) readSwitchdevManifest() error { // Read switchdev service - switchdevBeforeNMService, err := service.ReadServiceManifestFile(switchdevBeforeNMUnitFile) + switchdevBeforeNMService, err := p.hostHelper.ReadServiceManifestFile(switchdevBeforeNMUnitFile) if err != nil { return err } - switchdevAfterNMService, err := service.ReadServiceManifestFile(switchdevAfterNMUnitFile) + switchdevAfterNMService, err := p.hostHelper.ReadServiceManifestFile(switchdevAfterNMUnitFile) if err != nil { return err } - // Remove run condition form the service - conditionOpt := &unit.UnitOption{ - Section: "Unit", - Name: "ConditionPathExists", - Value: "!/etc/ignition-machine-config-encapsulated.json", - } - switchdevBeforeNMService, err = service.RemoveFromService(switchdevBeforeNMService, conditionOpt) + switchdevBeforeNMService, err = p.hostHelper.RemoveFromService(switchdevBeforeNMService, host.ConditionOpt) if err != nil { return err } - switchdevAfterNMService, err = service.RemoveFromService(switchdevAfterNMService, conditionOpt) + switchdevAfterNMService, err = p.hostHelper.RemoveFromService(switchdevAfterNMService, host.ConditionOpt) if err != nil { return err } @@ -214,11 +205,11 @@ func (p *K8sPlugin) readSwitchdevManifest() error { p.switchdevAfterNMService = switchdevAfterNMService // Read switchdev run script - switchdevBeforeNMRunScript, err := service.ReadScriptManifestFile(configuresSwitchdevBeforeNMScript) + switchdevBeforeNMRunScript, err := p.hostHelper.ReadScriptManifestFile(configuresSwitchdevBeforeNMScript) if err != nil { return err } - switchdevAfterNMRunScript, err := service.ReadScriptManifestFile(configuresSwitchdevAfterNMScript) + switchdevAfterNMRunScript, err := p.hostHelper.ReadScriptManifestFile(configuresSwitchdevAfterNMScript) if err != nil { return err } @@ -226,7 +217,7 @@ func (p *K8sPlugin) readSwitchdevManifest() error { p.switchdevAfterNMRunScript = switchdevAfterNMRunScript // Read switchdev udev script - switchdevUdevScript, err := service.ReadScriptManifestFile(switchdevRenamingUdevScript) + switchdevUdevScript, err := p.hostHelper.ReadScriptManifestFile(switchdevRenamingUdevScript) if err != nil { return err } @@ -236,7 +227,7 @@ func (p *K8sPlugin) readSwitchdevManifest() error { } func (p *K8sPlugin) readNetworkManagerManifest() error { - networkManagerService, err := service.ReadServiceInjectionManifestFile(networkManagerUnitFile) + networkManagerService, err := p.hostHelper.ReadServiceInjectionManifestFile(networkManagerUnitFile) if err != nil { return err } @@ -246,7 +237,7 @@ func (p *K8sPlugin) readNetworkManagerManifest() error { } func (p *K8sPlugin) readOpenVSwitchdManifest() error { - openVSwitchService, err := service.ReadServiceInjectionManifestFile(ovsUnitFile) + openVSwitchService, err := p.hostHelper.ReadServiceInjectionManifestFile(ovsUnitFile) if err != nil { return err } @@ -256,7 +247,7 @@ func (p *K8sPlugin) readOpenVSwitchdManifest() error { } func (p *K8sPlugin) readSriovServiceManifest() error { - sriovService, err := service.ReadServiceManifestFile(sriovUnitFile) + sriovService, err := p.hostHelper.ReadServiceManifestFile(sriovUnitFile) if err != nil { return err } @@ -322,7 +313,7 @@ func (p *K8sPlugin) switchdevServiceStateUpdate() error { func (p *K8sPlugin) sriovServiceStateUpdate() error { log.Log.Info("sriovServiceStateUpdate()") - isServiceEnabled, err := p.serviceManager.IsServiceEnabled(p.sriovService.Path) + isServiceEnabled, err := p.hostHelper.IsServiceEnabled(p.sriovService.Path) if err != nil { return err } @@ -340,12 +331,12 @@ func (p *K8sPlugin) sriovServiceStateUpdate() error { return nil } -func (p *K8sPlugin) getSwitchDevSystemServices() []*service.Service { - return []*service.Service{p.networkManagerService, p.openVSwitchService} +func (p *K8sPlugin) getSwitchDevSystemServices() []*host.Service { + return []*host.Service{p.networkManagerService, p.openVSwitchService} } -func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *service.ScriptManifestFile) (needUpdate bool, err error) { - data, err := os.ReadFile(path.Join(chroot, scriptObj.Path)) +func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *host.ScriptManifestFile) (needUpdate bool, err error) { + data, err := os.ReadFile(path.Join(consts.Host, scriptObj.Path)) if err != nil { if !os.IsNotExist(err) { return false, err @@ -357,8 +348,8 @@ func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *service.ScriptManifes return false, nil } -func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *service.Service) (needUpdate bool, err error) { - swdService, err := p.serviceManager.ReadService(serviceObj.Path) +func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *host.Service) (needUpdate bool, err error) { + swdService, err := p.hostHelper.ReadService(serviceObj.Path) if err != nil { if !os.IsNotExist(err) { return false, err @@ -366,7 +357,7 @@ func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *service.Service) (n // service not exists return true, nil } else { - needChange, err := service.CompareServices(swdService, serviceObj) + needChange, err := p.hostHelper.CompareServices(swdService, serviceObj) if err != nil { return false, err } @@ -374,16 +365,16 @@ func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *service.Service) (n } } -func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *service.Service) bool { +func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *host.Service) bool { log.Log.Info("isSystemServiceNeedUpdate()") - systemService, err := p.serviceManager.ReadService(serviceObj.Path) + systemService, err := p.hostHelper.ReadService(serviceObj.Path) if err != nil { log.Log.Error(err, "k8s-plugin isSystemServiceNeedUpdate(): failed to read sriov-config service file, ignoring", "path", serviceObj.Path) return false } if systemService != nil { - needChange, err := service.CompareServices(systemService, serviceObj) + needChange, err := p.hostHelper.CompareServices(systemService, serviceObj) if err != nil { log.Log.Error(err, "k8s-plugin isSystemServiceNeedUpdate(): failed to compare sriov-config service, ignoring") return false @@ -395,9 +386,9 @@ func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *service.Service) bool } func (p *K8sPlugin) systemServicesStateUpdate() error { - var services []*service.Service + var services []*host.Service for _, systemService := range p.getSwitchDevSystemServices() { - exist, err := p.serviceManager.IsServiceExist(systemService.Path) + exist, err := p.hostHelper.IsServiceExist(systemService.Path) if err != nil { return err } @@ -431,7 +422,7 @@ func (p *K8sPlugin) switchDevServicesStateUpdate() error { func (p *K8sPlugin) updateSriovService() error { if p.updateTarget.sriovScript { - err := p.serviceManager.EnableService(p.sriovService) + err := p.hostHelper.EnableService(p.sriovService) if err != nil { return err } @@ -442,21 +433,21 @@ func (p *K8sPlugin) updateSriovService() error { func (p *K8sPlugin) updateSwitchdevService() error { if p.updateTarget.switchdevBeforeNMService { - err := p.serviceManager.EnableService(p.switchdevBeforeNMService) + err := p.hostHelper.EnableService(p.switchdevBeforeNMService) if err != nil { return err } } if p.updateTarget.switchdevAfterNMService { - err := p.serviceManager.EnableService(p.switchdevAfterNMService) + err := p.hostHelper.EnableService(p.switchdevAfterNMService) if err != nil { return err } } if p.updateTarget.switchdevBeforeNMRunScript { - err := os.WriteFile(path.Join(chroot, p.switchdevBeforeNMRunScript.Path), + err := os.WriteFile(path.Join(consts.Host, p.switchdevBeforeNMRunScript.Path), []byte(p.switchdevBeforeNMRunScript.Contents.Inline), 0755) if err != nil { return err @@ -464,7 +455,7 @@ func (p *K8sPlugin) updateSwitchdevService() error { } if p.updateTarget.switchdevAfterNMRunScript { - err := os.WriteFile(path.Join(chroot, p.switchdevAfterNMRunScript.Path), + err := os.WriteFile(path.Join(consts.Host, p.switchdevAfterNMRunScript.Path), []byte(p.switchdevAfterNMRunScript.Contents.Inline), 0755) if err != nil { return err @@ -472,7 +463,7 @@ func (p *K8sPlugin) updateSwitchdevService() error { } if p.updateTarget.switchdevUdevScript { - err := os.WriteFile(path.Join(chroot, p.switchdevUdevScript.Path), + err := os.WriteFile(path.Join(consts.Host, p.switchdevUdevScript.Path), []byte(p.switchdevUdevScript.Contents.Inline), 0755) if err != nil { return err @@ -481,32 +472,3 @@ func (p *K8sPlugin) updateSwitchdevService() error { return nil } - -func (p *K8sPlugin) updateSystemService(serviceObj *service.Service) error { - systemService, err := p.serviceManager.ReadService(serviceObj.Path) - if err != nil { - return err - } - if systemService == nil { - // Invalid case to reach here - return fmt.Errorf("k8s-plugin updateSystemService(): can't update non-existing service %q", serviceObj.Name) - } - serviceOptions, err := unit.Deserialize(strings.NewReader(serviceObj.Content)) - if err != nil { - return err - } - updatedService, err := service.AppendToService(systemService, serviceOptions...) - if err != nil { - return err - } - - return p.serviceManager.EnableService(updatedService) -} - -func (p *K8sPlugin) SetSystemdFlag() { - p.useSystemdService = true -} - -func (p *K8sPlugin) IsSystemService() bool { - return p.useSystemdService -} diff --git a/pkg/plugins/mellanox/mellanox_plugin.go b/pkg/plugins/mellanox/mellanox_plugin.go index 5f9f9f56a..d36996ca6 100644 --- a/pkg/plugins/mellanox/mellanox_plugin.go +++ b/pkg/plugins/mellanox/mellanox_plugin.go @@ -2,15 +2,13 @@ package mellanox import ( "fmt" - "strconv" - "strings" "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" ) var PluginName = "mellanox_plugin" @@ -18,36 +16,21 @@ var PluginName = "mellanox_plugin" type MellanoxPlugin struct { PluginName string SpecVersion string + helpers helper.HostHelpersInterface } -type mlnxNic struct { - enableSriov bool - totalVfs int - linkTypeP1 string - linkTypeP2 string -} - -const ( - PreconfiguredLinkType = "Preconfigured" - UknownLinkType = "Uknown" - TotalVfs = "NUM_OF_VFS" - EnableSriov = "SRIOV_EN" - LinkTypeP1 = "LINK_TYPE_P1" - LinkTypeP2 = "LINK_TYPE_P2" - MellanoxVendorID = "15b3" -) - -var attributesToChange map[string]mlnxNic +var attributesToChange map[string]mlx.MlxNic var mellanoxNicsStatus map[string]map[string]sriovnetworkv1.InterfaceExt var mellanoxNicsSpec map[string]sriovnetworkv1.Interface // Initialize our plugin and set up initial values -func NewMellanoxPlugin() (plugin.VendorPlugin, error) { +func NewMellanoxPlugin(helpers helper.HostHelpersInterface) (plugin.VendorPlugin, error) { mellanoxNicsStatus = map[string]map[string]sriovnetworkv1.InterfaceExt{} return &MellanoxPlugin{ PluginName: PluginName, SpecVersion: "1.0", + helpers: helpers, }, nil } @@ -68,18 +51,18 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS needDrain = false needReboot = false err = nil - attributesToChange = map[string]mlnxNic{} + attributesToChange = map[string]mlx.MlxNic{} mellanoxNicsSpec = map[string]sriovnetworkv1.Interface{} processedNics := map[string]bool{} // Read mellanox NIC status once if len(mellanoxNicsStatus) == 0 { for _, iface := range new.Status.Interfaces { - if iface.Vendor != MellanoxVendorID { + if iface.Vendor != mlx.MellanoxVendorID { continue } - pciPrefix := getPciAddressPrefix(iface.PciAddress) + pciPrefix := mlx.GetPciAddressPrefix(iface.PciAddress) if ifaces, ok := mellanoxNicsStatus[pciPrefix]; ok { ifaces[iface.PciAddress] = iface } else { @@ -90,14 +73,14 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS // Add only mellanox cards that required changes in the map, to help track dual port NICs for _, iface := range new.Spec.Interfaces { - pciPrefix := getPciAddressPrefix(iface.PciAddress) + pciPrefix := mlx.GetPciAddressPrefix(iface.PciAddress) if _, ok := mellanoxNicsStatus[pciPrefix]; !ok { continue } mellanoxNicsSpec[iface.PciAddress] = iface } - if utils.IsKernelLockdownMode(false) { + if p.helpers.IsKernelLockdownMode() { if len(mellanoxNicsSpec) > 0 { log.Log.Info("Lockdown mode detected, failing on interface update for mellanox devices") return false, false, fmt.Errorf("mellanox device detected when in lockdown mode") @@ -107,25 +90,25 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS } for _, ifaceSpec := range mellanoxNicsSpec { - pciPrefix := getPciAddressPrefix(ifaceSpec.PciAddress) + pciPrefix := mlx.GetPciAddressPrefix(ifaceSpec.PciAddress) // skip processed nics, help not running the same logic 2 times for dual port NICs if _, ok := processedNics[pciPrefix]; ok { continue } processedNics[pciPrefix] = true - fwCurrent, fwNext, err := getMlnxNicFwData(ifaceSpec.PciAddress) + fwCurrent, fwNext, err := p.helpers.GetMlxNicFwData(ifaceSpec.PciAddress) if err != nil { return false, false, err } - isDualPort := isDualPort(ifaceSpec.PciAddress) + isDualPort := mlx.IsDualPort(ifaceSpec.PciAddress, mellanoxNicsStatus) // Attributes to change - attrs := &mlnxNic{totalVfs: -1} + attrs := &mlx.MlxNic{TotalVfs: -1} var changeWithoutReboot bool var totalVfs int - totalVfs, needReboot, changeWithoutReboot = handleTotalVfs(fwCurrent, fwNext, attrs, ifaceSpec, isDualPort) - sriovEnNeedReboot, sriovEnChangeWithoutReboot := handleEnableSriov(totalVfs, fwCurrent, fwNext, attrs) + totalVfs, needReboot, changeWithoutReboot = mlx.HandleTotalVfs(fwCurrent, fwNext, attrs, ifaceSpec, isDualPort, mellanoxNicsSpec) + sriovEnNeedReboot, sriovEnChangeWithoutReboot := mlx.HandleEnableSriov(totalVfs, fwCurrent, fwNext, attrs) needReboot = needReboot || sriovEnNeedReboot changeWithoutReboot = changeWithoutReboot || sriovEnChangeWithoutReboot @@ -133,10 +116,10 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS if ifaceSpec.ExternallyManaged && needReboot { return true, true, fmt.Errorf( "interface %s required a change in the TotalVfs but the policy is externally managed failing: firmware TotalVf %d requested TotalVf %d", - ifaceSpec.PciAddress, fwCurrent.totalVfs, totalVfs) + ifaceSpec.PciAddress, fwCurrent.TotalVfs, totalVfs) } - needLinkChange, err := handleLinkType(pciPrefix, fwCurrent, attrs) + needLinkChange, err := mlx.HandleLinkType(pciPrefix, fwCurrent, attrs, mellanoxNicsSpec, mellanoxNicsStatus) if err != nil { return false, false, err } @@ -162,14 +145,14 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS continue } - _, fwNext, err := getMlnxNicFwData(pciAddress) + _, fwNext, err := p.helpers.GetMlxNicFwData(pciAddress) if err != nil { return false, false, err } - if fwNext.totalVfs > 0 || fwNext.enableSriov { - attributesToChange[pciAddress] = mlnxNic{totalVfs: 0} - log.Log.V(2).Info("Changing TotalVfs to 0, doesn't require rebooting", "fwNext.totalVfs", fwNext.totalVfs) + if fwNext.TotalVfs > 0 || fwNext.EnableSriov { + attributesToChange[pciAddress] = mlx.MlxNic{TotalVfs: 0} + log.Log.V(2).Info("Changing TotalVfs to 0, doesn't require rebooting", "fwNext.totalVfs", fwNext.TotalVfs) } } @@ -182,251 +165,10 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS // Apply config change func (p *MellanoxPlugin) Apply() error { - if utils.IsKernelLockdownMode(false) { + if p.helpers.IsKernelLockdownMode() { log.Log.Info("mellanox-plugin Apply() - skipping due to lockdown mode") return nil } log.Log.Info("mellanox-plugin Apply()") - return configFW() -} - -func configFW() error { - log.Log.Info("mellanox-plugin configFW()") - for pciAddr, fwArgs := range attributesToChange { - cmdArgs := []string{"-d", pciAddr, "-y", "set"} - if fwArgs.enableSriov { - cmdArgs = append(cmdArgs, fmt.Sprintf("%s=True", EnableSriov)) - } else if fwArgs.totalVfs == 0 { - cmdArgs = append(cmdArgs, fmt.Sprintf("%s=False", EnableSriov)) - } - if fwArgs.totalVfs > -1 { - cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%d", TotalVfs, fwArgs.totalVfs)) - } - if len(fwArgs.linkTypeP1) > 0 { - cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%s", LinkTypeP1, fwArgs.linkTypeP1)) - } - if len(fwArgs.linkTypeP2) > 0 { - cmdArgs = append(cmdArgs, fmt.Sprintf("%s=%s", LinkTypeP2, fwArgs.linkTypeP2)) - } - - log.Log.V(2).Info("mellanox-plugin: configFW()", "cmd-args", cmdArgs) - if len(cmdArgs) <= 4 { - continue - } - _, err := utils.RunCommand("mstconfig", cmdArgs...) - if err != nil { - log.Log.Error(err, "mellanox-plugin configFW(): failed") - return err - } - } - return nil -} - -func getMlnxNicFwData(pciAddress string) (current, next *mlnxNic, err error) { - log.Log.Info("mellanox-plugin getMlnxNicFwData()", "device", pciAddress) - err = nil - attrs := []string{TotalVfs, EnableSriov, LinkTypeP1, LinkTypeP2} - - out, err := utils.MstConfigReadData(pciAddress) - if err != nil { - log.Log.Error(err, "mellanox-plugin getMlnxNicFwData(): failed") - return - } - mstCurrentData, mstNextData := utils.ParseMstconfigOutput(out, attrs) - current, err = mlnxNicFromMap(mstCurrentData) - if err != nil { - log.Log.Error(err, "mellanox-plugin mlnxNicFromMap() for current mstconfig data failed") - return - } - next, err = mlnxNicFromMap(mstNextData) - if err != nil { - log.Log.Error(err, "mellanox-plugin mlnxNicFromMap() for next mstconfig data failed") - } - return -} - -func mlnxNicFromMap(mstData map[string]string) (*mlnxNic, error) { - log.Log.Info("mellanox-plugin mlnxNicFromMap()", "data", mstData) - fwData := &mlnxNic{} - if strings.Contains(mstData[EnableSriov], "True") { - fwData.enableSriov = true - } - i, err := strconv.Atoi(mstData[TotalVfs]) - if err != nil { - return nil, err - } - - fwData.totalVfs = i - fwData.linkTypeP1 = getLinkType(mstData[LinkTypeP1]) - if linkTypeP2, ok := mstData[LinkTypeP2]; ok { - fwData.linkTypeP2 = getLinkType(linkTypeP2) - } - - return fwData, nil -} - -func getPciAddressPrefix(pciAddress string) string { - return pciAddress[:len(pciAddress)-1] -} - -func isDualPort(pciAddress string) bool { - log.Log.Info("mellanox-plugin isDualPort()", "address", pciAddress) - pciAddressPrefix := getPciAddressPrefix(pciAddress) - return len(mellanoxNicsStatus[pciAddressPrefix]) > 1 -} - -func getLinkType(linkType string) string { - log.Log.Info("mellanox-plugin getLinkType()", "link-type", linkType) - if strings.Contains(linkType, constants.LinkTypeETH) { - return constants.LinkTypeETH - } else if strings.Contains(linkType, constants.LinkTypeIB) { - return constants.LinkTypeIB - } else if len(linkType) > 0 { - log.Log.Error(nil, "mellanox-plugin getLinkType(): link type is not one of [ETH, IB], treating as unknown", - "link-type", linkType) - return UknownLinkType - } else { - log.Log.Info("mellanox-plugin getLinkType(): LINK_TYPE_P* attribute was not found, treating as preconfigured link type") - return PreconfiguredLinkType - } -} - -func isLinkTypeRequireChange(iface sriovnetworkv1.Interface, ifaceStatus sriovnetworkv1.InterfaceExt, fwLinkType string) (bool, error) { - log.Log.Info("mellanox-plugin isLinkTypeRequireChange()", "device", iface.PciAddress) - if iface.LinkType != "" && !strings.EqualFold(ifaceStatus.LinkType, iface.LinkType) { - if !strings.EqualFold(iface.LinkType, constants.LinkTypeETH) && !strings.EqualFold(iface.LinkType, constants.LinkTypeIB) { - return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Not supported link type: %s,"+ - " supported link types: [eth, ETH, ib, and IB]", iface.LinkType) - } - if fwLinkType == UknownLinkType { - return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Unknown link type: %s", fwLinkType) - } - if fwLinkType == PreconfiguredLinkType { - return false, fmt.Errorf("mellanox-plugin OnNodeStateChange(): Network card %s does not support link type change", iface.PciAddress) - } - - return true, nil - } - - return false, nil -} - -func getOtherPortSpec(pciAddress string) *sriovnetworkv1.Interface { - log.Log.Info("mellanox-plugin getOtherPortSpec()", "pciAddress", pciAddress) - pciAddrPrefix := getPciAddressPrefix(pciAddress) - pciAddrSuffix := pciAddress[len(pciAddrPrefix):] - - if pciAddrSuffix == "0" { - iface := mellanoxNicsSpec[pciAddrPrefix+"1"] - return &iface - } - - iface := mellanoxNicsSpec[pciAddrPrefix+"0"] - return &iface -} - -// handleTotalVfs return required total VFs or max (required VFs for dual port NIC) and needReboot if totalVfs will change -func handleTotalVfs(fwCurrent, fwNext, attrs *mlnxNic, ifaceSpec sriovnetworkv1.Interface, isDualPort bool) ( - totalVfs int, needReboot, changeWithoutReboot bool) { - totalVfs = ifaceSpec.NumVfs - // Check if the other port is changing the number of VF - if isDualPort { - otherIfaceSpec := getOtherPortSpec(ifaceSpec.PciAddress) - if otherIfaceSpec != nil { - if otherIfaceSpec.NumVfs > totalVfs { - totalVfs = otherIfaceSpec.NumVfs - } - } - } - - // if the PF is externally managed we just need to check the totalVfs requested in the policy is not higher than - // the configured amount - if ifaceSpec.ExternallyManaged { - if totalVfs > fwCurrent.totalVfs { - log.Log.Error(nil, "The nic is externallyManaged and TotalVfs configured on the system is lower then requested VFs, failing configuration", - "current", fwCurrent.totalVfs, "requested", totalVfs) - attrs.totalVfs = totalVfs - needReboot = true - changeWithoutReboot = false - } - return - } - - if fwCurrent.totalVfs != totalVfs { - log.Log.V(2).Info("Changing TotalVfs, needs reboot", "current", fwCurrent.totalVfs, "requested", totalVfs) - attrs.totalVfs = totalVfs - needReboot = true - } - - // Remove policy then re-apply it - if !needReboot && fwNext.totalVfs != totalVfs { - log.Log.V(2).Info("Changing TotalVfs to same as Next Boot value, doesn't require rebooting", - "current", fwCurrent.totalVfs, "next", fwNext.totalVfs, "requested", totalVfs) - attrs.totalVfs = totalVfs - changeWithoutReboot = true - } - - return -} - -// handleEnableSriov based on totalVfs it decide to disable (totalVfs=0) or enable (totalVfs changed from 0) sriov -// and need reboot if enableSriov will change -func handleEnableSriov(totalVfs int, fwCurrent, fwNext, attrs *mlnxNic) (needReboot, changeWithoutReboot bool) { - if totalVfs == 0 && fwCurrent.enableSriov { - log.Log.V(2).Info("disabling Sriov, needs reboot") - attrs.enableSriov = false - return true, false - } else if totalVfs > 0 && !fwCurrent.enableSriov { - log.Log.V(2).Info("enabling Sriov, needs reboot") - attrs.enableSriov = true - return true, false - } else if totalVfs > 0 && !fwNext.enableSriov { - attrs.enableSriov = true - return false, true - } - - return false, false -} - -func getIfaceStatus(pciAddress string) sriovnetworkv1.InterfaceExt { - return mellanoxNicsStatus[getPciAddressPrefix(pciAddress)][pciAddress] -} - -// handleLinkType based on existing linkType and requested link -func handleLinkType(pciPrefix string, fwData, attr *mlnxNic) (bool, error) { - needReboot := false - - pciAddress := pciPrefix + "0" - if firstPortSpec, ok := mellanoxNicsSpec[pciAddress]; ok { - ifaceStatus := getIfaceStatus(pciAddress) - needChange, err := isLinkTypeRequireChange(firstPortSpec, ifaceStatus, fwData.linkTypeP1) - if err != nil { - return false, err - } - - if needChange { - log.Log.V(2).Info("Changing LinkTypeP1, needs reboot", - "from", fwData.linkTypeP1, "to", firstPortSpec.LinkType) - attr.linkTypeP1 = firstPortSpec.LinkType - needReboot = true - } - } - - pciAddress = pciPrefix + "1" - if secondPortSpec, ok := mellanoxNicsSpec[pciAddress]; ok { - ifaceStatus := getIfaceStatus(pciAddress) - needChange, err := isLinkTypeRequireChange(secondPortSpec, ifaceStatus, fwData.linkTypeP2) - if err != nil { - return false, err - } - - if needChange { - log.Log.V(2).Info("Changing LinkTypeP2, needs reboot", - "from", fwData.linkTypeP2, "to", secondPortSpec.LinkType) - attr.linkTypeP2 = secondPortSpec.LinkType - needReboot = true - } - } - - return needReboot, nil + return p.helpers.MlxConfigFW(attributesToChange) } diff --git a/pkg/plugins/mock/mock_plugin.go b/pkg/plugins/mock/mock_plugin.go new file mode 100644 index 000000000..b821139c5 --- /dev/null +++ b/pkg/plugins/mock/mock_plugin.go @@ -0,0 +1,93 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: plugin.go + +// Package mock_plugin is a generated GoMock package. +package mock_plugin + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" +) + +// MockVendorPlugin is a mock of VendorPlugin interface. +type MockVendorPlugin struct { + ctrl *gomock.Controller + recorder *MockVendorPluginMockRecorder +} + +// MockVendorPluginMockRecorder is the mock recorder for MockVendorPlugin. +type MockVendorPluginMockRecorder struct { + mock *MockVendorPlugin +} + +// NewMockVendorPlugin creates a new mock instance. +func NewMockVendorPlugin(ctrl *gomock.Controller) *MockVendorPlugin { + mock := &MockVendorPlugin{ctrl: ctrl} + mock.recorder = &MockVendorPluginMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockVendorPlugin) EXPECT() *MockVendorPluginMockRecorder { + return m.recorder +} + +// Apply mocks base method. +func (m *MockVendorPlugin) Apply() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Apply") + ret0, _ := ret[0].(error) + return ret0 +} + +// Apply indicates an expected call of Apply. +func (mr *MockVendorPluginMockRecorder) Apply() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockVendorPlugin)(nil).Apply)) +} + +// Name mocks base method. +func (m *MockVendorPlugin) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockVendorPluginMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockVendorPlugin)(nil).Name)) +} + +// OnNodeStateChange mocks base method. +func (m *MockVendorPlugin) OnNodeStateChange(new *v1.SriovNetworkNodeState) (bool, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "OnNodeStateChange", new) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// OnNodeStateChange indicates an expected call of OnNodeStateChange. +func (mr *MockVendorPluginMockRecorder) OnNodeStateChange(new interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnNodeStateChange", reflect.TypeOf((*MockVendorPlugin)(nil).OnNodeStateChange), new) +} + +// Spec mocks base method. +func (m *MockVendorPlugin) Spec() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Spec") + ret0, _ := ret[0].(string) + return ret0 +} + +// Spec indicates an expected call of Spec. +func (mr *MockVendorPluginMockRecorder) Spec() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Spec", reflect.TypeOf((*MockVendorPlugin)(nil).Spec)) +} diff --git a/pkg/plugins/plugin.go b/pkg/plugins/plugin.go index 1723ca610..276e37cf2 100644 --- a/pkg/plugins/plugin.go +++ b/pkg/plugins/plugin.go @@ -4,6 +4,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" ) +//go:generate ../../bin/mockgen -destination mock/mock_plugin.go -source plugin.go type VendorPlugin interface { // Return the name of plugin Name() string diff --git a/pkg/plugins/virtual/virtual_plugin.go b/pkg/plugins/virtual/virtual_plugin.go index 9fb6cb774..06a57a80f 100644 --- a/pkg/plugins/virtual/virtual_plugin.go +++ b/pkg/plugins/virtual/virtual_plugin.go @@ -6,10 +6,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + consts "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var PluginName = "virtual_plugin" @@ -21,8 +21,7 @@ type VirtualPlugin struct { DesireState *sriovnetworkv1.SriovNetworkNodeState LastState *sriovnetworkv1.SriovNetworkNodeState LoadVfioDriver uint - RunningOnHost bool - HostManager host.HostManagerInterface + helpers helper.HostHelpersInterface } const ( @@ -32,13 +31,12 @@ const ( ) // Initialize our plugin and set up initial values -func NewVirtualPlugin(runningOnHost bool) (plugin.VendorPlugin, error) { +func NewVirtualPlugin(helper helper.HostHelpersInterface) (plugin.VendorPlugin, error) { return &VirtualPlugin{ PluginName: PluginName, SpecVersion: "1.0", LoadVfioDriver: unloaded, - RunningOnHost: runningOnHost, - HostManager: host.NewHostManager(runningOnHost), + helpers: helper, }, nil } @@ -79,12 +77,12 @@ func (p *VirtualPlugin) Apply() error { // This is the case for OpenStack deployments where the underlying virtualization platform is KVM. // NOTE: if VFIO was already loaded for some reason, we will not try to load it again with the new options. kernelArgs := "enable_unsafe_noiommu_mode=1" - if err := p.HostManager.LoadKernelModule("vfio", kernelArgs); err != nil { + if err := p.helpers.LoadKernelModule("vfio", kernelArgs); err != nil { log.Log.Error(err, "virtual-plugin Apply(): fail to load vfio kmod") return err } - if err := p.HostManager.LoadKernelModule("vfio_pci"); err != nil { + if err := p.helpers.LoadKernelModule("vfio_pci"); err != nil { log.Log.Error(err, "virtual-plugin Apply(): fail to load vfio_pci kmod") return err } @@ -98,12 +96,12 @@ func (p *VirtualPlugin) Apply() error { return nil } } - exit, err := utils.Chroot("/host") + exit, err := p.helpers.Chroot(consts.Host) if err != nil { return err } defer exit() - if err := utils.SyncNodeStateVirtual(p.DesireState); err != nil { + if err := syncNodeStateVirtual(p.DesireState, p.helpers); err != nil { return err } p.LastState = &sriovnetworkv1.SriovNetworkNodeState{} @@ -122,7 +120,62 @@ func (p *VirtualPlugin) IsSystemService() bool { func needVfioDriver(state *sriovnetworkv1.SriovNetworkNodeState) bool { for _, iface := range state.Spec.Interfaces { for i := range iface.VfGroups { - if iface.VfGroups[i].DeviceType == constants.DeviceTypeVfioPci { + if iface.VfGroups[i].DeviceType == consts.DeviceTypeVfioPci { + return true + } + } + } + return false +} + +// syncNodeStateVirtual attempt to update the node state to match the desired state in virtual platforms +func syncNodeStateVirtual(newState *sriovnetworkv1.SriovNetworkNodeState, helpers helper.HostHelpersInterface) error { + var err error + for _, ifaceStatus := range newState.Status.Interfaces { + for _, iface := range newState.Spec.Interfaces { + if iface.PciAddress == ifaceStatus.PciAddress { + if !needUpdateVirtual(&iface, &ifaceStatus) { + log.Log.V(2).Info("syncNodeStateVirtual(): no need update interface", "address", iface.PciAddress) + break + } + if err = helpers.ConfigSriovDeviceVirtual(&iface); err != nil { + log.Log.Error(err, "syncNodeStateVirtual(): fail to config sriov interface", "address", iface.PciAddress) + return err + } + break + } + } + } + return nil +} + +func needUpdateVirtual(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) bool { + // The device MTU is set by the platform + // The NumVfs is always 1 + if iface.NumVfs > 0 { + for _, vf := range ifaceStatus.VFs { + ingroup := false + for _, group := range iface.VfGroups { + if sriovnetworkv1.IndexInRange(vf.VfID, group.VfRange) { + ingroup = true + if group.DeviceType != consts.DeviceTypeNetDevice { + if group.DeviceType != vf.Driver { + log.Log.V(2).Info("needUpdateVirtual(): Driver needs update", + "desired", group.DeviceType, "current", vf.Driver) + return true + } + } else { + if sriovnetworkv1.StringInArray(vf.Driver, vars.DpdkDrivers) { + log.Log.V(2).Info("needUpdateVirtual(): Driver needs update", + "desired", group.DeviceType, "current", vf.Driver) + return true + } + } + break + } + } + if !ingroup && sriovnetworkv1.StringInArray(vf.Driver, vars.DpdkDrivers) { + // VF which has DPDK driver loaded but not in any group, needs to be reset to default driver. return true } } diff --git a/pkg/systemd/systemd.go b/pkg/systemd/systemd.go index 87ae19a11..f682d85f5 100644 --- a/pkg/systemd/systemd.go +++ b/pkg/systemd/systemd.go @@ -25,30 +25,33 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) const ( - SriovSystemdConfigPath = utils.SriovConfBasePath + "/sriov-interface-config.yaml" - SriovSystemdResultPath = utils.SriovConfBasePath + "/sriov-interface-result.yaml" - sriovSystemdSupportedNicPath = utils.SriovConfBasePath + "/sriov-supported-nics-ids.yaml" + SriovSystemdConfigPath = consts.SriovConfBasePath + "/sriov-interface-config.yaml" + SriovSystemdResultPath = consts.SriovConfBasePath + "/sriov-interface-result.yaml" + sriovSystemdSupportedNicPath = consts.SriovConfBasePath + "/sriov-supported-nics-ids.yaml" sriovSystemdServiceBinaryPath = "/var/lib/sriov/sriov-network-config-daemon" - SriovHostSystemdConfigPath = "/host" + SriovSystemdConfigPath - SriovHostSystemdResultPath = "/host" + SriovSystemdResultPath - sriovHostSystemdSupportedNicPath = "/host" + sriovSystemdSupportedNicPath - sriovHostSystemdServiceBinaryPath = "/host" + sriovSystemdServiceBinaryPath + SriovHostSystemdConfigPath = consts.Host + SriovSystemdConfigPath + SriovHostSystemdResultPath = consts.Host + SriovSystemdResultPath + sriovHostSystemdSupportedNicPath = consts.Host + sriovSystemdSupportedNicPath + sriovHostSystemdServiceBinaryPath = consts.Host + sriovSystemdServiceBinaryPath SriovServicePath = "/etc/systemd/system/sriov-config.service" - SriovHostServicePath = "/host" + SriovServicePath + SriovHostServicePath = consts.Host + SriovServicePath - HostSriovConfBasePath = "/host" + utils.SriovConfBasePath + HostSriovConfBasePath = consts.Host + consts.SriovConfBasePath ) +// TODO: move this to the host interface also + type SriovConfig struct { Spec sriovnetworkv1.SriovNetworkNodeStateSpec `yaml:"spec"` UnsupportedNics bool `yaml:"unsupportedNics"` - PlatformType utils.PlatformType `yaml:"platformType"` + PlatformType consts.PlatformTypes `yaml:"platformType"` } type SriovResult struct { @@ -67,15 +70,15 @@ func ReadConfFile() (spec *SriovConfig, err error) { return spec, err } -func WriteConfFile(newState *sriovnetworkv1.SriovNetworkNodeState, unsupportedNics bool, platformType utils.PlatformType) (bool, error) { +func WriteConfFile(newState *sriovnetworkv1.SriovNetworkNodeState) (bool, error) { newFile := false // remove the device plugin revision as we don't need it here newState.Spec.DpConfigVersion = "" sriovConfig := &SriovConfig{ newState.Spec, - unsupportedNics, - platformType, + vars.DevMode, + vars.PlatformType, } _, err := os.Stat(SriovHostSystemdConfigPath) diff --git a/pkg/webhook/validate.go b/pkg/webhook/validate.go index 366881dc6..64457d210 100644 --- a/pkg/webhook/validate.go +++ b/pkg/webhook/validate.go @@ -16,8 +16,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) const ( @@ -35,7 +35,7 @@ func validateSriovOperatorConfig(cr *sriovnetworkv1.SriovOperatorConfig, operati log.Log.V(2).Info("validateSriovOperatorConfig", "object", cr) var warnings []string - if cr.GetName() != constants.DefaultConfigName { + if cr.GetName() != consts.DefaultConfigName { return false, warnings, fmt.Errorf("only default SriovOperatorConfig is used") } @@ -95,7 +95,7 @@ func validateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePolicy, o log.Log.V(2).Info("validateSriovNetworkNodePolicy", "object", cr) var warnings []string - if cr.GetName() == constants.DefaultPolicyName && cr.GetNamespace() == os.Getenv("NAMESPACE") { + if cr.GetName() == consts.DefaultPolicyName && cr.GetNamespace() == os.Getenv("NAMESPACE") { if operation == v1.Delete { // reject deletion of default policy return false, warnings, fmt.Errorf("default SriovNetworkNodePolicy shouldn't be deleted") @@ -193,19 +193,19 @@ func staticValidateSriovNetworkNodePolicy(cr *sriovnetworkv1.SriovNetworkNodePol // To configure RoCE on baremetal or virtual machine: // BM: DeviceType = netdevice && isRdma = true // VM: DeviceType = vfio-pci && isRdma = false - if cr.Spec.DeviceType == constants.DeviceTypeVfioPci && cr.Spec.IsRdma { + if cr.Spec.DeviceType == consts.DeviceTypeVfioPci && cr.Spec.IsRdma { return false, fmt.Errorf("'deviceType: vfio-pci' conflicts with 'isRdma: true'; Set 'deviceType' to (string)'netdevice' Or Set 'isRdma' to (bool)'false'") } - if strings.EqualFold(cr.Spec.LinkType, constants.LinkTypeIB) && !cr.Spec.IsRdma { + if strings.EqualFold(cr.Spec.LinkType, consts.LinkTypeIB) && !cr.Spec.IsRdma { return false, fmt.Errorf("'linkType: ib or IB' requires 'isRdma: true'; Set 'isRdma' to (bool)'true'") } // vdpa: deviceType must be set to 'netdevice' - if cr.Spec.DeviceType != constants.DeviceTypeNetDevice && (cr.Spec.VdpaType == constants.VdpaTypeVirtio || cr.Spec.VdpaType == constants.VdpaTypeVhost) { + if cr.Spec.DeviceType != consts.DeviceTypeNetDevice && (cr.Spec.VdpaType == consts.VdpaTypeVirtio || cr.Spec.VdpaType == consts.VdpaTypeVhost) { return false, fmt.Errorf("'deviceType: %s' conflicts with '%s'; Set 'deviceType' to (string)'netdevice' Or Remove 'vdpaType'", cr.Spec.DeviceType, cr.Spec.VdpaType) } // vdpa: device must be configured in switchdev mode - if (cr.Spec.VdpaType == constants.VdpaTypeVirtio || cr.Spec.VdpaType == constants.VdpaTypeVhost) && cr.Spec.EswitchMode != sriovnetworkv1.ESwithModeSwitchDev { + if (cr.Spec.VdpaType == consts.VdpaTypeVirtio || cr.Spec.VdpaType == consts.VdpaTypeVhost) && cr.Spec.EswitchMode != sriovnetworkv1.ESwithModeSwitchDev { return false, fmt.Errorf("vdpa requires the device to be configured in switchdev mode") } @@ -297,7 +297,7 @@ func validatePolicyForNodeState(policy *sriovnetworkv1.SriovNetworkNodePolicy, s if err == nil { interfaceSelected = true interfaceSelectedForNode = true - if policy.GetName() != constants.DefaultPolicyName && policy.Spec.NumVfs == 0 { + if policy.GetName() != consts.DefaultPolicyName && policy.Spec.NumVfs == 0 { return nil, fmt.Errorf("numVfs(%d) in CR %s is not allowed", policy.Spec.NumVfs, policy.GetName()) } if policy.Spec.NumVfs > iface.TotalVfs && iface.Vendor == IntelID { @@ -322,7 +322,7 @@ func validatePolicyForNodeState(policy *sriovnetworkv1.SriovNetworkNodePolicy, s } } // vdpa: only mellanox cards are supported - if (policy.Spec.VdpaType == constants.VdpaTypeVirtio || policy.Spec.VdpaType == constants.VdpaTypeVhost) && iface.Vendor != MellanoxID { + if (policy.Spec.VdpaType == consts.VdpaTypeVirtio || policy.Spec.VdpaType == consts.VdpaTypeVhost) && iface.Vendor != MellanoxID { return nil, fmt.Errorf("vendor(%s) in CR %s not supported for vdpa interface(%s)", iface.Vendor, policy.GetName(), iface.Name) } } else { @@ -440,7 +440,7 @@ func validateNicModel(selector *sriovnetworkv1.SriovNetworkNicSelector, iface *s } // Check the vendor and device ID of the VF only if we are on a virtual environment - for key := range utils.PlatformMap { + for key := range vars.PlatformsMap { if strings.Contains(strings.ToLower(node.Spec.ProviderID), strings.ToLower(key)) && selector.NetFilter != "" && selector.NetFilter == iface.NetFilter && sriovnetworkv1.IsVfSupportedModel(iface.Vendor, iface.DeviceID) { diff --git a/test/util/cluster/cluster.go b/test/util/cluster/cluster.go index fdf06bdf7..af2230cff 100644 --- a/test/util/cluster/cluster.go +++ b/test/util/cluster/cluster.go @@ -17,6 +17,7 @@ import ( runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" sriovv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" testclient "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/client" "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/nodes" "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/pod" @@ -323,7 +324,7 @@ func GetNodeSecureBootState(clients *testclient.ClientSet, nodeName, namespace s podDefinition.Namespace = namespace volume := corev1.Volume{Name: "host", VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{Path: "/"}}} - mount := corev1.VolumeMount{Name: "host", MountPath: "/host"} + mount := corev1.VolumeMount{Name: "host", MountPath: consts.Host} podDefinition = pod.RedefineWithMount(podDefinition, volume, mount) created, err := clients.Pods(namespace).Create(context.Background(), podDefinition, metav1.CreateOptions{}) if err != nil { From d5eb6967ff00d1f2236c30f8d6570e3a528e41a1 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 7 Jan 2024 18:31:35 +0200 Subject: [PATCH 09/61] nit: small fix to a test and git ignore update Signed-off-by: Sebastian Sch --- .gitignore | 3 ++- test/conformance/tests/test_sriov_operator.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e63284190..6761d7ea1 100644 --- a/.gitignore +++ b/.gitignore @@ -82,4 +82,5 @@ tags # End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode #IDE (GoLand) specific .idea/ - +# test-environment files +registry-login.conf diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index 809a2c1bd..208ed2b9f 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -1193,7 +1193,7 @@ var _ = Describe("[sriov] operator", func() { capacity, _ = resNum.AsInt64() res["openshift.io/testresource1"] = capacity return res - }, 2*time.Minute, time.Second).Should(Equal(map[string]int64{ + }, 15*time.Minute, time.Second).Should(Equal(map[string]int64{ "openshift.io/testresource": int64(3), "openshift.io/testresource1": int64(2), })) From 6eb63a9359deb1381000363a342f16611c4f7280 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 9 Jan 2024 17:07:33 +0200 Subject: [PATCH 10/61] Use go-install-tool instead of go-get-tool for gomock go-get-tool is not available in the Makefile Signed-off-by: Yury Kulazhenkov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 250d0c4cf..90e7ef468 100644 --- a/Makefile +++ b/Makefile @@ -157,7 +157,7 @@ envtest: ## Download envtest-setup locally if necessary. GOMOCK = $(shell pwd)/bin/mockgen gomock: - $(call go-get-tool,$(GOMOCK),github.com/golang/mock/mockgen@v1.6.0) + $(call go-install-tool,$(GOMOCK),github.com/golang/mock/mockgen@v1.6.0) # go-install-tool will 'go install' any package $2 and install it to $1. define go-install-tool From dc5c9d20d89f49a303817b324d6658cb0ba98ce8 Mon Sep 17 00:00:00 2001 From: adrianc Date: Wed, 27 Dec 2023 14:26:06 +0200 Subject: [PATCH 11/61] Do not reset Firmware config in Mellanox plugin When interface(pf) is externally managed, we need to avoid resetting firmware configurations. - use store manager to get latest pf config from host so we can reliably determine if interface is externally managed if it does not appear in spec - when interface appears in spec, block both sriov and link type firmware configurations if interface is externally managed - skip pfs that are externally managed Signed-off-by: adrianc --- pkg/daemon/plugin.go | 4 +- pkg/plugins/mellanox/mellanox_plugin.go | 76 +++++++++++++++++-------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/pkg/daemon/plugin.go b/pkg/daemon/plugin.go index 38e1d9d73..8cb344347 100644 --- a/pkg/daemon/plugin.go +++ b/pkg/daemon/plugin.go @@ -82,7 +82,9 @@ func registerVendorPlugins(ns *sriovnetworkv1.SriovNetworkNodeState, helpers hel log.Log.Error(err, "registerVendorPlugins(): failed to load plugin", "plugin-name", plug.Name()) return vendorPlugins, fmt.Errorf("registerVendorPlugins(): failed to load the %s plugin error: %v", plug.Name(), err) } - vendorPlugins[plug.Name()] = plug + if _, ok := vendorPlugins[plug.Name()]; !ok { + vendorPlugins[plug.Name()] = plug + } } } diff --git a/pkg/plugins/mellanox/mellanox_plugin.go b/pkg/plugins/mellanox/mellanox_plugin.go index d36996ca6..a95d24b9d 100644 --- a/pkg/plugins/mellanox/mellanox_plugin.go +++ b/pkg/plugins/mellanox/mellanox_plugin.go @@ -52,22 +52,21 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS needReboot = false err = nil attributesToChange = map[string]mlx.MlxNic{} + mellanoxNicsStatus = map[string]map[string]sriovnetworkv1.InterfaceExt{} mellanoxNicsSpec = map[string]sriovnetworkv1.Interface{} processedNics := map[string]bool{} - // Read mellanox NIC status once - if len(mellanoxNicsStatus) == 0 { - for _, iface := range new.Status.Interfaces { - if iface.Vendor != mlx.MellanoxVendorID { - continue - } + // fill mellanoxNicsStatus + for _, iface := range new.Status.Interfaces { + if iface.Vendor != mlx.MellanoxVendorID { + continue + } - pciPrefix := mlx.GetPciAddressPrefix(iface.PciAddress) - if ifaces, ok := mellanoxNicsStatus[pciPrefix]; ok { - ifaces[iface.PciAddress] = iface - } else { - mellanoxNicsStatus[pciPrefix] = map[string]sriovnetworkv1.InterfaceExt{iface.PciAddress: iface} - } + pciPrefix := mlx.GetPciAddressPrefix(iface.PciAddress) + if ifaces, ok := mellanoxNicsStatus[pciPrefix]; ok { + ifaces[iface.PciAddress] = iface + } else { + mellanoxNicsStatus[pciPrefix] = map[string]sriovnetworkv1.InterfaceExt{iface.PciAddress: iface} } } @@ -106,25 +105,29 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS attrs := &mlx.MlxNic{TotalVfs: -1} var changeWithoutReboot bool - var totalVfs int - totalVfs, needReboot, changeWithoutReboot = mlx.HandleTotalVfs(fwCurrent, fwNext, attrs, ifaceSpec, isDualPort, mellanoxNicsSpec) + totalVfs, totalVfsNeedReboot, totalVfsChangeWithoutReboot := mlx.HandleTotalVfs(fwCurrent, fwNext, attrs, ifaceSpec, isDualPort, mellanoxNicsSpec) sriovEnNeedReboot, sriovEnChangeWithoutReboot := mlx.HandleEnableSriov(totalVfs, fwCurrent, fwNext, attrs) - needReboot = needReboot || sriovEnNeedReboot - changeWithoutReboot = changeWithoutReboot || sriovEnChangeWithoutReboot - - // failing as we can't the fwTotalVf is lower than the request one on a nic with externallyManage configured - if ifaceSpec.ExternallyManaged && needReboot { - return true, true, fmt.Errorf( - "interface %s required a change in the TotalVfs but the policy is externally managed failing: firmware TotalVf %d requested TotalVf %d", - ifaceSpec.PciAddress, fwCurrent.TotalVfs, totalVfs) - } + needReboot = totalVfsNeedReboot || sriovEnNeedReboot + changeWithoutReboot = totalVfsChangeWithoutReboot || sriovEnChangeWithoutReboot needLinkChange, err := mlx.HandleLinkType(pciPrefix, fwCurrent, attrs, mellanoxNicsSpec, mellanoxNicsStatus) if err != nil { return false, false, err } - needReboot = needReboot || needLinkChange + + // no FW changes allowed when NIC is externally managed + if ifaceSpec.ExternallyManaged { + if totalVfsNeedReboot || totalVfsChangeWithoutReboot { + return false, false, fmt.Errorf( + "interface %s required a change in the TotalVfs but the policy is externally managed failing: firmware TotalVf %d requested TotalVf %d", + ifaceSpec.PciAddress, fwCurrent.TotalVfs, totalVfs) + } + if needLinkChange { + return false, false, fmt.Errorf("change required for link type but the policy is externally managed, failing") + } + } + if needReboot || changeWithoutReboot { attributesToChange[ifaceSpec.PciAddress] = *attrs } @@ -140,6 +143,11 @@ func (p *MellanoxPlugin) OnNodeStateChange(new *sriovnetworkv1.SriovNetworkNodeS processedNics[pciPrefix] = true pciAddress := pciPrefix + "0" + // Skip externally managed NICs + if p.nicHasExternallyManagedPFs(portsMap) { + continue + } + // Skip unsupported devices if id := sriovnetworkv1.GetVfDeviceID(portsMap[pciAddress].DeviceID); id == "" { continue @@ -172,3 +180,23 @@ func (p *MellanoxPlugin) Apply() error { log.Log.Info("mellanox-plugin Apply()") return p.helpers.MlxConfigFW(attributesToChange) } + +// nicHasExternallyManagedPFs returns true if one of the ports(interface) of the NIC is marked as externally managed +// in StoreManagerInterface. +func (p *MellanoxPlugin) nicHasExternallyManagedPFs(nicPortsMap map[string]sriovnetworkv1.InterfaceExt) bool { + for _, iface := range nicPortsMap { + pfStatus, exist, err := p.helpers.LoadPfsStatus(iface.PciAddress) + if err != nil { + log.Log.Error(err, "failed to load PF status from disk", "address", iface.PciAddress) + continue + } + if !exist { + continue + } + if pfStatus.ExternallyManaged { + log.Log.V(2).Info("PF is extenally managed, skip FW TotalVfs reset") + return true + } + } + return false +} From 2af158f8a64752b5a9429df6819304ad0a1149ed Mon Sep 17 00:00:00 2001 From: adrianc Date: Wed, 27 Dec 2023 14:31:45 +0200 Subject: [PATCH 12/61] block mtu change on pf when externally managed Signed-off-by: adrianc --- pkg/host/sriov.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/host/sriov.go b/pkg/host/sriov.go index 7d6343771..8a878854b 100644 --- a/pkg/host/sriov.go +++ b/pkg/host/sriov.go @@ -343,6 +343,12 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * } // set PF mtu if iface.Mtu > 0 && iface.Mtu > ifaceStatus.Mtu { + if iface.ExternallyManaged { + err := fmt.Errorf("ConfigSriovDevice(): requested MTU(%d) is greater than configured MTU(%d) for device %s. cannot change MTU as policy is configured as ExternallyManaged", + iface.Mtu, ifaceStatus.Mtu, iface.PciAddress) + log.Log.Error(nil, err.Error()) + return err + } err = s.networkHelper.SetNetdevMTU(iface.PciAddress, iface.Mtu) if err != nil { log.Log.Error(err, "configSriovDevice(): fail to set mtu for PF", "device", iface.PciAddress) From 6508c69093d0b9c4aa082f557eb7f66a05650441 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Thu, 14 Dec 2023 15:50:47 +0200 Subject: [PATCH 13/61] add design doc for switchdev mode refactoring Signed-off-by: Yury Kulazhenkov --- doc/design/switchdev-refactoring.md | 206 ++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 doc/design/switchdev-refactoring.md diff --git a/doc/design/switchdev-refactoring.md b/doc/design/switchdev-refactoring.md new file mode 100644 index 000000000..ec0c0e93b --- /dev/null +++ b/doc/design/switchdev-refactoring.md @@ -0,0 +1,206 @@ +--- +title: switchdev mode refactoring +authors: + - ykulazhenkov +reviewers: +creation-date: 14-12-2023 +last-updated: 14-12-2023 +--- + +# switchdev and systemd modes refactoring + +## Summary + +We need to refactor the implementation used for NICs in switchdev mode and align its behavior with the systemd +mode of the operator. The refactoring is required to simplify the development of the new switchdev-related +features for the sriov-network-operator. + +## Motivation + +Currently the **sriov-network-operator** supports two configuration modes: +* `daemon` +* `systemd` + +The configuration mode can be changed by setting the `configurationMode` field in the `SriovOperatorConfig` CR. + +_**Note**: This setting is global and applies to all sriov-network-operator-daemons in the cluster._ + +In the `daemon` mode, which historically is the first implemented mode, +the operator will setup NICs with _**SRIOV legacy**_ configuration directly in the **sriov-network-operator-daemon** +component by executing all enabled plugins. + +When the operator is in `systemd` mode, the **sriov-network-operator-daemon** component will execute most plugins +in the same way as in the `daemon` mode but will skip the call of the *generic* or *virtual* +plugin(when running in a virtualized environment) and instead will render config for the systemd +service that starts on the next OS boot and calls one of these plugins. +Then, the result of the service execution is handled by the **sriov-network-operator-daemon**. + +The `systemd` mode was implemented to support scenarios when, after the host reboot, +we need VFs to be configured before Kubernetes (kubelet) and Pods with workloads are started. + +To setup NICs with _**switchdev**_ configuration, the operator uses a different flow that ignores +the `configurationMode` setting. Two systemd services(not the same as used for systemd mode) are created on the node. +The first service is executed before the NetworkManager starts, and the second one after. +Both services run bash scripts. The script from the first service is responsible for VFs creation and for +switching a NIC to the switchdev eSwitch mode. The script from the second service binds VFs to the required drivers. + +If a NIC has _**switchdev**_ configuration, then `configurationMode` of the operator does not affect it. + +```mermaid +--- +title: Current logic +--- +flowchart TD; + operatorMode["SriovOperatorConfig.configurationMode"]; + nicMode["NIC's eSwitch mode"]; + inDaemon["apply configuration(legacy) in + sriov-network-operator-daemon"] + bashSystemd["create two switchdev services(bash scripts) + to handle configuration(switchdev) on boot"]; + systemdSystemd["create single systemd service(go code) + to handle configuration(legacy) on boot"] + + nicMode-- switchdev --> bashSystemd; + nicMode-- legacy --> operatorMode; + operatorMode-- daemon --> inDaemon; + operatorMode-- systemd --> systemdSystemd; + +``` + +#### Problems of the current implementation + +* it is confusing that `configurationMode` does not affect devices with switchdev configuration. +* system services for switchdev configuration are shell scripts completely independent from the +main code base and it is hard to extend them with new functionality. +* for switchdev NICs, VF configuration flow (bash-based) has some limitations compared to legacy VF configuration. +* it is impossible to apply switchdev configuration for the NIC without reboot. + +### Use Cases + +* As a developer I don't want to maintain the code with similar logic in two places: +switchdev bash scrips and **sriov-network-operator-daemon** code. +* As a developer and a user I want to have only one set of systemd services that handle +both _**switchdev**_ configurations and `systemd` mode. +* As a user I want `configurationMode` to work the same way for NICs with +_**legacy**_ and _**switchdev**_ configurations. +* As a user I want to apply _**switchdev**_ configuration for NIC by the **sriov-network-operator-daemon** +without reboot (in case if reboot is not required by other logic, +e.g. kernel parameters configuration, FW configuration). + +### Goals + +* it should be possible to apply _**switchdev**_ configuration in the **sriov-network-operator-daemon** without reboot. +* the code used by `daemon` and `systemd` modes to handle _**switchdev**_ and _**legacy**_ +configurations should be the same Golang code. +* `configurationMode` option should work the same for NICs with _**legacy**_ and _**switchdev**_ configurations. +* the operator should use unified systemd services which will be deployed only +if the operator works in the `systemd` mode. +* `systemd` mode should be changed to support 2 stage configuration: +pre system network manager (NetworkManager or netplan) and after system network manager. + _Note: This is required to support all use-cases supported by the current switchdev implementation._ + + +### Non-Goals + +* replace _Externally Manage PF_ feature +* remove all shell scripts from the code + +## Proposal + +1. Drop existing bash-based implementation which is used for NICs with _**switchdev**_ configuration +2. Modify _generic_ and _virtual (if required)_ plugins to support _**switchdev**_ configuration +3. Modify code related to the _Externally Manage PF_ feature +to support _**switchdev**_ configuration +4. Modify `systemd` mode flow to handle devices with both _**legacy**_ and _**switchdev**_ configurations +5. Split `systemd` mode system service to two parts: + - `pre` - executes before NetworkManager/netplan and OVS + - `after` - executes after NetworkManager/netplan and OVS + +```mermaid +--- +title: Proposed logic +--- +flowchart TD; + operatorMode["SriovOperatorConfig.configurationMode"]; + inDaemon["apply configurations(legacy and switchdev) in + sriov-network-operator-daemon"] + systemdSystemd["create `pre` and `after` systemd services(go code) + to handle configurations(legacy and switchdev) on boot"] + + operatorMode-- daemon --> inDaemon; + operatorMode-- systemd --> systemdSystemd; + +``` + + +### Workflow Description + +Users using only NICs with _**legacy**_ SRIOV configurations will not need to change their workflow. +The operator should behave for these configurations the same way as it does now. + +Users using NICs with _**switchdev**_ configurations will need to explicitly set operator's +`configurationMode` to `systemd` if they expect the configuration of the NIC to happen +early on boot (before Kubernetes starts) to support the hwoffload use-case. + +### API Extensions + +#### SriovNetworkNodeState CR + +`SriovNetworkNodeState.status.interfaces[*].Vfs[*].vdpaType` field should be added. + +This field should be used to report information about type of the VDPA +device that is configured for VF. +Empty string means that there is no VDPA device. + +Valid values are: `virtio`, `vhost` (same as in `SriovNetworkNodePolicySpec`) + +``` +type VirtualFunction struct { + Name string `json:"name,omitempty"` + Mac string `json:"mac,omitempty"` + Assigned string `json:"assigned,omitempty"` + Driver string `json:"driver,omitempty"` + PciAddress string `json:"pciAddress"` + Vendor string `json:"vendor,omitempty"` + DeviceID string `json:"deviceID,omitempty"` + Vlan int `json:"Vlan,omitempty"` + Mtu int `json:"mtu,omitempty"` + VfID int `json:"vfID"` ++ VdpaType string `json:"vdpaType,omitempty"` +} +``` + +#### SriovOperatorConfig CR + +Change in the operator's behavior: `configurationMode` option now have effect +on NICs with _**switchdev**_ configurations. + +### Implementation Details/Notes/Constraints + +We should consider improving unit-test coverage for modified code parts during the implementation. + +After the operator upgrade, we should clean up from the host unneeded files (scripts, system services, config files) created by the previous version of the operator. + +### Upgrade & Downgrade considerations + +* after upgrading the operator, _**switchdev**_ config will be applied by **sriov-network-operator-daemon** and not by systemd service unless the user changes `configurationMode` setting to `systemd` +* after upgrading the operator, "implicit mixed mode" when _**switchdev**_ NIC configurations are handled by bash scripts(in systemd services) +and _**legacy**_ NIC configurations are managed by **sriov-network-operator-daemon** will not be supported anymore. + +_Note: `configurationMode` is a global setting, so the user will need to decide +which mode to use for the entire cluster_ + +Upgrade/Downgrade for users using only NICs with _**legacy**_ configurations will not require any actions. +Upgrade/Downgrade for clusters with _**switchdev**_ configurations will require +changing the operator's `configurationMode` option. + +### Test Plan + +The proposed changes will not introduce new functionality. + +After the refactoring, _**switchdev**_ configurations will also be supported in the `daemon` mode. +This is the only thing we may need to develop additional tests for. +All other changes should be validated by running regression testing. + +_Note: behavior for _**switchdev**_ configurations will be changed in a non-fully compatible way; +this may require to fix existing tests._ From 30d6790388184509fb01b629e83fa6b079b0574c Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Wed, 10 Jan 2024 16:04:56 +0200 Subject: [PATCH 14/61] Add vdpaType field to the node SriovNetworkNodeState CRD This field should be used to report information about type of the VDPA device that is configured for VF. Empty string means that there is no VDPA device. Valid values are: `virtio`, `vhost` (same as in `SriovNetworkNodePolicySpec`) Signed-off-by: Yury Kulazhenkov --- api/v1/sriovnetworknodestate_types.go | 1 + .../bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml | 2 ++ .../crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml | 2 ++ 3 files changed, 5 insertions(+) diff --git a/api/v1/sriovnetworknodestate_types.go b/api/v1/sriovnetworknodestate_types.go index a653b391f..8d4023adb 100644 --- a/api/v1/sriovnetworknodestate_types.go +++ b/api/v1/sriovnetworknodestate_types.go @@ -82,6 +82,7 @@ type VirtualFunction struct { Vlan int `json:"Vlan,omitempty"` Mtu int `json:"mtu,omitempty"` VfID int `json:"vfID"` + VdpaType string `json:"vdpaType,omitempty"` } // SriovNetworkNodeStateStatus defines the observed state of SriovNetworkNodeState diff --git a/config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml index 8e756f681..e5674e3df 100644 --- a/config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml +++ b/config/crd/bases/sriovnetwork.openshift.io_sriovnetworknodestates.yaml @@ -112,6 +112,8 @@ spec: type: string pciAddress: type: string + vdpaType: + type: string vendor: type: string vfID: diff --git a/deployment/sriov-network-operator/crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/deployment/sriov-network-operator/crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml index 8e756f681..e5674e3df 100644 --- a/deployment/sriov-network-operator/crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml +++ b/deployment/sriov-network-operator/crds/sriovnetwork.openshift.io_sriovnetworknodestates.yaml @@ -112,6 +112,8 @@ spec: type: string pciAddress: type: string + vdpaType: + type: string vendor: type: string vfID: From 3620e1ae44dc5463ea3431e7c32f1c10cd86e6c9 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Thu, 11 Jan 2024 09:12:57 +0100 Subject: [PATCH 15/61] Refactor mtuFilePath to clean up and reduce duplicate code --- pkg/host/network.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/host/network.go b/pkg/host/network.go index 14885f6b9..dab12b354 100644 --- a/pkg/host/network.go +++ b/pkg/host/network.go @@ -142,15 +142,18 @@ func (n *network) IsSwitchdev(name string) bool { return true } +func mtuFilePath(ifaceName string, pciAddr string) string { + mtuFile := "net/" + ifaceName + "/mtu" + return filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, mtuFile) +} + func (n *network) GetNetdevMTU(pciAddr string) int { log.Log.V(2).Info("GetNetdevMTU(): get MTU", "device", pciAddr) ifaceName := n.TryGetInterfaceName(pciAddr) if ifaceName == "" { return 0 } - mtuFile := "net/" + ifaceName + "/mtu" - mtuFilePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, mtuFile) - data, err := os.ReadFile(mtuFilePath) + data, err := os.ReadFile(mtuFilePath(ifaceName, pciAddr)) if err != nil { log.Log.Error(err, "GetNetdevMTU(): fail to read mtu file", "path", mtuFilePath) return 0 @@ -179,8 +182,7 @@ func (n *network) SetNetdevMTU(pciAddr string, mtu int) error { if len(ifaceName) < 1 { return fmt.Errorf("SetNetdevMTU(): interface name is empty") } - mtuFile := "net/" + ifaceName[0] + "/mtu" - mtuFilePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, mtuFile) + mtuFilePath := mtuFilePath(ifaceName[0], pciAddr) return os.WriteFile(mtuFilePath, []byte(strconv.Itoa(mtu)), os.ModeAppend) }, backoff.WithMaxRetries(b, 10)) if err != nil { From e2b45f44da9086e706502c33574f41444d3dcf05 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Thu, 11 Jan 2024 09:14:31 +0100 Subject: [PATCH 16/61] Ignore goconst in conformance tests --- .golangci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index d21d5c8c4..2125187e0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,6 +25,7 @@ linters-settings: goconst: min-len: 2 min-occurrences: 2 + ignore-tests: true gocritic: enabled-tags: - diagnostic @@ -118,4 +119,7 @@ issues: - lll - stylecheck - goconst + - path: test/conformance/tests + linters: + - goconst From 0c155510688b4e24b757f206cd568f3c5a6825d1 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Thu, 11 Jan 2024 09:14:48 +0100 Subject: [PATCH 17/61] Fix goconst errors --- api/v1/helper.go | 7 ++++--- controllers/sriovnetworkpoolconfig_controller.go | 6 +++++- pkg/daemon/daemon.go | 5 +++-- pkg/platforms/openstack/openstack.go | 14 ++++++++------ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/api/v1/helper.go b/api/v1/helper.go index 664531260..712a54874 100644 --- a/api/v1/helper.go +++ b/api/v1/helper.go @@ -37,7 +37,8 @@ const ( SriovCniStateAuto = "auto" SriovCniStateOff = "off" SriovCniStateOn = "on" - SriovCniIpamEmpty = "\"ipam\":{}" + SriovCniIpam = "\"ipam\"" + SriovCniIpamEmpty = SriovCniIpam + ":{}" ) const invalidVfIndex = -1 @@ -595,7 +596,7 @@ func (cr *SriovIBNetwork) RenderNetAttDef() (*uns.Unstructured, error) { } if cr.Spec.IPAM != "" { - data.Data["SriovCniIpam"] = "\"ipam\":" + strings.Join(strings.Fields(cr.Spec.IPAM), "") + data.Data["SriovCniIpam"] = SriovCniIpam + ":" + strings.Join(strings.Fields(cr.Spec.IPAM), "") } else { data.Data["SriovCniIpam"] = SriovCniIpamEmpty } @@ -730,7 +731,7 @@ func (cr *SriovNetwork) RenderNetAttDef() (*uns.Unstructured, error) { } if cr.Spec.IPAM != "" { - data.Data["SriovCniIpam"] = "\"ipam\":" + strings.Join(strings.Fields(cr.Spec.IPAM), "") + data.Data["SriovCniIpam"] = SriovCniIpam + ":" + strings.Join(strings.Fields(cr.Spec.IPAM), "") } else { data.Data["SriovCniIpam"] = SriovCniIpamEmpty } diff --git a/controllers/sriovnetworkpoolconfig_controller.go b/controllers/sriovnetworkpoolconfig_controller.go index fd4643476..211fdd9cf 100644 --- a/controllers/sriovnetworkpoolconfig_controller.go +++ b/controllers/sriovnetworkpoolconfig_controller.go @@ -29,6 +29,10 @@ type SriovNetworkPoolConfigReconciler struct { PlatformHelper platforms.Interface } +const ( + mcPriority string = "00-" +) + //+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs/status,verbs=get;update;patch //+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworkpoolconfigs/finalizers,verbs=update @@ -126,7 +130,7 @@ func (r *SriovNetworkPoolConfigReconciler) syncOvsHardwareOffloadMachineConfigs( logger := log.Log.WithName("syncOvsHardwareOffloadMachineConfigs") mcpName := nc.Spec.OvsHardwareOffloadConfig.Name - mcName := "00-" + mcpName + "-" + constants.OVSHWOLMachineConfigNameSuffix + mcName := mcPriority + mcpName + "-" + constants.OVSHWOLMachineConfigNameSuffix foundMC := &mcfgv1.MachineConfig{} mcp := &mcfgv1.MachineConfigPool{} diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 290b4400e..9d4a43e94 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -206,12 +206,13 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { } var timeout int64 = 5 + var metadataKey = "metadata.name" dn.mu = &sync.Mutex{} informerFactory := sninformer.NewFilteredSharedInformerFactory(dn.client, time.Second*15, namespace, func(lo *metav1.ListOptions) { - lo.FieldSelector = "metadata.name=" + vars.NodeName + lo.FieldSelector = metadataKey + "=" + vars.NodeName lo.TimeoutSeconds = &timeout }, ) @@ -228,7 +229,7 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { time.Second*30, namespace, func(lo *metav1.ListOptions) { - lo.FieldSelector = "metadata.name=" + "default" + lo.FieldSelector = metadataKey + "=" + "default" }, ) diff --git a/pkg/platforms/openstack/openstack.go b/pkg/platforms/openstack/openstack.go index 658995727..b86e079ca 100644 --- a/pkg/platforms/openstack/openstack.go +++ b/pkg/platforms/openstack/openstack.go @@ -24,15 +24,17 @@ const ( ospHostMetaDataDir = "/host/var/config/openstack/2018-08-27" ospMetaDataDir = "/var/config/openstack/2018-08-27" ospMetaDataBaseURL = "http://169.254.169.254/openstack/2018-08-27" - ospHostNetworkDataFile = ospHostMetaDataDir + "/network_data.json" - ospHostMetaDataFile = ospHostMetaDataDir + "/meta_data.json" - ospNetworkDataURL = ospMetaDataBaseURL + "/network_data.json" - ospMetaDataURL = ospMetaDataBaseURL + "/meta_data.json" + ospNetworkDataJSON = "network_data.json" + ospMetaDataJSON = "meta_data.json" + ospHostNetworkDataFile = ospHostMetaDataDir + "/" + ospNetworkDataJSON + ospHostMetaDataFile = ospHostMetaDataDir + "/" + ospMetaDataJSON + ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON + ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON ) var ( - ospNetworkDataFile = ospMetaDataDir + "/network_data.json" - ospMetaDataFile = ospMetaDataDir + "/meta_data.json" + ospNetworkDataFile = ospMetaDataDir + "/" + ospNetworkDataJSON + ospMetaDataFile = ospMetaDataDir + "/" + ospMetaDataJSON ) //go:generate ../../../bin/mockgen -destination mock/mock_openstack.go -source openstack.go From 9c2a7d320e348bd91902c1a60b30744a3a123b72 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Wed, 10 Jan 2024 10:49:03 +0100 Subject: [PATCH 18/61] Update to golang 1.21 --- go.mod | 4 ++-- go.sum | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index adc5d6772..07a3178d8 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/k8snetworkplumbingwg/sriov-network-operator -go 1.20 +go 1.21 require ( github.com/Masterminds/sprig/v3 v3.2.2 @@ -27,7 +27,6 @@ require ( github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae go.uber.org/zap v1.25.0 golang.org/x/time v0.3.0 - gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.28.3 k8s.io/apiextensions-apiserver v0.28.3 @@ -140,6 +139,7 @@ require ( google.golang.org/grpc v1.54.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect howett.net/plist v1.0.0 // indirect k8s.io/cli-runtime v0.28.3 // indirect k8s.io/component-base v0.28.3 // indirect diff --git a/go.sum b/go.sum index 22d7d524b..dfaf5fdc2 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,14 @@ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9 github.com/ajeddeloh/go-json v0.0.0-20170920214419-6a2fe990e083 h1:uwcvnXW76Y0rHM+qs7y8iHknWUWXYFNlD6FEVhc47TU= github.com/ajeddeloh/go-json v0.0.0-20170920214419-6a2fe990e083/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.28 h1:SaPM7dlmp7h3Lj1nJ4jdzOkTdom08+g20k7AU5heZYg= github.com/aws/aws-sdk-go v1.30.28/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beevik/etree v1.1.1-0.20200718192613-4a2f8b9d084c/go.mod h1:0yGO2rna3S9DkITDWHY1bMtcY4IJ4w+4S+EooZUR0bE= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -112,6 +114,7 @@ github.com/coreos/vcontext v0.0.0-20211021162308-f1dbbca7bef4/go.mod h1:HckqHnP/ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -131,7 +134,9 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -302,6 +307,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -312,6 +318,7 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= @@ -343,7 +350,9 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= @@ -377,9 +386,11 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -442,6 +453,7 @@ go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -808,6 +820,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From dad8ddca1dea79efff563231aafc50e1e6e748bd Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Wed, 27 Dec 2023 15:21:03 +0100 Subject: [PATCH 19/61] bump golang version in GitHub actions --- .github/workflows/test.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 75696ffde..f0bb6f31f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v3 with: - go-version: 1.20.x + go-version: 1.21.x - name: Check out code into the Go module directory uses: actions/checkout@v2 @@ -32,10 +32,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v2 with: - go-version: 1.20.x + go-version: 1.21.x - name: Check out code into the Go module directory uses: actions/checkout@v2 @@ -53,10 +53,10 @@ jobs: name: Golangci-lint runs-on: ubuntu-latest steps: - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v2 with: - go-version: 1.20.x + go-version: 1.21.x - name: Check out code into the Go module directory uses: actions/checkout@v2 - name: golangci-lint @@ -70,10 +70,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v2 with: - go-version: 1.20.x + go-version: 1.21.x - name: Check out code into the Go module directory uses: actions/checkout@v2 @@ -107,10 +107,10 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v2 - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v3 with: - go-version: 1.20.x + go-version: 1.21.x - name: run test run: make test-e2e-conformance-virtual-k8s-cluster-ci @@ -141,10 +141,10 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v2 - - name: Set up Go 1.20 + - name: Set up Go 1.21 uses: actions/setup-go@v3 with: - go-version: 1.20.x + go-version: 1.21.x - name: run test run: make test-e2e-conformance-virtual-ocp-cluster-ci From 98ee66cda46a9761af30de1d48248e6adadd2db8 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Wed, 27 Dec 2023 15:21:25 +0100 Subject: [PATCH 20/61] bump golang version in Dockerfile --- Dockerfile | 2 +- Dockerfile.sriov-network-config-daemon | 2 +- Dockerfile.webhook | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7e871754c..8e503f2ad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20 AS builder +FROM golang:1.21 AS builder WORKDIR /go/src/github.com/k8snetworkplumbingwg/sriov-network-operator COPY . . RUN make _build-manager BIN_PATH=build/_output/cmd diff --git a/Dockerfile.sriov-network-config-daemon b/Dockerfile.sriov-network-config-daemon index e37ea87b9..6f7069362 100644 --- a/Dockerfile.sriov-network-config-daemon +++ b/Dockerfile.sriov-network-config-daemon @@ -1,4 +1,4 @@ -FROM golang:1.20 AS builder +FROM golang:1.21 AS builder WORKDIR /go/src/github.com/k8snetworkplumbingwg/sriov-network-operator COPY . . RUN make _build-sriov-network-config-daemon BIN_PATH=build/_output/cmd diff --git a/Dockerfile.webhook b/Dockerfile.webhook index bc3994917..2ea2c006d 100644 --- a/Dockerfile.webhook +++ b/Dockerfile.webhook @@ -1,4 +1,4 @@ -FROM golang:1.20 AS builder +FROM golang:1.21 AS builder WORKDIR /go/src/github.com/k8snetworkplumbingwg/sriov-network-operator COPY . . RUN make _build-webhook BIN_PATH=build/_output/cmd From c5245b9d31f2ee2fe5d0a5b9b0a7ac62baa1b516 Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Thu, 28 Dec 2023 15:10:33 +0100 Subject: [PATCH 21/61] Bump golangci-lint to latest version as of today --- .github/workflows/test.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f0bb6f31f..4476a96d7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,7 +63,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.51.0 + version: v1.55.2 test-coverage: name: test-coverage diff --git a/Makefile b/Makefile index 90e7ef468..df5f6c91d 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ GOLANGCI_LINT = $(BIN_DIR)/golangci-lint # golangci-lint version should be updated periodically # we keep it fixed to avoid it from unexpectedly failing on the project # in case of a version bump -GOLANGCI_LINT_VER = v1.51.0 +GOLANGCI_LINT_VER = v1.55.2 .PHONY: all build clean gendeepcopy test test-e2e test-e2e-k8s run image fmt sync-manifests test-e2e-conformance manifests update-codegen From 708f0d5f53386d74f990547285f87f5ade7db5cd Mon Sep 17 00:00:00 2001 From: Balazs Nemeth Date: Thu, 11 Jan 2024 09:12:43 +0100 Subject: [PATCH 22/61] Update golangci to use new config format for depguard --- .golangci.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2125187e0..253c4ff23 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,13 +10,11 @@ run: - pkg/client linters-settings: depguard: - list-type: blacklist - packages: - # logging is allowed only by logutils.Log, logrus - # is allowed to use only in logutils package - - github.com/sirupsen/logrus - packages-with-error-message: - - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" + rules: + main: + deny: + - pkg: github.com/sirupsen/logrus + desc: "logging is allowed only by logutils.Log" dupl: threshold: 100 funlen: From 12e3306ee3aaea6750f630a2b3d1f4bd82f08fdc Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 9 Jan 2024 17:06:14 +0200 Subject: [PATCH 23/61] Add additional methods to host/kernel.go New methods are: * BindDriverByBusAndDevice - binds device to the provided driver * UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver Both methods allows to work with devices not only on PCI bus. +refactor driver-related methods +add unit-tests for changed methods Signed-off-by: Yury Kulazhenkov --- pkg/consts/constants.go | 9 +- pkg/helper/mock/mock_helper.go | 28 +++++ pkg/host/kernel.go | 222 +++++++++++++++++++++++---------- pkg/host/kernel_test.go | 216 ++++++++++++++++++++++++++++++++ pkg/host/suite_test.go | 21 ++++ 5 files changed, 429 insertions(+), 67 deletions(-) create mode 100644 pkg/host/kernel_test.go create mode 100644 pkg/host/suite_test.go diff --git a/pkg/consts/constants.go b/pkg/consts/constants.go index d56d36e7f..e7255368d 100644 --- a/pkg/consts/constants.go +++ b/pkg/consts/constants.go @@ -77,13 +77,16 @@ const ( CheckpointFileName = "sno-initial-node-state.json" Unknown = "Unknown" - SysBusPciDevices = "/sys/bus/pci/devices" - SysBusPciDrivers = "/sys/bus/pci/drivers" - SysBusPciDriversProbe = "/sys/bus/pci/drivers_probe" + SysBus = "/sys/bus" + SysBusPciDevices = SysBus + "/pci/devices" + SysBusPciDrivers = SysBus + "/pci/drivers" + SysBusPciDriversProbe = SysBus + "/pci/drivers_probe" SysClassNet = "/sys/class/net" ProcKernelCmdLine = "/proc/cmdline" NetClass = 0x02 NumVfsFile = "sriov_numvfs" + BusPci = "pci" + BusVdpa = "vdpa" UdevFolder = "/etc/udev" UdevRulesFolder = UdevFolder + "/rules.d" diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index 74814f4e6..75015a925 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -81,6 +81,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) BindDpdkDriver(arg0, arg1 interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDpdkDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDpdkDriver), arg0, arg1) } +// BindDriverByBusAndDevice mocks base method. +func (m *MockHostHelpersInterface) BindDriverByBusAndDevice(arg0, arg1, arg2 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDriverByBusAndDevice", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDriverByBusAndDevice indicates an expected call of BindDriverByBusAndDevice. +func (mr *MockHostHelpersInterfaceMockRecorder) BindDriverByBusAndDevice(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDriverByBusAndDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDriverByBusAndDevice), arg0, arg1, arg2) +} + // Chroot mocks base method. func (m *MockHostHelpersInterface) Chroot(arg0 string) (func() error, error) { m.ctrl.T.Helper() @@ -994,6 +1008,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) Unbind(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockHostHelpersInterface)(nil).Unbind), arg0) } +// UnbindDriverByBusAndDevice mocks base method. +func (m *MockHostHelpersInterface) UnbindDriverByBusAndDevice(bus, device string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbindDriverByBusAndDevice", bus, device) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnbindDriverByBusAndDevice indicates an expected call of UnbindDriverByBusAndDevice. +func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverByBusAndDevice(bus, device interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverByBusAndDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).UnbindDriverByBusAndDevice), bus, device) +} + // UnbindDriverIfNeeded mocks base method. func (m *MockHostHelpersInterface) UnbindDriverIfNeeded(arg0 string, arg1 bool) error { m.ctrl.T.Helper() diff --git a/pkg/host/kernel.go b/pkg/host/kernel.go index ac7277eef..171807d95 100644 --- a/pkg/host/kernel.go +++ b/pkg/host/kernel.go @@ -1,12 +1,12 @@ package host import ( + "errors" "fmt" "os" "path/filepath" "strings" - dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" "sigs.k8s.io/controller-runtime/pkg/log" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" @@ -36,12 +36,21 @@ type KernelInterface interface { BindDpdkDriver(string, string) error // BindDefaultDriver binds the virtual function to is default driver BindDefaultDriver(string) error + // BindDriverByBusAndDevice binds device to the provided driver + // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" + // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA + // driver - the name of the driver, e.g. vfio-pci or vhost_vdpa. + BindDriverByBusAndDevice(bus, device, driver string) error // HasDriver returns try if the virtual function is bind to a driver HasDriver(string) (bool, string) // RebindVfToDefaultDriver rebinds the virtual function to is default driver RebindVfToDefaultDriver(string) error // UnbindDriverIfNeeded unbinds the virtual function from a driver if needed UnbindDriverIfNeeded(string, bool) error + // UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver + // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" + // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA + UnbindDriverByBusAndDevice(bus, device string) error // LoadKernelModule loads a kernel module to the host LoadKernelModule(name string, args ...string) error // IsKernelModuleLoaded returns try if the requested kernel module is loaded @@ -165,18 +174,7 @@ func (k *kernel) IsKernelArgsSet(cmdLine string, karg string) bool { // Unbind unbind driver for one device func (k *kernel) Unbind(pciAddr string) error { log.Log.V(2).Info("Unbind(): unbind device driver for device", "device", pciAddr) - yes, driver := k.HasDriver(pciAddr) - if !yes { - return nil - } - - filePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDrivers, driver, "unbind") - err := os.WriteFile(filePath, []byte(pciAddr), os.ModeAppend) - if err != nil { - log.Log.Error(err, "Unbind(): fail to unbind driver for device", "device", pciAddr) - return err - } - return nil + return k.UnbindDriverByBusAndDevice(consts.BusPci, pciAddr) } // BindDpdkDriver bind dpdk driver for one device @@ -184,45 +182,15 @@ func (k *kernel) Unbind(pciAddr string) error { func (k *kernel) BindDpdkDriver(pciAddr, driver string) error { log.Log.V(2).Info("BindDpdkDriver(): bind device to driver", "device", pciAddr, "driver", driver) - - if yes, d := k.HasDriver(pciAddr); yes { - if driver == d { - log.Log.V(2).Info("BindDpdkDriver(): device already bound to driver", - "device", pciAddr, "driver", driver) - return nil - } - - if err := k.Unbind(pciAddr); err != nil { - return err - } - } - - driverOverridePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "driver_override") - err := os.WriteFile(driverOverridePath, []byte(driver), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): fail to write driver_override for device", - "device", pciAddr, "driver", driver) - return err - } - bindPath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDrivers, driver, "bind") - err = os.WriteFile(bindPath, []byte(pciAddr), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): fail to bind driver for device", - "driver", driver, "device", pciAddr) - _, err := os.Readlink(filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "iommu_group")) - if err != nil { + if err := k.BindDriverByBusAndDevice(consts.BusPci, pciAddr, driver); err != nil { + _, innerErr := os.Readlink(filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "iommu_group")) + if innerErr != nil { log.Log.Error(err, "Could not read IOMMU group for device", "device", pciAddr) return fmt.Errorf( - "cannot bind driver %s to device %s, make sure IOMMU is enabled in BIOS. %w", driver, pciAddr, err) + "cannot bind driver %s to device %s, make sure IOMMU is enabled in BIOS. %w", driver, pciAddr, innerErr) } return err } - err = os.WriteFile(driverOverridePath, []byte(""), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDpdkDriver(): failed to clear driver_override for device", "device", pciAddr) - return err - } - return nil } @@ -231,32 +199,58 @@ func (k *kernel) BindDpdkDriver(pciAddr, driver string) error { func (k *kernel) BindDefaultDriver(pciAddr string) error { log.Log.V(2).Info("BindDefaultDriver(): bind device to default driver", "device", pciAddr) - if yes, d := k.HasDriver(pciAddr); yes { - if !sriovnetworkv1.StringInArray(d, vars.DpdkDrivers) { + curDriver, err := getDriverByBusAndDevice(consts.BusPci, pciAddr) + if err != nil { + return err + } + if curDriver != "" { + if !sriovnetworkv1.StringInArray(curDriver, vars.DpdkDrivers) { log.Log.V(2).Info("BindDefaultDriver(): device already bound to default driver", - "device", pciAddr, "driver", d) + "device", pciAddr, "driver", curDriver) return nil } - if err := k.Unbind(pciAddr); err != nil { + if err := k.UnbindDriverByBusAndDevice(consts.BusPci, pciAddr); err != nil { return err } } - - driverOverridePath := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDevices, pciAddr, "driver_override") - err := os.WriteFile(driverOverridePath, []byte("\x00"), os.ModeAppend) - if err != nil { - log.Log.Error(err, "BindDefaultDriver(): failed to write driver_override for device", "device", pciAddr) + if err := setDriverOverride(consts.BusPci, pciAddr, ""); err != nil { + return err + } + if err := probeDriver(consts.BusPci, pciAddr); err != nil { return err } + return nil +} - pciDriversProbe := filepath.Join(vars.FilesystemRoot, consts.SysBusPciDriversProbe) - err = os.WriteFile(pciDriversProbe, []byte(pciAddr), os.ModeAppend) +// BindDriverByBusAndDevice binds device to the provided driver +// bus - the bus path in the sysfs, e.g. "pci" or "vdpa" +// device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA +// driver - the name of the driver, e.g. vfio-pci or vhost_vdpa. +func (k *kernel) BindDriverByBusAndDevice(bus, device, driver string) error { + log.Log.V(2).Info("BindDriverByBusAndDevice(): bind device to driver", + "bus", bus, "device", device, "driver", driver) + + curDriver, err := getDriverByBusAndDevice(bus, device) if err != nil { - log.Log.Error(err, "BindDefaultDriver(): failed to bind driver for device", "device", pciAddr) return err } - - return nil + if curDriver != "" { + if curDriver == driver { + log.Log.V(2).Info("BindDriverByBusAndDevice(): device already bound to driver", + "bus", bus, "device", device, "driver", driver) + return nil + } + if err := k.UnbindDriverByBusAndDevice(bus, device); err != nil { + return err + } + } + if err := setDriverOverride(bus, device, driver); err != nil { + return err + } + if err := bindDriver(bus, device, driver); err != nil { + return err + } + return setDriverOverride(bus, device, "") } // Workaround function to handle a case where the vf default driver is stuck and not able to create the vf kernel interface. @@ -287,14 +281,33 @@ func (k *kernel) UnbindDriverIfNeeded(vfAddr string, isRdma bool) error { return nil } +// UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver +// bus - the bus path in the sysfs, e.g. "pci" or "vdpa" +// device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA +func (k *kernel) UnbindDriverByBusAndDevice(bus, device string) error { + log.Log.V(2).Info("UnbindDriverByBusAndDevice(): unbind device driver for device", "bus", bus, "device", device) + driver, err := getDriverByBusAndDevice(bus, device) + if err != nil { + return err + } + if driver == "" { + log.Log.V(2).Info("UnbindDriverByBusAndDevice(): device has no driver", "bus", bus, "device", device) + return nil + } + return unbindDriver(bus, device, driver) +} + func (k *kernel) HasDriver(pciAddr string) (bool, string) { - driver, err := dputils.GetDriverName(pciAddr) + driver, err := getDriverByBusAndDevice(consts.BusPci, pciAddr) if err != nil { log.Log.V(2).Info("HasDriver(): device driver is empty for device", "device", pciAddr) return false, "" } - log.Log.V(2).Info("HasDriver(): device driver for device", "device", pciAddr, "driver", driver) - return true, driver + if driver != "" { + log.Log.V(2).Info("HasDriver(): device driver for device", "device", pciAddr, "driver", driver) + return true, driver + } + return false, "" } func (k *kernel) TryEnableRdma() (bool, error) { @@ -625,3 +638,84 @@ func (k *kernel) IsKernelLockdownMode() bool { } return strings.Contains(stdout, "[integrity]") || strings.Contains(stdout, "[confidentiality]") } + +// returns driver for device on the bus +func getDriverByBusAndDevice(bus, device string) (string, error) { + driverLink := filepath.Join(vars.FilesystemRoot, consts.SysBus, bus, "devices", device, "driver") + driverInfo, err := os.Readlink(driverLink) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + log.Log.V(2).Info("getDriverByBusAndDevice(): driver path for device not exist", "bus", bus, "device", device, "driver", driverInfo) + return "", nil + } + log.Log.Error(err, "getDriverByBusAndDevice(): error getting driver info for device", "bus", bus, "device", device) + return "", err + } + log.Log.V(2).Info("getDriverByBusAndDevice(): driver for device", "bus", bus, "device", device, "driver", driverInfo) + return filepath.Base(driverInfo), nil +} + +// binds device to the provide driver +func bindDriver(bus, device, driver string) error { + log.Log.V(2).Info("bindDriver(): bind to driver", "bus", bus, "device", device, "driver", driver) + bindPath := filepath.Join(vars.FilesystemRoot, consts.SysBus, bus, "drivers", driver, "bind") + err := os.WriteFile(bindPath, []byte(device), os.ModeAppend) + if err != nil { + log.Log.Error(err, "bindDriver(): failed to bind driver", "bus", bus, "device", device, "driver", driver) + return err + } + return nil +} + +// unbind device from the driver +func unbindDriver(bus, device, driver string) error { + log.Log.V(2).Info("unbindDriver(): unbind from driver", "bus", bus, "device", device, "driver", driver) + unbindPath := filepath.Join(vars.FilesystemRoot, consts.SysBus, bus, "drivers", driver, "unbind") + err := os.WriteFile(unbindPath, []byte(device), os.ModeAppend) + if err != nil { + log.Log.Error(err, "unbindDriver(): failed to unbind driver", "bus", bus, "device", device, "driver", driver) + return err + } + return nil +} + +// probes driver for device on the bus +func probeDriver(bus, device string) error { + log.Log.V(2).Info("probeDriver(): drivers probe", "bus", bus, "device", device) + probePath := filepath.Join(vars.FilesystemRoot, consts.SysBus, bus, "drivers_probe") + err := os.WriteFile(probePath, []byte(device), os.ModeAppend) + if err != nil { + log.Log.Error(err, "probeDriver(): failed to trigger driver probe", "bus", bus, "device", device) + return err + } + return nil +} + +// set driver override for the bus/device, +// resets override if override arg is "", +// if device doesn't support overriding (has no driver_override path), does nothing +func setDriverOverride(bus, device, override string) error { + driverOverridePath := filepath.Join(vars.FilesystemRoot, consts.SysBus, bus, "devices", device, "driver_override") + if _, err := os.Stat(driverOverridePath); err != nil { + if os.IsNotExist(err) { + log.Log.V(2).Info("setDriverOverride(): device doesn't support driver override, skip", "bus", bus, "device", device) + return nil + } + return err + } + var overrideData []byte + if override != "" { + log.Log.V(2).Info("setDriverOverride(): configure driver override for device", "bus", bus, "device", device, "driver", override) + overrideData = []byte(override) + } else { + log.Log.V(2).Info("setDriverOverride(): reset driver override for device", "bus", bus, "device", device) + overrideData = []byte("\x00") + } + err := os.WriteFile(driverOverridePath, overrideData, os.ModeAppend) + if err != nil { + log.Log.Error(err, "setDriverOverride(): fail to write driver_override for device", + "bus", bus, "device", device, "driver", override) + return err + } + return nil +} diff --git a/pkg/host/kernel_test.go b/pkg/host/kernel_test.go new file mode 100644 index 000000000..687cda454 --- /dev/null +++ b/pkg/host/kernel_test.go @@ -0,0 +1,216 @@ +package host + +import ( + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" +) + +func assertFileContentsEquals(path, expectedContent string) { + d, err := os.ReadFile(filepath.Join(vars.FilesystemRoot, path)) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + ExpectWithOffset(1, string(d)).To(Equal(expectedContent)) +} + +var _ = Describe("Kernel", func() { + Context("Drivers", func() { + var ( + k KernelInterface + ) + configureFS := func(f *fakefilesystem.FS) { + var ( + cleanFakeFs func() + err error + ) + vars.FilesystemRoot, cleanFakeFs, err = f.Use() + Expect(err).ToNot(HaveOccurred()) + DeferCleanup(cleanFakeFs) + } + BeforeEach(func() { + k = newKernelInterface(nil) + }) + Context("Unbind, UnbindDriverByBusAndDevice", func() { + It("unknown device", func() { + Expect(k.UnbindDriverByBusAndDevice(consts.BusPci, "unknown-dev")).NotTo(HaveOccurred()) + }) + It("known device, no driver", func() { + configureFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) + Expect(k.Unbind("0000:d8:00.0")).NotTo(HaveOccurred()) + }) + It("has driver, succeed", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/test-driver"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers/test-driver/unbind": {}}, + }) + Expect(k.Unbind("0000:d8:00.0")).NotTo(HaveOccurred()) + // check that echo to unbind path was done + assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + }) + It("has driver, failed to unbind", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + }) + Expect(k.Unbind("0000:d8:00.0")).To(HaveOccurred()) + }) + }) + Context("HasDriver", func() { + It("unknown device", func() { + has, driver := k.HasDriver("unknown-dev") + Expect(has).To(BeFalse()) + Expect(driver).To(BeEmpty()) + }) + It("known device, no driver", func() { + configureFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) + has, driver := k.HasDriver("0000:d8:00.0") + Expect(has).To(BeFalse()) + Expect(driver).To(BeEmpty()) + }) + It("has driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/test-driver"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + }) + has, driver := k.HasDriver("0000:d8:00.0") + Expect(has).To(BeTrue()) + Expect(driver).To(Equal("test-driver")) + }) + }) + Context("BindDefaultDriver", func() { + It("unknown device", func() { + Expect(k.BindDefaultDriver("unknown-dev")).To(HaveOccurred()) + }) + It("no driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers_probe": {}, "/sys/bus/pci/devices/0000:d8:00.0/driver_override": {}}, + }) + Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) + // should probe driver for dev + assertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") + }) + It("already bind to default driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + }) + Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) + }) + It("bind to dpdk driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/vfio-pci"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/vfio-pci"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers_probe": {}, + "/sys/bus/pci/drivers/vfio-pci/unbind": {}}, + }) + Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) + // should unbind from dpdk driver + assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/unbind", "0000:d8:00.0") + // should probe driver for dev + assertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") + }) + }) + Context("BindDpdkDriver", func() { + It("unknown device", func() { + Expect(k.BindDpdkDriver("unknown-dev", "vfio-pci")).To(HaveOccurred()) + }) + It("no driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/vfio-pci"}, + Files: map[string][]byte{ + "/sys/bus/pci/devices/0000:d8:00.0/driver_override": {}}, + }) + Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) + // should reset driver override + assertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/driver_override", "\x00") + }) + It("already bind to required driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/vfio-pci"}, + }) + Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) + }) + It("bind to wrong driver", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/test-driver", + "/sys/bus/pci/drivers/vfio-pci"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers/test-driver/unbind": {}, + "/sys/bus/pci/drivers/vfio-pci/bind": {}, + "/sys/bus/pci/devices/0000:d8:00.0/driver_override": {}}, + }) + Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) + // should unbind from driver1 + assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + // should bind to driver2 + assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") + }) + It("fail to bind", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/test-driver"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers/test-driver/unbind": {}, + "/sys/bus/pci/devices/0000:d8:00.0/driver_override": {}}, + }) + Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).To(HaveOccurred()) + }) + }) + Context("BindDriverByBusAndDevice", func() { + It("device doesn't support driver_override", func() { + configureFS(&fakefilesystem.FS{ + Dirs: []string{ + "/sys/bus/pci/devices/0000:d8:00.0", + "/sys/bus/pci/drivers/test-driver", + "/sys/bus/pci/drivers/vfio-pci"}, + Symlinks: map[string]string{ + "/sys/bus/pci/devices/0000:d8:00.0/driver": "../../../../bus/pci/drivers/test-driver"}, + Files: map[string][]byte{ + "/sys/bus/pci/drivers/test-driver/unbind": {}, + "/sys/bus/pci/drivers/vfio-pci/bind": {}}, + }) + Expect(k.BindDriverByBusAndDevice(consts.BusPci, "0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) + // should unbind from driver1 + assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + // should bind to driver2 + assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") + }) + }) + }) +}) diff --git a/pkg/host/suite_test.go b/pkg/host/suite_test.go new file mode 100644 index 000000000..674437292 --- /dev/null +++ b/pkg/host/suite_test.go @@ -0,0 +1,21 @@ +package host + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "go.uber.org/zap/zapcore" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func TestHostManager(t *testing.T) { + log.SetLogger(zap.New( + zap.WriteTo(GinkgoWriter), + zap.Level(zapcore.Level(-2)), + zap.UseDevMode(true))) + RegisterFailHandler(Fail) + RunSpecs(t, "Package Host Suite") +} From f22ea7076f7444d3d1a38db0d1a0bb5939fa9edb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:08:38 +0000 Subject: [PATCH 24/61] Bump google.golang.org/grpc from 1.54.0 to 1.56.3 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.54.0 to 1.56.3. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.54.0...v1.56.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 4 +- go.sum | 8 +- vendor/github.com/golang/glog/glog.go | 1217 +++++------------ vendor/github.com/golang/glog/glog_file.go | 305 ++++- vendor/github.com/golang/glog/glog_flags.go | 395 ++++++ .../golang/glog/internal/logsink/logsink.go | 387 ++++++ .../glog/internal/logsink/logsink_fatal.go | 35 + .../glog/internal/stackdump/stackdump.go | 127 ++ vendor/google.golang.org/grpc/CONTRIBUTING.md | 4 - .../grpc/attributes/attributes.go | 29 + .../grpc/balancer/balancer.go | 2 +- .../grpc/balancer_conn_wrappers.go | 486 ++++--- .../grpc_binarylog_v1/binarylog.pb.go | 2 +- vendor/google.golang.org/grpc/call.go | 5 + vendor/google.golang.org/grpc/clientconn.go | 622 ++++++--- vendor/google.golang.org/grpc/dialoptions.go | 30 + vendor/google.golang.org/grpc/idle.go | 287 ++++ .../grpc/internal/binarylog/binarylog.go | 3 + .../grpc/internal/binarylog/method_logger.go | 9 + .../grpc/internal/buffer/unbounded.go | 26 +- .../grpc/internal/envconfig/envconfig.go | 4 + .../grpc/internal/envconfig/observability.go | 6 + .../grpc/internal/envconfig/xds.go | 21 +- .../grpc/internal/grpcrand/grpcrand.go | 14 + .../internal/grpcsync/callback_serializer.go | 119 ++ .../grpc/internal/internal.go | 24 + .../grpc/internal/serviceconfig/duration.go | 130 ++ .../grpc/internal/transport/controlbuf.go | 17 +- .../grpc/internal/transport/handler_server.go | 11 +- .../grpc/internal/transport/http2_client.go | 27 +- .../grpc/internal/transport/http2_server.go | 74 +- .../grpc/internal/transport/http_util.go | 2 - .../grpc/internal/transport/logging.go | 40 + .../grpc/internal/transport/transport.go | 2 +- .../google.golang.org/grpc/picker_wrapper.go | 38 +- vendor/google.golang.org/grpc/pickfirst.go | 52 +- .../grpc/resolver/resolver.go | 16 +- .../grpc/resolver_conn_wrapper.go | 229 ++-- vendor/google.golang.org/grpc/server.go | 99 +- .../google.golang.org/grpc/service_config.go | 75 +- .../google.golang.org/grpc/status/status.go | 53 +- vendor/google.golang.org/grpc/stream.go | 29 +- vendor/google.golang.org/grpc/version.go | 2 +- vendor/modules.txt | 8 +- 44 files changed, 3415 insertions(+), 1660 deletions(-) create mode 100644 vendor/github.com/golang/glog/glog_flags.go create mode 100644 vendor/github.com/golang/glog/internal/logsink/logsink.go create mode 100644 vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go create mode 100644 vendor/github.com/golang/glog/internal/stackdump/stackdump.go create mode 100644 vendor/google.golang.org/grpc/idle.go create mode 100644 vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go create mode 100644 vendor/google.golang.org/grpc/internal/serviceconfig/duration.go create mode 100644 vendor/google.golang.org/grpc/internal/transport/logging.go diff --git a/go.mod b/go.mod index 07a3178d8..4c3878244 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/go-openapi/swag v0.22.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.0.0 // indirect + github.com/golang/glog v1.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // indirect @@ -136,7 +136,7 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect - google.golang.org/grpc v1.54.0 // indirect + google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index dfaf5fdc2..f8763b531 100644 --- a/go.sum +++ b/go.sum @@ -173,8 +173,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -795,8 +795,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/vendor/github.com/golang/glog/glog.go b/vendor/github.com/golang/glog/glog.go index 718c34f88..e108ae8b4 100644 --- a/vendor/github.com/golang/glog/glog.go +++ b/vendor/github.com/golang/glog/glog.go @@ -1,6 +1,6 @@ -// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ +// Go support for leveled logs, analogous to https://github.com/google/glog. // -// Copyright 2013 Google Inc. All Rights Reserved. +// Copyright 2023 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -50,15 +50,15 @@ // Log files will be written to this directory instead of the // default temporary directory. // -// Other flags provide aids to debugging. +// Other flags provide aids to debugging. // // -log_backtrace_at="" -// When set to a file and line number holding a logging statement, -// such as +// A comma-separated list of file and line numbers holding a logging +// statement, such as // -log_backtrace_at=gopherflakes.go:234 -// a stack trace will be written to the Info log whenever execution -// hits that statement. (Unlike with -vmodule, the ".go" must be -// present.) +// A stack trace will be written to the Info log whenever execution +// hits one of these statements. (Unlike with -vmodule, the ".go" +// must bepresent.) // -v=0 // Enable V-leveled logging at the specified level. // -vmodule="" @@ -66,100 +66,47 @@ // where pattern is a literal file name (minus the ".go" suffix) or // "glob" pattern and N is a V level. For instance, // -vmodule=gopher*=3 -// sets the V level to 3 in all Go files whose names begin "gopher". -// +// sets the V level to 3 in all Go files whose names begin with "gopher", +// and +// -vmodule=/path/to/glog/glog_test=1 +// sets the V level to 1 in the Go file /path/to/glog/glog_test.go. +// If a glob pattern contains a slash, it is matched against the full path, +// and the file name. Otherwise, the pattern is +// matched only against the file's basename. When both -vmodule and -v +// are specified, the -vmodule values take precedence for the specified +// modules. package glog +// This file contains the parts of the log package that are shared among all +// implementations (file, envelope, and appengine). + import ( - "bufio" "bytes" "errors" - "flag" "fmt" - "io" stdLog "log" "os" - "path/filepath" + "reflect" "runtime" + "runtime/pprof" "strconv" - "strings" "sync" "sync/atomic" + "syscall" "time" -) - -// severity identifies the sort of log: info, warning etc. It also implements -// the flag.Value interface. The -stderrthreshold flag is of type severity and -// should be modified only through the flag.Value interface. The values match -// the corresponding constants in C++. -type severity int32 // sync/atomic int32 -// These constants identify the log levels in order of increasing severity. -// A message written to a high-severity log file is also written to each -// lower-severity log file. -const ( - infoLog severity = iota - warningLog - errorLog - fatalLog - numSeverity = 4 + "github.com/golang/glog/internal/logsink" + "github.com/golang/glog/internal/stackdump" ) -const severityChar = "IWEF" - -var severityName = []string{ - infoLog: "INFO", - warningLog: "WARNING", - errorLog: "ERROR", - fatalLog: "FATAL", -} - -// get returns the value of the severity. -func (s *severity) get() severity { - return severity(atomic.LoadInt32((*int32)(s))) -} - -// set sets the value of the severity. -func (s *severity) set(val severity) { - atomic.StoreInt32((*int32)(s), int32(val)) -} - -// String is part of the flag.Value interface. -func (s *severity) String() string { - return strconv.FormatInt(int64(*s), 10) -} - -// Get is part of the flag.Value interface. -func (s *severity) Get() interface{} { - return *s -} +var timeNow = time.Now // Stubbed out for testing. -// Set is part of the flag.Value interface. -func (s *severity) Set(value string) error { - var threshold severity - // Is it a known name? - if v, ok := severityByName(value); ok { - threshold = v - } else { - v, err := strconv.Atoi(value) - if err != nil { - return err - } - threshold = severity(v) - } - logging.stderrThreshold.set(threshold) - return nil -} +// MaxSize is the maximum size of a log file in bytes. +var MaxSize uint64 = 1024 * 1024 * 1800 -func severityByName(s string) (severity, bool) { - s = strings.ToUpper(s) - for i, name := range severityName { - if name == s { - return severity(i), true - } - } - return 0, false -} +// ErrNoLog is the error we return if no log file has yet been created +// for the specified log type. +var ErrNoLog = errors.New("log file not yet created") // OutputStats tracks the number of output lines and bytes written. type OutputStats struct { @@ -183,724 +130,99 @@ var Stats struct { Info, Warning, Error OutputStats } -var severityStats = [numSeverity]*OutputStats{ - infoLog: &Stats.Info, - warningLog: &Stats.Warning, - errorLog: &Stats.Error, +var severityStats = [...]*OutputStats{ + logsink.Info: &Stats.Info, + logsink.Warning: &Stats.Warning, + logsink.Error: &Stats.Error, + logsink.Fatal: nil, } -// Level is exported because it appears in the arguments to V and is -// the type of the v flag, which can be set programmatically. -// It's a distinct type because we want to discriminate it from logType. -// Variables of type level are only changed under logging.mu. -// The -v flag is read only with atomic ops, so the state of the logging -// module is consistent. - -// Level is treated as a sync/atomic int32. - -// Level specifies a level of verbosity for V logs. *Level implements -// flag.Value; the -v flag is of type Level and should be modified -// only through the flag.Value interface. +// Level specifies a level of verbosity for V logs. The -v flag is of type +// Level and should be modified only through the flag.Value interface. type Level int32 -// get returns the value of the Level. -func (l *Level) get() Level { - return Level(atomic.LoadInt32((*int32)(l))) -} - -// set sets the value of the Level. -func (l *Level) set(val Level) { - atomic.StoreInt32((*int32)(l), int32(val)) -} - -// String is part of the flag.Value interface. -func (l *Level) String() string { - return strconv.FormatInt(int64(*l), 10) -} +var metaPool sync.Pool // Pool of *logsink.Meta. -// Get is part of the flag.Value interface. -func (l *Level) Get() interface{} { - return *l -} - -// Set is part of the flag.Value interface. -func (l *Level) Set(value string) error { - v, err := strconv.Atoi(value) - if err != nil { - return err - } - logging.mu.Lock() - defer logging.mu.Unlock() - logging.setVState(Level(v), logging.vmodule.filter, false) - return nil -} - -// moduleSpec represents the setting of the -vmodule flag. -type moduleSpec struct { - filter []modulePat -} - -// modulePat contains a filter for the -vmodule flag. -// It holds a verbosity level and a file pattern to match. -type modulePat struct { - pattern string - literal bool // The pattern is a literal string - level Level -} - -// match reports whether the file matches the pattern. It uses a string -// comparison if the pattern contains no metacharacters. -func (m *modulePat) match(file string) bool { - if m.literal { - return file == m.pattern - } - match, _ := filepath.Match(m.pattern, file) - return match -} - -func (m *moduleSpec) String() string { - // Lock because the type is not atomic. TODO: clean this up. - logging.mu.Lock() - defer logging.mu.Unlock() - var b bytes.Buffer - for i, f := range m.filter { - if i > 0 { - b.WriteRune(',') - } - fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) +// metaPoolGet returns a *logsink.Meta from metaPool as both an interface and a +// pointer, allocating a new one if necessary. (Returning the interface value +// directly avoids an allocation if there was an existing pointer in the pool.) +func metaPoolGet() (any, *logsink.Meta) { + if metai := metaPool.Get(); metai != nil { + return metai, metai.(*logsink.Meta) } - return b.String() -} - -// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the -// struct is not exported. -func (m *moduleSpec) Get() interface{} { - return nil + meta := new(logsink.Meta) + return meta, meta } -var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") - -// Syntax: -vmodule=recordio=2,file=1,gfs*=3 -func (m *moduleSpec) Set(value string) error { - var filter []modulePat - for _, pat := range strings.Split(value, ",") { - if len(pat) == 0 { - // Empty strings such as from a trailing comma can be ignored. - continue - } - patLev := strings.Split(pat, "=") - if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { - return errVmoduleSyntax - } - pattern := patLev[0] - v, err := strconv.Atoi(patLev[1]) - if err != nil { - return errors.New("syntax error: expect comma-separated list of filename=N") - } - if v < 0 { - return errors.New("negative value for vmodule level") - } - if v == 0 { - continue // Ignore. It's harmless but no point in paying the overhead. - } - // TODO: check syntax of filter? - filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)}) - } - logging.mu.Lock() - defer logging.mu.Unlock() - logging.setVState(logging.verbosity, filter, true) - return nil -} - -// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters -// that require filepath.Match to be called to match the pattern. -func isLiteral(pattern string) bool { - return !strings.ContainsAny(pattern, `\*?[]`) -} - -// traceLocation represents the setting of the -log_backtrace_at flag. -type traceLocation struct { - file string - line int -} - -// isSet reports whether the trace location has been specified. -// logging.mu is held. -func (t *traceLocation) isSet() bool { - return t.line > 0 -} +type stack bool -// match reports whether the specified file and line matches the trace location. -// The argument file name is the full path, not the basename specified in the flag. -// logging.mu is held. -func (t *traceLocation) match(file string, line int) bool { - if t.line != line { - return false - } - if i := strings.LastIndex(file, "/"); i >= 0 { - file = file[i+1:] - } - return t.file == file -} - -func (t *traceLocation) String() string { - // Lock because the type is not atomic. TODO: clean this up. - logging.mu.Lock() - defer logging.mu.Unlock() - return fmt.Sprintf("%s:%d", t.file, t.line) -} - -// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the -// struct is not exported -func (t *traceLocation) Get() interface{} { - return nil -} - -var errTraceSyntax = errors.New("syntax error: expect file.go:234") - -// Syntax: -log_backtrace_at=gopherflakes.go:234 -// Note that unlike vmodule the file extension is included here. -func (t *traceLocation) Set(value string) error { - if value == "" { - // Unset. - t.line = 0 - t.file = "" - } - fields := strings.Split(value, ":") - if len(fields) != 2 { - return errTraceSyntax - } - file, line := fields[0], fields[1] - if !strings.Contains(file, ".") { - return errTraceSyntax - } - v, err := strconv.Atoi(line) - if err != nil { - return errTraceSyntax - } - if v <= 0 { - return errors.New("negative or zero value for level") - } - logging.mu.Lock() - defer logging.mu.Unlock() - t.line = v - t.file = file - return nil -} - -// flushSyncWriter is the interface satisfied by logging destinations. -type flushSyncWriter interface { - Flush() error - Sync() error - io.Writer -} - -func init() { - flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files") - flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") - flag.Var(&logging.verbosity, "v", "log level for V logs") - flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") - flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") - flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") - - // Default stderrThreshold is ERROR. - logging.stderrThreshold = errorLog - - logging.setVState(0, nil, false) - go logging.flushDaemon() -} - -// Flush flushes all pending log I/O. -func Flush() { - logging.lockAndFlushAll() -} - -// loggingT collects all the global state of the logging setup. -type loggingT struct { - // Boolean flags. Not handled atomically because the flag.Value interface - // does not let us avoid the =true, and that shorthand is necessary for - // compatibility. TODO: does this matter enough to fix? Seems unlikely. - toStderr bool // The -logtostderr flag. - alsoToStderr bool // The -alsologtostderr flag. - - // Level flag. Handled atomically. - stderrThreshold severity // The -stderrthreshold flag. - - // freeList is a list of byte buffers, maintained under freeListMu. - freeList *buffer - // freeListMu maintains the free list. It is separate from the main mutex - // so buffers can be grabbed and printed to without holding the main lock, - // for better parallelization. - freeListMu sync.Mutex - - // mu protects the remaining elements of this structure and is - // used to synchronize logging. - mu sync.Mutex - // file holds writer for each of the log types. - file [numSeverity]flushSyncWriter - // pcs is used in V to avoid an allocation when computing the caller's PC. - pcs [1]uintptr - // vmap is a cache of the V Level for each V() call site, identified by PC. - // It is wiped whenever the vmodule flag changes state. - vmap map[uintptr]Level - // filterLength stores the length of the vmodule filter chain. If greater - // than zero, it means vmodule is enabled. It may be read safely - // using sync.LoadInt32, but is only modified under mu. - filterLength int32 - // traceLocation is the state of the -log_backtrace_at flag. - traceLocation traceLocation - // These flags are modified only under lock, although verbosity may be fetched - // safely using atomic.LoadInt32. - vmodule moduleSpec // The state of the -vmodule flag. - verbosity Level // V logging level, the value of the -v flag/ -} - -// buffer holds a byte Buffer for reuse. The zero value is ready for use. -type buffer struct { - bytes.Buffer - tmp [64]byte // temporary byte array for creating headers. - next *buffer -} - -var logging loggingT - -// setVState sets a consistent state for V logging. -// l.mu is held. -func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) { - // Turn verbosity off so V will not fire while we are in transition. - logging.verbosity.set(0) - // Ditto for filter length. - atomic.StoreInt32(&logging.filterLength, 0) - - // Set the new filters and wipe the pc->Level map if the filter has changed. - if setFilter { - logging.vmodule.filter = filter - logging.vmap = make(map[uintptr]Level) - } - - // Things are consistent now, so enable filtering and verbosity. - // They are enabled in order opposite to that in V. - atomic.StoreInt32(&logging.filterLength, int32(len(filter))) - logging.verbosity.set(verbosity) -} - -// getBuffer returns a new, ready-to-use buffer. -func (l *loggingT) getBuffer() *buffer { - l.freeListMu.Lock() - b := l.freeList - if b != nil { - l.freeList = b.next - } - l.freeListMu.Unlock() - if b == nil { - b = new(buffer) - } else { - b.next = nil - b.Reset() - } - return b -} - -// putBuffer returns a buffer to the free list. -func (l *loggingT) putBuffer(b *buffer) { - if b.Len() >= 256 { - // Let big buffers die a natural death. - return - } - l.freeListMu.Lock() - b.next = l.freeList - l.freeList = b - l.freeListMu.Unlock() -} - -var timeNow = time.Now // Stubbed out for testing. +const ( + noStack = stack(false) + withStack = stack(true) +) -/* -header formats a log header as defined by the C++ implementation. -It returns a buffer containing the formatted header and the user's file and line number. -The depth specifies how many stack frames above lives the source line to be identified in the log message. - -Log lines have this form: - Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... -where the fields are defined as follows: - L A single character, representing the log level (eg 'I' for INFO) - mm The month (zero padded; ie May is '05') - dd The day (zero padded) - hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds - threadid The space-padded thread ID as returned by GetTID() - file The file name - line The line number - msg The user-supplied message -*/ -func (l *loggingT) header(s severity, depth int) (*buffer, string, int) { - _, file, line, ok := runtime.Caller(3 + depth) +func appendBacktrace(depth int, format string, args []any) (string, []any) { + // Capture a backtrace as a stackdump.Stack (both text and PC slice). + // Structured log sinks can extract the backtrace in whichever format they + // prefer (PCs or text), and Text sinks will include it as just another part + // of the log message. + // + // Use depth instead of depth+1 so that the backtrace always includes the + // log function itself - otherwise the reason for the trace appearing in the + // log may not be obvious to the reader. + dump := stackdump.Caller(depth) + + // Add an arg and an entry in the format string for the stack dump. + // + // Copy the "args" slice to avoid a rare but serious aliasing bug + // (corrupting the caller's slice if they passed it to a non-Fatal call + // using "..."). + format = format + "\n\n%v\n" + args = append(append([]any(nil), args...), dump) + + return format, args +} + +// logf writes a log message for a log function call (or log function wrapper) +// at the given depth in the current goroutine's stack. +func logf(depth int, severity logsink.Severity, verbose bool, stack stack, format string, args ...any) { + now := timeNow() + _, file, line, ok := runtime.Caller(depth + 1) if !ok { file = "???" line = 1 - } else { - slash := strings.LastIndex(file, "/") - if slash >= 0 { - file = file[slash+1:] - } } - return l.formatHeader(s, file, line), file, line -} -// formatHeader formats a log header using the provided file name and line number. -func (l *loggingT) formatHeader(s severity, file string, line int) *buffer { - now := timeNow() - if line < 0 { - line = 0 // not a real line number, but acceptable to someDigits + if stack == withStack || backtraceAt(file, line) { + format, args = appendBacktrace(depth+1, format, args) } - if s > fatalLog { - s = infoLog // for safety. - } - buf := l.getBuffer() - - // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. - // It's worth about 3X. Fprintf is hard. - _, month, day := now.Date() - hour, minute, second := now.Clock() - // Lmmdd hh:mm:ss.uuuuuu threadid file:line] - buf.tmp[0] = severityChar[s] - buf.twoDigits(1, int(month)) - buf.twoDigits(3, day) - buf.tmp[5] = ' ' - buf.twoDigits(6, hour) - buf.tmp[8] = ':' - buf.twoDigits(9, minute) - buf.tmp[11] = ':' - buf.twoDigits(12, second) - buf.tmp[14] = '.' - buf.nDigits(6, 15, now.Nanosecond()/1000, '0') - buf.tmp[21] = ' ' - buf.nDigits(7, 22, pid, ' ') // TODO: should be TID - buf.tmp[29] = ' ' - buf.Write(buf.tmp[:30]) - buf.WriteString(file) - buf.tmp[0] = ':' - n := buf.someDigits(1, line) - buf.tmp[n+1] = ']' - buf.tmp[n+2] = ' ' - buf.Write(buf.tmp[:n+3]) - return buf -} - -// Some custom tiny helper functions to print the log header efficiently. - -const digits = "0123456789" -// twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i]. -func (buf *buffer) twoDigits(i, d int) { - buf.tmp[i+1] = digits[d%10] - d /= 10 - buf.tmp[i] = digits[d%10] -} - -// nDigits formats an n-digit integer at buf.tmp[i], -// padding with pad on the left. -// It assumes d >= 0. -func (buf *buffer) nDigits(n, i, d int, pad byte) { - j := n - 1 - for ; j >= 0 && d > 0; j-- { - buf.tmp[i+j] = digits[d%10] - d /= 10 - } - for ; j >= 0; j-- { - buf.tmp[i+j] = pad - } -} - -// someDigits formats a zero-prefixed variable-width integer at buf.tmp[i]. -func (buf *buffer) someDigits(i, d int) int { - // Print into the top, then copy down. We know there's space for at least - // a 10-digit number. - j := len(buf.tmp) - for { - j-- - buf.tmp[j] = digits[d%10] - d /= 10 - if d == 0 { - break - } + metai, meta := metaPoolGet() + *meta = logsink.Meta{ + Time: now, + File: file, + Line: line, + Depth: depth + 1, + Severity: severity, + Verbose: verbose, + Thread: int64(pid), } - return copy(buf.tmp[i:], buf.tmp[j:]) + sinkf(meta, format, args...) + metaPool.Put(metai) } -func (l *loggingT) println(s severity, args ...interface{}) { - buf, file, line := l.header(s, 0) - fmt.Fprintln(buf, args...) - l.output(s, buf, file, line, false) -} - -func (l *loggingT) print(s severity, args ...interface{}) { - l.printDepth(s, 1, args...) -} - -func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) { - buf, file, line := l.header(s, depth) - fmt.Fprint(buf, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, false) -} - -func (l *loggingT) printf(s severity, format string, args ...interface{}) { - buf, file, line := l.header(s, 0) - fmt.Fprintf(buf, format, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, false) -} - -// printWithFileLine behaves like print but uses the provided file and line number. If -// alsoLogToStderr is true, the log message always appears on standard error; it -// will also appear in the log file unless --logtostderr is set. -func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) { - buf := l.formatHeader(s, file, line) - fmt.Fprint(buf, args...) - if buf.Bytes()[buf.Len()-1] != '\n' { - buf.WriteByte('\n') - } - l.output(s, buf, file, line, alsoToStderr) -} - -// output writes the data to the log files and releases the buffer. -func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { - l.mu.Lock() - if l.traceLocation.isSet() { - if l.traceLocation.match(file, line) { - buf.Write(stacks(false)) - } - } - data := buf.Bytes() - if !flag.Parsed() { - os.Stderr.Write([]byte("ERROR: logging before flag.Parse: ")) - os.Stderr.Write(data) - } else if l.toStderr { - os.Stderr.Write(data) - } else { - if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { - os.Stderr.Write(data) - } - if l.file[s] == nil { - if err := l.createFiles(s); err != nil { - os.Stderr.Write(data) // Make sure the message appears somewhere. - l.exit(err) - } - } - switch s { - case fatalLog: - l.file[fatalLog].Write(data) - fallthrough - case errorLog: - l.file[errorLog].Write(data) - fallthrough - case warningLog: - l.file[warningLog].Write(data) - fallthrough - case infoLog: - l.file[infoLog].Write(data) - } - } - if s == fatalLog { - // If we got here via Exit rather than Fatal, print no stacks. - if atomic.LoadUint32(&fatalNoStacks) > 0 { - l.mu.Unlock() - timeoutFlush(10 * time.Second) - os.Exit(1) - } - // Dump all goroutine stacks before exiting. - // First, make sure we see the trace for the current goroutine on standard error. - // If -logtostderr has been specified, the loop below will do that anyway - // as the first stack in the full dump. - if !l.toStderr { - os.Stderr.Write(stacks(false)) - } - // Write the stack trace for all goroutines to the files. - trace := stacks(true) - logExitFunc = func(error) {} // If we get a write error, we'll still exit below. - for log := fatalLog; log >= infoLog; log-- { - if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. - f.Write(trace) - } - } - l.mu.Unlock() - timeoutFlush(10 * time.Second) - os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway. - } - l.putBuffer(buf) - l.mu.Unlock() - if stats := severityStats[s]; stats != nil { +func sinkf(meta *logsink.Meta, format string, args ...any) { + meta.Depth++ + n, err := logsink.Printf(meta, format, args...) + if stats := severityStats[meta.Severity]; stats != nil { atomic.AddInt64(&stats.lines, 1) - atomic.AddInt64(&stats.bytes, int64(len(data))) - } -} - -// timeoutFlush calls Flush and returns when it completes or after timeout -// elapses, whichever happens first. This is needed because the hooks invoked -// by Flush may deadlock when glog.Fatal is called from a hook that holds -// a lock. -func timeoutFlush(timeout time.Duration) { - done := make(chan bool, 1) - go func() { - Flush() // calls logging.lockAndFlushAll() - done <- true - }() - select { - case <-done: - case <-time.After(timeout): - fmt.Fprintln(os.Stderr, "glog: Flush took longer than", timeout) - } -} - -// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. -func stacks(all bool) []byte { - // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. - n := 10000 - if all { - n = 100000 - } - var trace []byte - for i := 0; i < 5; i++ { - trace = make([]byte, n) - nbytes := runtime.Stack(trace, all) - if nbytes < len(trace) { - return trace[:nbytes] - } - n *= 2 - } - return trace -} - -// logExitFunc provides a simple mechanism to override the default behavior -// of exiting on error. Used in testing and to guarantee we reach a required exit -// for fatal logs. Instead, exit could be a function rather than a method but that -// would make its use clumsier. -var logExitFunc func(error) - -// exit is called if there is trouble creating or writing log files. -// It flushes the logs and exits the program; there's no point in hanging around. -// l.mu is held. -func (l *loggingT) exit(err error) { - fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err) - // If logExitFunc is set, we do that instead of exiting. - if logExitFunc != nil { - logExitFunc(err) - return - } - l.flushAll() - os.Exit(2) -} - -// syncBuffer joins a bufio.Writer to its underlying file, providing access to the -// file's Sync method and providing a wrapper for the Write method that provides log -// file rotation. There are conflicting methods, so the file cannot be embedded. -// l.mu is held for all its methods. -type syncBuffer struct { - logger *loggingT - *bufio.Writer - file *os.File - sev severity - nbytes uint64 // The number of bytes written to this file -} - -func (sb *syncBuffer) Sync() error { - return sb.file.Sync() -} - -func (sb *syncBuffer) Write(p []byte) (n int, err error) { - if sb.nbytes+uint64(len(p)) >= MaxSize { - if err := sb.rotateFile(time.Now()); err != nil { - sb.logger.exit(err) - } + atomic.AddInt64(&stats.bytes, int64(n)) } - n, err = sb.Writer.Write(p) - sb.nbytes += uint64(n) - if err != nil { - sb.logger.exit(err) - } - return -} -// rotateFile closes the syncBuffer's file and starts a new one. -func (sb *syncBuffer) rotateFile(now time.Time) error { - if sb.file != nil { - sb.Flush() - sb.file.Close() - } - var err error - sb.file, _, err = create(severityName[sb.sev], now) - sb.nbytes = 0 if err != nil { - return err - } - - sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) - - // Write header. - var buf bytes.Buffer - fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) - fmt.Fprintf(&buf, "Running on machine: %s\n", host) - fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) - fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") - n, err := sb.file.Write(buf.Bytes()) - sb.nbytes += uint64(n) - return err -} - -// bufferSize sizes the buffer associated with each log file. It's large -// so that log records can accumulate without the logging thread blocking -// on disk I/O. The flushDaemon will block instead. -const bufferSize = 256 * 1024 - -// createFiles creates all the log files for severity from sev down to infoLog. -// l.mu is held. -func (l *loggingT) createFiles(sev severity) error { - now := time.Now() - // Files are created in decreasing severity order, so as soon as we find one - // has already been created, we can stop. - for s := sev; s >= infoLog && l.file[s] == nil; s-- { - sb := &syncBuffer{ - logger: l, - sev: s, - } - if err := sb.rotateFile(now); err != nil { - return err - } - l.file[s] = sb - } - return nil -} - -const flushInterval = 30 * time.Second - -// flushDaemon periodically flushes the log file buffers. -func (l *loggingT) flushDaemon() { - for range time.NewTicker(flushInterval).C { - l.lockAndFlushAll() - } -} - -// lockAndFlushAll is like flushAll but locks l.mu first. -func (l *loggingT) lockAndFlushAll() { - l.mu.Lock() - l.flushAll() - l.mu.Unlock() -} - -// flushAll flushes all the logs and attempts to "sync" their data to disk. -// l.mu is held. -func (l *loggingT) flushAll() { - // Flush from fatal down, in case there's trouble flushing. - for s := fatalLog; s >= infoLog; s-- { - file := l.file[s] - if file != nil { - file.Flush() // ignore error - file.Sync() // ignore error - } + logsink.Printf(meta, "glog: exiting because of error: %s", err) + sinks.file.Flush() + os.Exit(2) } } @@ -912,9 +234,9 @@ func (l *loggingT) flushAll() { // Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not // recognized, CopyStandardLogTo panics. func CopyStandardLogTo(name string) { - sev, ok := severityByName(name) - if !ok { - panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name)) + sev, err := logsink.ParseSeverity(name) + if err != nil { + panic(fmt.Sprintf("log.CopyStandardLogTo(%q): %v", name, err)) } // Set a log format that captures the user's file and line: // d.go:23: message @@ -922,9 +244,22 @@ func CopyStandardLogTo(name string) { stdLog.SetOutput(logBridge(sev)) } +// NewStandardLogger returns a Logger that writes to the Google logs for the +// named and lower severities. +// +// Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not +// recognized, NewStandardLogger panics. +func NewStandardLogger(name string) *stdLog.Logger { + sev, err := logsink.ParseSeverity(name) + if err != nil { + panic(fmt.Sprintf("log.NewStandardLogger(%q): %v", name, err)) + } + return stdLog.New(logBridge(sev), "", stdLog.Lshortfile) +} + // logBridge provides the Write method that enables CopyStandardLogTo to connect // Go's standard logs to the logs provided by this package. -type logBridge severity +type logBridge logsink.Severity // Write parses the standard logging line and passes its components to the // logger for severity(lb). @@ -946,36 +281,72 @@ func (lb logBridge) Write(b []byte) (n int, err error) { line = 1 } } - // printWithFileLine with alsoToStderr=true, so standard log messages - // always appear on standard error. - logging.printWithFileLine(severity(lb), file, line, true, text) + + // The depth below hard-codes details of how stdlog gets here. The alternative would be to walk + // up the stack looking for src/log/log.go but that seems like it would be + // unfortunately slow. + const stdLogDepth = 4 + + metai, meta := metaPoolGet() + *meta = logsink.Meta{ + Time: timeNow(), + File: file, + Line: line, + Depth: stdLogDepth, + Severity: logsink.Severity(lb), + Thread: int64(pid), + } + + format := "%s" + args := []any{text} + if backtraceAt(file, line) { + format, args = appendBacktrace(meta.Depth, format, args) + } + + sinkf(meta, format, args...) + metaPool.Put(metai) + return len(b), nil } -// setV computes and remembers the V level for a given PC -// when vmodule is enabled. -// File pattern matching takes the basename of the file, stripped -// of its .go suffix, and uses filepath.Match, which is a little more -// general than the *? matching used in C++. -// l.mu is held. -func (l *loggingT) setV(pc uintptr) Level { - fn := runtime.FuncForPC(pc) - file, _ := fn.FileLine(pc) - // The file is something like /a/b/c/d.go. We want just the d. - if strings.HasSuffix(file, ".go") { - file = file[:len(file)-3] +// defaultFormat returns a fmt.Printf format specifier that formats its +// arguments as if they were passed to fmt.Print. +func defaultFormat(args []any) string { + n := len(args) + switch n { + case 0: + return "" + case 1: + return "%v" + } + + b := make([]byte, 0, n*3-1) + wasString := true // Suppress leading space. + for _, arg := range args { + isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String + if wasString || isString { + b = append(b, "%v"...) + } else { + b = append(b, " %v"...) + } + wasString = isString } - if slash := strings.LastIndex(file, "/"); slash >= 0 { - file = file[slash+1:] + return string(b) +} + +// lnFormat returns a fmt.Printf format specifier that formats its arguments +// as if they were passed to fmt.Println. +func lnFormat(args []any) string { + if len(args) == 0 { + return "\n" } - for _, filter := range l.vmodule.filter { - if filter.match(file) { - l.vmap[pc] = filter.level - return filter.level - } + + b := make([]byte, 0, len(args)*3) + for range args { + b = append(b, "%v "...) } - l.vmap[pc] = 0 - return 0 + b[len(b)-1] = '\n' // Replace the last space with a newline. + return string(b) } // Verbose is a boolean type that implements Infof (like Printf) etc. @@ -986,9 +357,13 @@ type Verbose bool // The returned value is a boolean of type Verbose, which implements Info, Infoln // and Infof. These methods will write to the Info log if called. // Thus, one may write either +// // if glog.V(2) { glog.Info("log this") } +// // or +// // glog.V(2).Info("log this") +// // The second form is shorter but the first is cheaper if logging is off because it does // not evaluate its arguments. // @@ -997,184 +372,250 @@ type Verbose bool // V is at most the value of -v, or of -vmodule for the source file containing the // call, the V call will log. func V(level Level) Verbose { - // This function tries hard to be cheap unless there's work to do. - // The fast path is two atomic loads and compares. + return VDepth(1, level) +} - // Here is a cheap but safe test to see if V logging is enabled globally. - if logging.verbosity.get() >= level { - return Verbose(true) - } +// VDepth acts as V but uses depth to determine which call frame to check vmodule for. +// VDepth(0, level) is the same as V(level). +func VDepth(depth int, level Level) Verbose { + return Verbose(verboseEnabled(depth+1, level)) +} - // It's off globally but it vmodule may still be set. - // Here is another cheap but safe test to see if vmodule is enabled. - if atomic.LoadInt32(&logging.filterLength) > 0 { - // Now we need a proper lock to use the logging structure. The pcs field - // is shared so we must lock before accessing it. This is fairly expensive, - // but if V logging is enabled we're slow anyway. - logging.mu.Lock() - defer logging.mu.Unlock() - if runtime.Callers(2, logging.pcs[:]) == 0 { - return Verbose(false) - } - v, ok := logging.vmap[logging.pcs[0]] - if !ok { - v = logging.setV(logging.pcs[0]) - } - return Verbose(v >= level) +// Info is equivalent to the global Info function, guarded by the value of v. +// See the documentation of V for usage. +func (v Verbose) Info(args ...any) { + v.InfoDepth(1, args...) +} + +// InfoDepth is equivalent to the global InfoDepth function, guarded by the value of v. +// See the documentation of V for usage. +func (v Verbose) InfoDepth(depth int, args ...any) { + if v { + logf(depth+1, logsink.Info, true, noStack, defaultFormat(args), args...) } - return Verbose(false) } -// Info is equivalent to the global Info function, guarded by the value of v. +// InfoDepthf is equivalent to the global InfoDepthf function, guarded by the value of v. // See the documentation of V for usage. -func (v Verbose) Info(args ...interface{}) { +func (v Verbose) InfoDepthf(depth int, format string, args ...any) { if v { - logging.print(infoLog, args...) + logf(depth+1, logsink.Info, true, noStack, format, args...) } } // Infoln is equivalent to the global Infoln function, guarded by the value of v. // See the documentation of V for usage. -func (v Verbose) Infoln(args ...interface{}) { +func (v Verbose) Infoln(args ...any) { if v { - logging.println(infoLog, args...) + logf(1, logsink.Info, true, noStack, lnFormat(args), args...) } } // Infof is equivalent to the global Infof function, guarded by the value of v. // See the documentation of V for usage. -func (v Verbose) Infof(format string, args ...interface{}) { +func (v Verbose) Infof(format string, args ...any) { if v { - logging.printf(infoLog, format, args...) + logf(1, logsink.Info, true, noStack, format, args...) } } // Info logs to the INFO log. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Info(args ...interface{}) { - logging.print(infoLog, args...) +func Info(args ...any) { + InfoDepth(1, args...) +} + +// InfoDepth calls Info from a different depth in the call stack. +// This enables a callee to emit logs that use the callsite information of its caller +// or any other callers in the stack. When depth == 0, the original callee's line +// information is emitted. When depth > 0, depth frames are skipped in the call stack +// and the final frame is treated like the original callee to Info. +func InfoDepth(depth int, args ...any) { + logf(depth+1, logsink.Info, false, noStack, defaultFormat(args), args...) } -// InfoDepth acts as Info but uses depth to determine which call frame to log. -// InfoDepth(0, "msg") is the same as Info("msg"). -func InfoDepth(depth int, args ...interface{}) { - logging.printDepth(infoLog, depth, args...) +// InfoDepthf acts as InfoDepth but with format string. +func InfoDepthf(depth int, format string, args ...any) { + logf(depth+1, logsink.Info, false, noStack, format, args...) } // Infoln logs to the INFO log. // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. -func Infoln(args ...interface{}) { - logging.println(infoLog, args...) +func Infoln(args ...any) { + logf(1, logsink.Info, false, noStack, lnFormat(args), args...) } // Infof logs to the INFO log. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Infof(format string, args ...interface{}) { - logging.printf(infoLog, format, args...) +func Infof(format string, args ...any) { + logf(1, logsink.Info, false, noStack, format, args...) } // Warning logs to the WARNING and INFO logs. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Warning(args ...interface{}) { - logging.print(warningLog, args...) +func Warning(args ...any) { + WarningDepth(1, args...) } // WarningDepth acts as Warning but uses depth to determine which call frame to log. // WarningDepth(0, "msg") is the same as Warning("msg"). -func WarningDepth(depth int, args ...interface{}) { - logging.printDepth(warningLog, depth, args...) +func WarningDepth(depth int, args ...any) { + logf(depth+1, logsink.Warning, false, noStack, defaultFormat(args), args...) +} + +// WarningDepthf acts as Warningf but uses depth to determine which call frame to log. +// WarningDepthf(0, "msg") is the same as Warningf("msg"). +func WarningDepthf(depth int, format string, args ...any) { + logf(depth+1, logsink.Warning, false, noStack, format, args...) } // Warningln logs to the WARNING and INFO logs. // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. -func Warningln(args ...interface{}) { - logging.println(warningLog, args...) +func Warningln(args ...any) { + logf(1, logsink.Warning, false, noStack, lnFormat(args), args...) } // Warningf logs to the WARNING and INFO logs. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Warningf(format string, args ...interface{}) { - logging.printf(warningLog, format, args...) +func Warningf(format string, args ...any) { + logf(1, logsink.Warning, false, noStack, format, args...) } // Error logs to the ERROR, WARNING, and INFO logs. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Error(args ...interface{}) { - logging.print(errorLog, args...) +func Error(args ...any) { + ErrorDepth(1, args...) } // ErrorDepth acts as Error but uses depth to determine which call frame to log. // ErrorDepth(0, "msg") is the same as Error("msg"). -func ErrorDepth(depth int, args ...interface{}) { - logging.printDepth(errorLog, depth, args...) +func ErrorDepth(depth int, args ...any) { + logf(depth+1, logsink.Error, false, noStack, defaultFormat(args), args...) +} + +// ErrorDepthf acts as Errorf but uses depth to determine which call frame to log. +// ErrorDepthf(0, "msg") is the same as Errorf("msg"). +func ErrorDepthf(depth int, format string, args ...any) { + logf(depth+1, logsink.Error, false, noStack, format, args...) } // Errorln logs to the ERROR, WARNING, and INFO logs. // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. -func Errorln(args ...interface{}) { - logging.println(errorLog, args...) +func Errorln(args ...any) { + logf(1, logsink.Error, false, noStack, lnFormat(args), args...) } // Errorf logs to the ERROR, WARNING, and INFO logs. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Errorf(format string, args ...interface{}) { - logging.printf(errorLog, format, args...) +func Errorf(format string, args ...any) { + logf(1, logsink.Error, false, noStack, format, args...) +} + +func fatalf(depth int, format string, args ...any) { + logf(depth+1, logsink.Fatal, false, withStack, format, args...) + sinks.file.Flush() + + err := abortProcess() // Should not return. + + // Failed to abort the process using signals. Dump a stack trace and exit. + Errorf("abortProcess returned unexpectedly: %v", err) + sinks.file.Flush() + pprof.Lookup("goroutine").WriteTo(os.Stderr, 1) + os.Exit(2) // Exit with the same code as the default SIGABRT handler. +} + +// abortProcess attempts to kill the current process in a way that will dump the +// currently-running goroutines someplace useful (Coroner or stderr). +// +// It does this by sending SIGABRT to the current process. Unfortunately, the +// signal may or may not be delivered to the current thread; in order to do that +// portably, we would need to add a cgo dependency and call pthread_kill. +// +// If successful, abortProcess does not return. +func abortProcess() error { + p, err := os.FindProcess(os.Getpid()) + if err != nil { + return err + } + if err := p.Signal(syscall.SIGABRT); err != nil { + return err + } + + // Sent the signal. Now we wait for it to arrive and any SIGABRT handlers to + // run (and eventually terminate the process themselves). + // + // We could just "select{}" here, but there's an outside chance that would + // trigger the runtime's deadlock detector if there happen not to be any + // background goroutines running. So we'll sleep a while first to give + // the signal some time. + time.Sleep(10 * time.Second) + select {} } // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). +// including a stack trace of all running goroutines, then calls os.Exit(2). // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Fatal(args ...interface{}) { - logging.print(fatalLog, args...) +func Fatal(args ...any) { + FatalDepth(1, args...) } // FatalDepth acts as Fatal but uses depth to determine which call frame to log. // FatalDepth(0, "msg") is the same as Fatal("msg"). -func FatalDepth(depth int, args ...interface{}) { - logging.printDepth(fatalLog, depth, args...) +func FatalDepth(depth int, args ...any) { + fatalf(depth+1, defaultFormat(args), args...) +} + +// FatalDepthf acts as Fatalf but uses depth to determine which call frame to log. +// FatalDepthf(0, "msg") is the same as Fatalf("msg"). +func FatalDepthf(depth int, format string, args ...any) { + fatalf(depth+1, format, args...) } // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). +// including a stack trace of all running goroutines, then calls os.Exit(2). // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. -func Fatalln(args ...interface{}) { - logging.println(fatalLog, args...) +func Fatalln(args ...any) { + fatalf(1, lnFormat(args), args...) } // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, -// including a stack trace of all running goroutines, then calls os.Exit(255). +// including a stack trace of all running goroutines, then calls os.Exit(2). // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Fatalf(format string, args ...interface{}) { - logging.printf(fatalLog, format, args...) +func Fatalf(format string, args ...any) { + fatalf(1, format, args...) } -// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. -// It allows Exit and relatives to use the Fatal logs. -var fatalNoStacks uint32 +func exitf(depth int, format string, args ...any) { + logf(depth+1, logsink.Fatal, false, noStack, format, args...) + sinks.file.Flush() + os.Exit(1) +} // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. -func Exit(args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.print(fatalLog, args...) +func Exit(args ...any) { + ExitDepth(1, args...) } // ExitDepth acts as Exit but uses depth to determine which call frame to log. // ExitDepth(0, "msg") is the same as Exit("msg"). -func ExitDepth(depth int, args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.printDepth(fatalLog, depth, args...) +func ExitDepth(depth int, args ...any) { + exitf(depth+1, defaultFormat(args), args...) +} + +// ExitDepthf acts as Exitf but uses depth to determine which call frame to log. +// ExitDepthf(0, "msg") is the same as Exitf("msg"). +func ExitDepthf(depth int, format string, args ...any) { + exitf(depth+1, format, args...) } // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). -func Exitln(args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.println(fatalLog, args...) +func Exitln(args ...any) { + exitf(1, lnFormat(args), args...) } // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. -func Exitf(format string, args ...interface{}) { - atomic.StoreUint32(&fatalNoStacks, 1) - logging.printf(fatalLog, format, args...) +func Exitf(format string, args ...any) { + exitf(1, format, args...) } diff --git a/vendor/github.com/golang/glog/glog_file.go b/vendor/github.com/golang/glog/glog_file.go index 65075d281..af1c934b8 100644 --- a/vendor/github.com/golang/glog/glog_file.go +++ b/vendor/github.com/golang/glog/glog_file.go @@ -1,6 +1,6 @@ -// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ +// Go support for leveled logs, analogous to https://github.com/google/glog. // -// Copyright 2013 Google Inc. All Rights Reserved. +// Copyright 2023 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,26 +19,34 @@ package glog import ( + "bufio" + "bytes" "errors" "flag" "fmt" + "io" "os" "os/user" "path/filepath" + "runtime" "strings" "sync" "time" -) -// MaxSize is the maximum size of a log file in bytes. -var MaxSize uint64 = 1024 * 1024 * 1800 + "github.com/golang/glog/internal/logsink" +) // logDirs lists the candidate directories for new log files. var logDirs []string -// If non-empty, overrides the choice of directory in which to write logs. -// See createLogDirs for the full list of possible destinations. -var logDir = flag.String("log_dir", "", "If non-empty, write log files in this directory") +var ( + // If non-empty, overrides the choice of directory in which to write logs. + // See createLogDirs for the full list of possible destinations. + logDir = flag.String("log_dir", "", "If non-empty, write log files in this directory") + logLink = flag.String("log_link", "", "If non-empty, add symbolic links in this directory to the log files") + logBufLevel = flag.Int("logbuflevel", int(logsink.Info), "Buffer log messages logged at this level or lower"+ + " (-1 means don't buffer; 0 means buffer INFO only; ...). Has limited applicability on non-prod platforms.") +) func createLogDirs() { if *logDir != "" { @@ -64,9 +72,17 @@ func init() { if err == nil { userName = current.Username } - - // Sanitize userName since it may contain filepath separators on Windows. - userName = strings.Replace(userName, `\`, "_", -1) + // Sanitize userName since it is used to construct file paths. + userName = strings.Map(func(r rune) rune { + switch { + case r >= 'a' && r <= 'z': + case r >= 'A' && r <= 'Z': + case r >= '0' && r <= '9': + default: + return '_' + } + return r + }, userName) } // shortHostname returns its argument, truncating at the first period. @@ -122,3 +138,270 @@ func create(tag string, t time.Time) (f *os.File, filename string, err error) { } return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr) } + +// flushSyncWriter is the interface satisfied by logging destinations. +type flushSyncWriter interface { + Flush() error + Sync() error + io.Writer + filenames() []string +} + +var sinks struct { + stderr stderrSink + file fileSink +} + +func init() { + sinks.stderr.w = os.Stderr + + // Register stderr first: that way if we crash during file-writing at least + // the log will have gone somewhere. + logsink.TextSinks = append(logsink.TextSinks, &sinks.stderr, &sinks.file) + + sinks.file.flushChan = make(chan logsink.Severity, 1) + go sinks.file.flushDaemon() +} + +// stderrSink is a logsink.Text that writes log entries to stderr +// if they meet certain conditions. +type stderrSink struct { + mu sync.Mutex + w io.Writer +} + +// Enabled implements logsink.Text.Enabled. It returns true if any of the +// various stderr flags are enabled for logs of the given severity, if the log +// message is from the standard "log" package, or if google.Init has not yet run +// (and hence file logging is not yet initialized). +func (s *stderrSink) Enabled(m *logsink.Meta) bool { + return toStderr || alsoToStderr || m.Severity >= stderrThreshold.get() +} + +// Emit implements logsink.Text.Emit. +func (s *stderrSink) Emit(m *logsink.Meta, data []byte) (n int, err error) { + s.mu.Lock() + defer s.mu.Unlock() + + dn, err := s.w.Write(data) + n += dn + return n, err +} + +// severityWriters is an array of flushSyncWriter with a value for each +// logsink.Severity. +type severityWriters [4]flushSyncWriter + +// fileSink is a logsink.Text that prints to a set of Google log files. +type fileSink struct { + mu sync.Mutex + // file holds writer for each of the log types. + file severityWriters + flushChan chan logsink.Severity +} + +// Enabled implements logsink.Text.Enabled. It returns true if google.Init +// has run and both --disable_log_to_disk and --logtostderr are false. +func (s *fileSink) Enabled(m *logsink.Meta) bool { + return !toStderr +} + +// Emit implements logsink.Text.Emit +func (s *fileSink) Emit(m *logsink.Meta, data []byte) (n int, err error) { + s.mu.Lock() + defer s.mu.Unlock() + + if err = s.createMissingFiles(m.Severity); err != nil { + return 0, err + } + for sev := m.Severity; sev >= logsink.Info; sev-- { + if _, fErr := s.file[sev].Write(data); fErr != nil && err == nil { + err = fErr // Take the first error. + } + } + n = len(data) + if int(m.Severity) > *logBufLevel { + select { + case s.flushChan <- m.Severity: + default: + } + } + + return n, err +} + +// syncBuffer joins a bufio.Writer to its underlying file, providing access to the +// file's Sync method and providing a wrapper for the Write method that provides log +// file rotation. There are conflicting methods, so the file cannot be embedded. +// s.mu is held for all its methods. +type syncBuffer struct { + sink *fileSink + *bufio.Writer + file *os.File + names []string + sev logsink.Severity + nbytes uint64 // The number of bytes written to this file +} + +func (sb *syncBuffer) Sync() error { + return sb.file.Sync() +} + +func (sb *syncBuffer) Write(p []byte) (n int, err error) { + if sb.nbytes+uint64(len(p)) >= MaxSize { + if err := sb.rotateFile(time.Now()); err != nil { + return 0, err + } + } + n, err = sb.Writer.Write(p) + sb.nbytes += uint64(n) + return n, err +} + +func (sb *syncBuffer) filenames() []string { + return sb.names +} + +const footer = "\nCONTINUED IN NEXT FILE\n" + +// rotateFile closes the syncBuffer's file and starts a new one. +func (sb *syncBuffer) rotateFile(now time.Time) error { + var err error + pn := "" + file, name, err := create(sb.sev.String(), now) + + if sb.file != nil { + // The current log file becomes the previous log at the end of + // this block, so save its name for use in the header of the next + // file. + pn = sb.file.Name() + sb.Flush() + // If there's an existing file, write a footer with the name of + // the next file in the chain, followed by the constant string + // \nCONTINUED IN NEXT FILE\n to make continuation detection simple. + sb.file.Write([]byte("Next log: ")) + sb.file.Write([]byte(name)) + sb.file.Write([]byte(footer)) + sb.file.Close() + } + + sb.file = file + sb.names = append(sb.names, name) + sb.nbytes = 0 + if err != nil { + return err + } + + sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) + + // Write header. + var buf bytes.Buffer + fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) + fmt.Fprintf(&buf, "Running on machine: %s\n", host) + fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) + fmt.Fprintf(&buf, "Previous log: %s\n", pn) + fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") + n, err := sb.file.Write(buf.Bytes()) + sb.nbytes += uint64(n) + return err +} + +// bufferSize sizes the buffer associated with each log file. It's large +// so that log records can accumulate without the logging thread blocking +// on disk I/O. The flushDaemon will block instead. +const bufferSize = 256 * 1024 + +// createMissingFiles creates all the log files for severity from infoLog up to +// upTo that have not already been created. +// s.mu is held. +func (s *fileSink) createMissingFiles(upTo logsink.Severity) error { + if s.file[upTo] != nil { + return nil + } + now := time.Now() + // Files are created in increasing severity order, so we can be assured that + // if a high severity logfile exists, then so do all of lower severity. + for sev := logsink.Info; sev <= upTo; sev++ { + if s.file[sev] != nil { + continue + } + sb := &syncBuffer{ + sink: s, + sev: sev, + } + if err := sb.rotateFile(now); err != nil { + return err + } + s.file[sev] = sb + } + return nil +} + +// flushDaemon periodically flushes the log file buffers. +func (s *fileSink) flushDaemon() { + tick := time.NewTicker(30 * time.Second) + defer tick.Stop() + for { + select { + case <-tick.C: + s.Flush() + case sev := <-s.flushChan: + s.flush(sev) + } + } +} + +// Flush flushes all pending log I/O. +func Flush() { + sinks.file.Flush() +} + +// Flush flushes all the logs and attempts to "sync" their data to disk. +func (s *fileSink) Flush() error { + return s.flush(logsink.Info) +} + +// flush flushes all logs of severity threshold or greater. +func (s *fileSink) flush(threshold logsink.Severity) error { + s.mu.Lock() + defer s.mu.Unlock() + + var firstErr error + updateErr := func(err error) { + if err != nil && firstErr == nil { + firstErr = err + } + } + + // Flush from fatal down, in case there's trouble flushing. + for sev := logsink.Fatal; sev >= threshold; sev-- { + file := s.file[sev] + if file != nil { + updateErr(file.Flush()) + updateErr(file.Sync()) + } + } + + return firstErr +} + +// Names returns the names of the log files holding the FATAL, ERROR, +// WARNING, or INFO logs. Returns ErrNoLog if the log for the given +// level doesn't exist (e.g. because no messages of that level have been +// written). This may return multiple names if the log type requested +// has rolled over. +func Names(s string) ([]string, error) { + severity, err := logsink.ParseSeverity(s) + if err != nil { + return nil, err + } + + sinks.file.mu.Lock() + defer sinks.file.mu.Unlock() + f := sinks.file.file[severity] + if f == nil { + return nil, ErrNoLog + } + + return f.filenames(), nil +} diff --git a/vendor/github.com/golang/glog/glog_flags.go b/vendor/github.com/golang/glog/glog_flags.go new file mode 100644 index 000000000..3060e54d9 --- /dev/null +++ b/vendor/github.com/golang/glog/glog_flags.go @@ -0,0 +1,395 @@ +// Go support for leveled logs, analogous to https://github.com/google/glog. +// +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package glog + +import ( + "bytes" + "errors" + "flag" + "fmt" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" + + "github.com/golang/glog/internal/logsink" +) + +// modulePat contains a filter for the -vmodule flag. +// It holds a verbosity level and a file pattern to match. +type modulePat struct { + pattern string + literal bool // The pattern is a literal string + full bool // The pattern wants to match the full path + level Level +} + +// match reports whether the file matches the pattern. It uses a string +// comparison if the pattern contains no metacharacters. +func (m *modulePat) match(full, file string) bool { + if m.literal { + if m.full { + return full == m.pattern + } + return file == m.pattern + } + if m.full { + match, _ := filepath.Match(m.pattern, full) + return match + } + match, _ := filepath.Match(m.pattern, file) + return match +} + +// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters +// that require filepath.Match to be called to match the pattern. +func isLiteral(pattern string) bool { + return !strings.ContainsAny(pattern, `\*?[]`) +} + +// isFull reports whether the pattern matches the full file path, that is, +// whether it contains /. +func isFull(pattern string) bool { + return strings.ContainsRune(pattern, '/') +} + +// verboseFlags represents the setting of the -v and -vmodule flags. +type verboseFlags struct { + // moduleLevelCache is a sync.Map storing the -vmodule Level for each V() + // call site, identified by PC. If there is no matching -vmodule filter, + // the cached value is exactly v. moduleLevelCache is replaced with a new + // Map whenever the -vmodule or -v flag changes state. + moduleLevelCache atomic.Value + + // mu guards all fields below. + mu sync.Mutex + + // v stores the value of the -v flag. It may be read safely using + // sync.LoadInt32, but is only modified under mu. + v Level + + // module stores the parsed -vmodule flag. + module []modulePat + + // moduleLength caches len(module). If greater than zero, it + // means vmodule is enabled. It may be read safely using sync.LoadInt32, but + // is only modified under mu. + moduleLength int32 +} + +// NOTE: For compatibility with the open-sourced v1 version of this +// package (github.com/golang/glog) we need to retain that flag.Level +// implements the flag.Value interface. See also go/log-vs-glog. + +// String is part of the flag.Value interface. +func (l *Level) String() string { + return strconv.FormatInt(int64(l.Get().(Level)), 10) +} + +// Get is part of the flag.Value interface. +func (l *Level) Get() any { + if l == &vflags.v { + // l is the value registered for the -v flag. + return Level(atomic.LoadInt32((*int32)(l))) + } + return *l +} + +// Set is part of the flag.Value interface. +func (l *Level) Set(value string) error { + v, err := strconv.Atoi(value) + if err != nil { + return err + } + if l == &vflags.v { + // l is the value registered for the -v flag. + vflags.mu.Lock() + defer vflags.mu.Unlock() + vflags.moduleLevelCache.Store(&sync.Map{}) + atomic.StoreInt32((*int32)(l), int32(v)) + return nil + } + *l = Level(v) + return nil +} + +// vModuleFlag is the flag.Value for the --vmodule flag. +type vModuleFlag struct{ *verboseFlags } + +func (f vModuleFlag) String() string { + f.mu.Lock() + defer f.mu.Unlock() + + var b bytes.Buffer + for i, f := range f.module { + if i > 0 { + b.WriteRune(',') + } + fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) + } + return b.String() +} + +// Get returns nil for this flag type since the struct is not exported. +func (f vModuleFlag) Get() any { return nil } + +var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") + +// Syntax: -vmodule=recordio=2,foo/bar/baz=1,gfs*=3 +func (f vModuleFlag) Set(value string) error { + var filter []modulePat + for _, pat := range strings.Split(value, ",") { + if len(pat) == 0 { + // Empty strings such as from a trailing comma can be ignored. + continue + } + patLev := strings.Split(pat, "=") + if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { + return errVmoduleSyntax + } + pattern := patLev[0] + v, err := strconv.Atoi(patLev[1]) + if err != nil { + return errors.New("syntax error: expect comma-separated list of filename=N") + } + // TODO: check syntax of filter? + filter = append(filter, modulePat{pattern, isLiteral(pattern), isFull(pattern), Level(v)}) + } + + f.mu.Lock() + defer f.mu.Unlock() + f.module = filter + atomic.StoreInt32((*int32)(&f.moduleLength), int32(len(f.module))) + f.moduleLevelCache.Store(&sync.Map{}) + return nil +} + +func (f *verboseFlags) levelForPC(pc uintptr) Level { + if level, ok := f.moduleLevelCache.Load().(*sync.Map).Load(pc); ok { + return level.(Level) + } + + f.mu.Lock() + defer f.mu.Unlock() + level := Level(f.v) + fn := runtime.FuncForPC(pc) + file, _ := fn.FileLine(pc) + // The file is something like /a/b/c/d.go. We want just the d for + // regular matches, /a/b/c/d for full matches. + if strings.HasSuffix(file, ".go") { + file = file[:len(file)-3] + } + full := file + if slash := strings.LastIndex(file, "/"); slash >= 0 { + file = file[slash+1:] + } + for _, filter := range f.module { + if filter.match(full, file) { + level = filter.level + break // Use the first matching level. + } + } + f.moduleLevelCache.Load().(*sync.Map).Store(pc, level) + return level +} + +func (f *verboseFlags) enabled(callerDepth int, level Level) bool { + if atomic.LoadInt32(&f.moduleLength) == 0 { + // No vmodule values specified, so compare against v level. + return Level(atomic.LoadInt32((*int32)(&f.v))) >= level + } + + pcs := [1]uintptr{} + if runtime.Callers(callerDepth+2, pcs[:]) < 1 { + return false + } + frame, _ := runtime.CallersFrames(pcs[:]).Next() + return f.levelForPC(frame.Entry) >= level +} + +// traceLocation represents an entry in the -log_backtrace_at flag. +type traceLocation struct { + file string + line int +} + +var errTraceSyntax = errors.New("syntax error: expect file.go:234") + +func parseTraceLocation(value string) (traceLocation, error) { + fields := strings.Split(value, ":") + if len(fields) != 2 { + return traceLocation{}, errTraceSyntax + } + file, lineStr := fields[0], fields[1] + if !strings.Contains(file, ".") { + return traceLocation{}, errTraceSyntax + } + line, err := strconv.Atoi(lineStr) + if err != nil { + return traceLocation{}, errTraceSyntax + } + if line < 0 { + return traceLocation{}, errors.New("negative value for line") + } + return traceLocation{file, line}, nil +} + +// match reports whether the specified file and line matches the trace location. +// The argument file name is the full path, not the basename specified in the flag. +func (t traceLocation) match(file string, line int) bool { + if t.line != line { + return false + } + if i := strings.LastIndex(file, "/"); i >= 0 { + file = file[i+1:] + } + return t.file == file +} + +func (t traceLocation) String() string { + return fmt.Sprintf("%s:%d", t.file, t.line) +} + +// traceLocations represents the -log_backtrace_at flag. +// Syntax: -log_backtrace_at=recordio.go:234,sstable.go:456 +// Note that unlike vmodule the file extension is included here. +type traceLocations struct { + mu sync.Mutex + locsLen int32 // Safe for atomic read without mu. + locs []traceLocation +} + +func (t *traceLocations) String() string { + t.mu.Lock() + defer t.mu.Unlock() + + var buf bytes.Buffer + for i, tl := range t.locs { + if i > 0 { + buf.WriteString(",") + } + buf.WriteString(tl.String()) + } + return buf.String() +} + +// Get always returns nil for this flag type since the struct is not exported +func (t *traceLocations) Get() any { return nil } + +func (t *traceLocations) Set(value string) error { + var locs []traceLocation + for _, s := range strings.Split(value, ",") { + if s == "" { + continue + } + loc, err := parseTraceLocation(s) + if err != nil { + return err + } + locs = append(locs, loc) + } + + t.mu.Lock() + defer t.mu.Unlock() + atomic.StoreInt32(&t.locsLen, int32(len(locs))) + t.locs = locs + return nil +} + +func (t *traceLocations) match(file string, line int) bool { + if atomic.LoadInt32(&t.locsLen) == 0 { + return false + } + + t.mu.Lock() + defer t.mu.Unlock() + for _, tl := range t.locs { + if tl.match(file, line) { + return true + } + } + return false +} + +// severityFlag is an atomic flag.Value implementation for logsink.Severity. +type severityFlag int32 + +func (s *severityFlag) get() logsink.Severity { + return logsink.Severity(atomic.LoadInt32((*int32)(s))) +} +func (s *severityFlag) String() string { return strconv.FormatInt(int64(*s), 10) } +func (s *severityFlag) Get() any { return s.get() } +func (s *severityFlag) Set(value string) error { + threshold, err := logsink.ParseSeverity(value) + if err != nil { + // Not a severity name. Try a raw number. + v, err := strconv.Atoi(value) + if err != nil { + return err + } + threshold = logsink.Severity(v) + if threshold < logsink.Info || threshold > logsink.Fatal { + return fmt.Errorf("Severity %d out of range (min %d, max %d).", v, logsink.Info, logsink.Fatal) + } + } + atomic.StoreInt32((*int32)(s), int32(threshold)) + return nil +} + +var ( + vflags verboseFlags // The -v and -vmodule flags. + + logBacktraceAt traceLocations // The -log_backtrace_at flag. + + // Boolean flags. Not handled atomically because the flag.Value interface + // does not let us avoid the =true, and that shorthand is necessary for + // compatibility. TODO: does this matter enough to fix? Seems unlikely. + toStderr bool // The -logtostderr flag. + alsoToStderr bool // The -alsologtostderr flag. + + stderrThreshold severityFlag // The -stderrthreshold flag. +) + +// verboseEnabled returns whether the caller at the given depth should emit +// verbose logs at the given level, with depth 0 identifying the caller of +// verboseEnabled. +func verboseEnabled(callerDepth int, level Level) bool { + return vflags.enabled(callerDepth+1, level) +} + +// backtraceAt returns whether the logging call at the given function and line +// should also emit a backtrace of the current call stack. +func backtraceAt(file string, line int) bool { + return logBacktraceAt.match(file, line) +} + +func init() { + vflags.moduleLevelCache.Store(&sync.Map{}) + + flag.Var(&vflags.v, "v", "log level for V logs") + flag.Var(vModuleFlag{&vflags}, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") + + flag.Var(&logBacktraceAt, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") + + stderrThreshold = severityFlag(logsink.Error) + + flag.BoolVar(&toStderr, "logtostderr", false, "log to standard error instead of files") + flag.BoolVar(&alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") + flag.Var(&stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") +} diff --git a/vendor/github.com/golang/glog/internal/logsink/logsink.go b/vendor/github.com/golang/glog/internal/logsink/logsink.go new file mode 100644 index 000000000..53758e1c9 --- /dev/null +++ b/vendor/github.com/golang/glog/internal/logsink/logsink.go @@ -0,0 +1,387 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package logsink + +import ( + "bytes" + "fmt" + "strconv" + "strings" + "sync" + "time" + + "github.com/golang/glog/internal/stackdump" +) + +// MaxLogMessageLen is the limit on length of a formatted log message, including +// the standard line prefix and trailing newline. +// +// Chosen to match C++ glog. +const MaxLogMessageLen = 15000 + +// A Severity is a severity at which a message can be logged. +type Severity int8 + +// These constants identify the log levels in order of increasing severity. +// A message written to a high-severity log file is also written to each +// lower-severity log file. +const ( + Info Severity = iota + Warning + Error + + // Fatal contains logs written immediately before the process terminates. + // + // Sink implementations should not terminate the process themselves: the log + // package will perform any necessary cleanup and terminate the process as + // appropriate. + Fatal +) + +func (s Severity) String() string { + switch s { + case Info: + return "INFO" + case Warning: + return "WARNING" + case Error: + return "ERROR" + case Fatal: + return "FATAL" + } + return fmt.Sprintf("%T(%d)", s, s) +} + +// ParseSeverity returns the case-insensitive Severity value for the given string. +func ParseSeverity(name string) (Severity, error) { + name = strings.ToUpper(name) + for s := Info; s <= Fatal; s++ { + if s.String() == name { + return s, nil + } + } + return -1, fmt.Errorf("logsink: invalid severity %q", name) +} + +// Meta is metadata about a logging call. +type Meta struct { + // Time is the time at which the log call was made. + Time time.Time + + // File is the source file from which the log entry originates. + File string + // Line is the line offset within the source file. + Line int + // Depth is the number of stack frames between the logsink and the log call. + Depth int + + Severity Severity + + // Verbose indicates whether the call was made via "log.V". Log entries below + // the current verbosity threshold are not sent to the sink. + Verbose bool + + // Thread ID. This can be populated with a thread ID from another source, + // such as a system we are importing logs from. In the normal case, this + // will be set to the process ID (PID), since Go doesn't have threads. + Thread int64 + + // Stack trace starting in the logging function. May be nil. + // A logsink should implement the StackWanter interface to request this. + // + // Even if WantStack returns false, this field may be set (e.g. if another + // sink wants a stack trace). + Stack *stackdump.Stack +} + +// Structured is a logging destination that accepts structured data as input. +type Structured interface { + // Printf formats according to a fmt.Printf format specifier and writes a log + // entry. The precise result of formatting depends on the sink, but should + // aim for consistency with fmt.Printf. + // + // Printf returns the number of bytes occupied by the log entry, which + // may not be equal to the total number of bytes written. + // + // Printf returns any error encountered *if* it is severe enough that the log + // package should terminate the process. + // + // The sink must not modify the *Meta parameter, nor reference it after + // Printf has returned: it may be reused in subsequent calls. + Printf(meta *Meta, format string, a ...any) (n int, err error) +} + +// StackWanter can be implemented by a logsink.Structured to indicate that it +// wants a stack trace to accompany at least some of the log messages it receives. +type StackWanter interface { + // WantStack returns true if the sink requires a stack trace for a log message + // with this metadata. + // + // NOTE: Returning true implies that meta.Stack will be non-nil. Returning + // false does NOT imply that meta.Stack will be nil. + WantStack(meta *Meta) bool +} + +// Text is a logging destination that accepts pre-formatted log lines (instead of +// structured data). +type Text interface { + // Enabled returns whether this sink should output messages for the given + // Meta. If the sink returns false for a given Meta, the Printf function will + // not call Emit on it for the corresponding log message. + Enabled(*Meta) bool + + // Emit writes a pre-formatted text log entry (including any applicable + // header) to the log. It returns the number of bytes occupied by the entry + // (which may differ from the length of the passed-in slice). + // + // Emit returns any error encountered *if* it is severe enough that the log + // package should terminate the process. + // + // The sink must not modify the *Meta parameter, nor reference it after + // Printf has returned: it may be reused in subsequent calls. + // + // NOTE: When developing a text sink, keep in mind the surface in which the + // logs will be displayed, and whether it's important that the sink be + // resistent to tampering in the style of b/211428300. Standard text sinks + // (like `stderrSink`) do not protect against this (e.g. by escaping + // characters) because the cases where they would show user-influenced bytes + // are vanishingly small. + Emit(*Meta, []byte) (n int, err error) +} + +// bufs is a pool of *bytes.Buffer used in formatting log entries. +var bufs sync.Pool // Pool of *bytes.Buffer. + +// textPrintf formats a text log entry and emits it to all specified Text sinks. +// +// The returned n is the maximum across all Emit calls. +// The returned err is the first non-nil error encountered. +// Sinks that are disabled by configuration should return (0, nil). +func textPrintf(m *Meta, textSinks []Text, format string, args ...any) (n int, err error) { + // We expect at most file, stderr, and perhaps syslog. If there are more, + // we'll end up allocating - no big deal. + const maxExpectedTextSinks = 3 + var noAllocSinks [maxExpectedTextSinks]Text + + sinks := noAllocSinks[:0] + for _, s := range textSinks { + if s.Enabled(m) { + sinks = append(sinks, s) + } + } + if len(sinks) == 0 && m.Severity != Fatal { + return 0, nil // No TextSinks specified; don't bother formatting. + } + + bufi := bufs.Get() + var buf *bytes.Buffer + if bufi == nil { + buf = bytes.NewBuffer(nil) + bufi = buf + } else { + buf = bufi.(*bytes.Buffer) + buf.Reset() + } + + // Lmmdd hh:mm:ss.uuuuuu PID/GID file:line] + // + // The "PID" entry arguably ought to be TID for consistency with other + // environments, but TID is not meaningful in a Go program due to the + // multiplexing of goroutines across threads. + // + // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. + // It's worth about 3X. Fprintf is hard. + const severityChar = "IWEF" + buf.WriteByte(severityChar[m.Severity]) + + _, month, day := m.Time.Date() + hour, minute, second := m.Time.Clock() + twoDigits(buf, int(month)) + twoDigits(buf, day) + buf.WriteByte(' ') + twoDigits(buf, hour) + buf.WriteByte(':') + twoDigits(buf, minute) + buf.WriteByte(':') + twoDigits(buf, second) + buf.WriteByte('.') + nDigits(buf, 6, uint64(m.Time.Nanosecond()/1000), '0') + buf.WriteByte(' ') + + nDigits(buf, 7, uint64(m.Thread), ' ') + buf.WriteByte(' ') + + { + file := m.File + if i := strings.LastIndex(file, "/"); i >= 0 { + file = file[i+1:] + } + buf.WriteString(file) + } + + buf.WriteByte(':') + { + var tmp [19]byte + buf.Write(strconv.AppendInt(tmp[:0], int64(m.Line), 10)) + } + buf.WriteString("] ") + + msgStart := buf.Len() + fmt.Fprintf(buf, format, args...) + if buf.Len() > MaxLogMessageLen-1 { + buf.Truncate(MaxLogMessageLen - 1) + } + msgEnd := buf.Len() + if b := buf.Bytes(); b[len(b)-1] != '\n' { + buf.WriteByte('\n') + } + + for _, s := range sinks { + sn, sErr := s.Emit(m, buf.Bytes()) + if sn > n { + n = sn + } + if sErr != nil && err == nil { + err = sErr + } + } + + if m.Severity == Fatal { + savedM := *m + fatalMessageStore(savedEntry{ + meta: &savedM, + msg: buf.Bytes()[msgStart:msgEnd], + }) + } else { + bufs.Put(bufi) + } + return n, err +} + +const digits = "0123456789" + +// twoDigits formats a zero-prefixed two-digit integer to buf. +func twoDigits(buf *bytes.Buffer, d int) { + buf.WriteByte(digits[(d/10)%10]) + buf.WriteByte(digits[d%10]) +} + +// nDigits formats an n-digit integer to buf, padding with pad on the left. It +// assumes d != 0. +func nDigits(buf *bytes.Buffer, n int, d uint64, pad byte) { + var tmp [20]byte + + cutoff := len(tmp) - n + j := len(tmp) - 1 + for ; d > 0; j-- { + tmp[j] = digits[d%10] + d /= 10 + } + for ; j >= cutoff; j-- { + tmp[j] = pad + } + j++ + buf.Write(tmp[j:]) +} + +// Printf writes a log entry to all registered TextSinks in this package, then +// to all registered StructuredSinks. +// +// The returned n is the maximum across all Emit and Printf calls. +// The returned err is the first non-nil error encountered. +// Sinks that are disabled by configuration should return (0, nil). +func Printf(m *Meta, format string, args ...any) (n int, err error) { + m.Depth++ + n, err = textPrintf(m, TextSinks, format, args...) + + for _, sink := range StructuredSinks { + // TODO: Support TextSinks that implement StackWanter? + if sw, ok := sink.(StackWanter); ok && sw.WantStack(m) { + if m.Stack == nil { + // First, try to find a stacktrace in args, otherwise generate one. + for _, arg := range args { + if stack, ok := arg.(stackdump.Stack); ok { + m.Stack = &stack + break + } + } + if m.Stack == nil { + stack := stackdump.Caller( /* skipDepth = */ m.Depth) + m.Stack = &stack + } + } + } + sn, sErr := sink.Printf(m, format, args...) + if sn > n { + n = sn + } + if sErr != nil && err == nil { + err = sErr + } + } + return n, err +} + +// The sets of sinks to which logs should be written. +// +// These must only be modified during package init, and are read-only thereafter. +var ( + // StructuredSinks is the set of Structured sink instances to which logs + // should be written. + StructuredSinks []Structured + + // TextSinks is the set of Text sink instances to which logs should be + // written. + // + // These are registered separately from Structured sink implementations to + // avoid the need to repeat the work of formatting a message for each Text + // sink that writes it. The package-level Printf function writes to both sets + // independenty, so a given log destination should only register a Structured + // *or* a Text sink (not both). + TextSinks []Text +) + +type savedEntry struct { + meta *Meta + msg []byte +} + +// StructuredTextWrapper is a Structured sink which forwards logs to a set of Text sinks. +// +// The purpose of this sink is to allow applications to intercept logging calls before they are +// serialized and sent to Text sinks. For example, if one needs to redact PII from logging +// arguments before they reach STDERR, one solution would be to do the redacting in a Structured +// sink that forwards logs to a StructuredTextWrapper instance, and make STDERR a child of that +// StructuredTextWrapper instance. This is how one could set this up in their application: +// +// func init() { +// +// wrapper := logsink.StructuredTextWrapper{TextSinks: logsink.TextSinks} +// // sanitizersink will intercept logs and remove PII +// sanitizer := sanitizersink{Sink: &wrapper} +// logsink.StructuredSinks = append(logsink.StructuredSinks, &sanitizer) +// logsink.TextSinks = nil +// +// } +type StructuredTextWrapper struct { + // TextSinks is the set of Text sinks that should receive logs from this + // StructuredTextWrapper instance. + TextSinks []Text +} + +// Printf forwards logs to all Text sinks registered in the StructuredTextWrapper. +func (w *StructuredTextWrapper) Printf(meta *Meta, format string, args ...any) (n int, err error) { + return textPrintf(meta, w.TextSinks, format, args...) +} diff --git a/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go b/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go new file mode 100644 index 000000000..3dc269abc --- /dev/null +++ b/vendor/github.com/golang/glog/internal/logsink/logsink_fatal.go @@ -0,0 +1,35 @@ +package logsink + +import ( + "sync/atomic" + "unsafe" +) + +func fatalMessageStore(e savedEntry) { + // Only put a new one in if we haven't assigned before. + atomic.CompareAndSwapPointer(&fatalMessage, nil, unsafe.Pointer(&e)) +} + +var fatalMessage unsafe.Pointer // savedEntry stored with CompareAndSwapPointer + +// FatalMessage returns the Meta and message contents of the first message +// logged with Fatal severity, or false if none has occurred. +func FatalMessage() (*Meta, []byte, bool) { + e := (*savedEntry)(atomic.LoadPointer(&fatalMessage)) + if e == nil { + return nil, nil, false + } + return e.meta, e.msg, true +} + +// DoNotUseRacyFatalMessage is FatalMessage, but worse. +// +//go:norace +//go:nosplit +func DoNotUseRacyFatalMessage() (*Meta, []byte, bool) { + e := (*savedEntry)(fatalMessage) + if e == nil { + return nil, nil, false + } + return e.meta, e.msg, true +} diff --git a/vendor/github.com/golang/glog/internal/stackdump/stackdump.go b/vendor/github.com/golang/glog/internal/stackdump/stackdump.go new file mode 100644 index 000000000..3427c9d6b --- /dev/null +++ b/vendor/github.com/golang/glog/internal/stackdump/stackdump.go @@ -0,0 +1,127 @@ +// Copyright 2023 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package stackdump provides wrappers for runtime.Stack and runtime.Callers +// with uniform support for skipping caller frames. +// +// ⚠ Unlike the functions in the runtime package, these may allocate a +// non-trivial quantity of memory: use them with care. ⚠ +package stackdump + +import ( + "bytes" + "runtime" +) + +// runtimeStackSelfFrames is 1 if runtime.Stack includes the call to +// runtime.Stack itself or 0 if it does not. +// +// As of 2016-04-27, the gccgo compiler includes runtime.Stack but the gc +// compiler does not. +var runtimeStackSelfFrames = func() int { + for n := 1 << 10; n < 1<<20; n *= 2 { + buf := make([]byte, n) + n := runtime.Stack(buf, false) + if bytes.Contains(buf[:n], []byte("runtime.Stack")) { + return 1 + } else if n < len(buf) || bytes.Count(buf, []byte("\n")) >= 3 { + return 0 + } + } + return 0 +}() + +// Stack is a stack dump for a single goroutine. +type Stack struct { + // Text is a representation of the stack dump in a human-readable format. + Text []byte + + // PC is a representation of the stack dump using raw program counter values. + PC []uintptr +} + +func (s Stack) String() string { return string(s.Text) } + +// Caller returns the Stack dump for the calling goroutine, starting skipDepth +// frames before the caller of Caller. (Caller(0) provides a dump starting at +// the caller of this function.) +func Caller(skipDepth int) Stack { + return Stack{ + Text: CallerText(skipDepth + 1), + PC: CallerPC(skipDepth + 1), + } +} + +// CallerText returns a textual dump of the stack starting skipDepth frames before +// the caller. (CallerText(0) provides a dump starting at the caller of this +// function.) +func CallerText(skipDepth int) []byte { + for n := 1 << 10; ; n *= 2 { + buf := make([]byte, n) + n := runtime.Stack(buf, false) + if n < len(buf) { + return pruneFrames(skipDepth+1+runtimeStackSelfFrames, buf[:n]) + } + } +} + +// CallerPC returns a dump of the program counters of the stack starting +// skipDepth frames before the caller. (CallerPC(0) provides a dump starting at +// the caller of this function.) +func CallerPC(skipDepth int) []uintptr { + for n := 1 << 8; ; n *= 2 { + buf := make([]uintptr, n) + n := runtime.Callers(skipDepth+2, buf) + if n < len(buf) { + return buf[:n] + } + } +} + +// pruneFrames removes the topmost skipDepth frames of the first goroutine in a +// textual stack dump. It overwrites the passed-in slice. +// +// If there are fewer than skipDepth frames in the first goroutine's stack, +// pruneFrames prunes it to an empty stack and leaves the remaining contents +// intact. +func pruneFrames(skipDepth int, stack []byte) []byte { + headerLen := 0 + for i, c := range stack { + if c == '\n' { + headerLen = i + 1 + break + } + } + if headerLen == 0 { + return stack // No header line - not a well-formed stack trace. + } + + skipLen := headerLen + skipNewlines := skipDepth * 2 + for ; skipLen < len(stack) && skipNewlines > 0; skipLen++ { + c := stack[skipLen] + if c != '\n' { + continue + } + skipNewlines-- + skipLen++ + if skipNewlines == 0 || skipLen == len(stack) || stack[skipLen] == '\n' { + break + } + } + + pruned := stack[skipLen-headerLen:] + copy(pruned, stack[:headerLen]) + return pruned +} diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md index 8e001134d..608aa6e1a 100644 --- a/vendor/google.golang.org/grpc/CONTRIBUTING.md +++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md @@ -20,10 +20,6 @@ How to get your contributions merged smoothly and quickly. both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy. -- For speculative changes, consider opening an issue and discussing it first. If - you are suggesting a behavioral or API change, consider starting with a [gRFC - proposal](https://github.com/grpc/proposal). - - If you are searching for features to work on, issues labeled [Status: Help Wanted](https://github.com/grpc/grpc-go/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Status%3A+Help+Wanted%22) is a great place to start. These issues are well-documented and usually can be diff --git a/vendor/google.golang.org/grpc/attributes/attributes.go b/vendor/google.golang.org/grpc/attributes/attributes.go index 02f5dc531..3efca4591 100644 --- a/vendor/google.golang.org/grpc/attributes/attributes.go +++ b/vendor/google.golang.org/grpc/attributes/attributes.go @@ -25,6 +25,11 @@ // later release. package attributes +import ( + "fmt" + "strings" +) + // Attributes is an immutable struct for storing and retrieving generic // key/value pairs. Keys must be hashable, and users should define their own // types for keys. Values should not be modified after they are added to an @@ -99,3 +104,27 @@ func (a *Attributes) Equal(o *Attributes) bool { } return true } + +// String prints the attribute map. If any key or values throughout the map +// implement fmt.Stringer, it calls that method and appends. +func (a *Attributes) String() string { + var sb strings.Builder + sb.WriteString("{") + first := true + for k, v := range a.m { + var key, val string + if str, ok := k.(interface{ String() string }); ok { + key = str.String() + } + if str, ok := v.(interface{ String() string }); ok { + val = str.String() + } + if !first { + sb.WriteString(", ") + } + sb.WriteString(fmt.Sprintf("%q: %q, ", key, val)) + first = false + } + sb.WriteString("}") + return sb.String() +} diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go index 09d61dd1b..8f00523c0 100644 --- a/vendor/google.golang.org/grpc/balancer/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/balancer.go @@ -286,7 +286,7 @@ type PickResult struct { // // LB policies with child policies are responsible for propagating metadata // injected by their children to the ClientConn, as part of Pick(). - Metatada metadata.MD + Metadata metadata.MD } // TransientFailureError returns e. It exists for backward compatibility and diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go index 0359956d3..04b9ad411 100644 --- a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go +++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go @@ -25,14 +25,20 @@ import ( "sync" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/balancer/gracefulswitch" - "google.golang.org/grpc/internal/buffer" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/resolver" - "google.golang.org/grpc/status" +) + +type ccbMode int + +const ( + ccbModeActive = iota + ccbModeIdle + ccbModeClosed + ccbModeExitingIdle ) // ccBalancerWrapper sits between the ClientConn and the Balancer. @@ -49,192 +55,101 @@ import ( // It uses the gracefulswitch.Balancer internally to ensure that balancer // switches happen in a graceful manner. type ccBalancerWrapper struct { - cc *ClientConn - - // Since these fields are accessed only from handleXxx() methods which are - // synchronized by the watcher goroutine, we do not need a mutex to protect - // these fields. + // The following fields are initialized when the wrapper is created and are + // read-only afterwards, and therefore can be accessed without a mutex. + cc *ClientConn + opts balancer.BuildOptions + + // Outgoing (gRPC --> balancer) calls are guaranteed to execute in a + // mutually exclusive manner as they are scheduled in the serializer. Fields + // accessed *only* in these serializer callbacks, can therefore be accessed + // without a mutex. balancer *gracefulswitch.Balancer curBalancerName string - updateCh *buffer.Unbounded // Updates written on this channel are processed by watcher(). - resultCh *buffer.Unbounded // Results of calls to UpdateClientConnState() are pushed here. - closed *grpcsync.Event // Indicates if close has been called. - done *grpcsync.Event // Indicates if close has completed its work. + // mu guards access to the below fields. Access to the serializer and its + // cancel function needs to be mutex protected because they are overwritten + // when the wrapper exits idle mode. + mu sync.Mutex + serializer *grpcsync.CallbackSerializer // To serialize all outoing calls. + serializerCancel context.CancelFunc // To close the seralizer at close/enterIdle time. + mode ccbMode // Tracks the current mode of the wrapper. } // newCCBalancerWrapper creates a new balancer wrapper. The underlying balancer // is not created until the switchTo() method is invoked. func newCCBalancerWrapper(cc *ClientConn, bopts balancer.BuildOptions) *ccBalancerWrapper { + ctx, cancel := context.WithCancel(context.Background()) ccb := &ccBalancerWrapper{ - cc: cc, - updateCh: buffer.NewUnbounded(), - resultCh: buffer.NewUnbounded(), - closed: grpcsync.NewEvent(), - done: grpcsync.NewEvent(), + cc: cc, + opts: bopts, + serializer: grpcsync.NewCallbackSerializer(ctx), + serializerCancel: cancel, } - go ccb.watcher() ccb.balancer = gracefulswitch.NewBalancer(ccb, bopts) return ccb } -// The following xxxUpdate structs wrap the arguments received as part of the -// corresponding update. The watcher goroutine uses the 'type' of the update to -// invoke the appropriate handler routine to handle the update. - -type ccStateUpdate struct { - ccs *balancer.ClientConnState -} - -type scStateUpdate struct { - sc balancer.SubConn - state connectivity.State - err error -} - -type exitIdleUpdate struct{} - -type resolverErrorUpdate struct { - err error -} - -type switchToUpdate struct { - name string -} - -type subConnUpdate struct { - acbw *acBalancerWrapper -} - -// watcher is a long-running goroutine which reads updates from a channel and -// invokes corresponding methods on the underlying balancer. It ensures that -// these methods are invoked in a synchronous fashion. It also ensures that -// these methods are invoked in the order in which the updates were received. -func (ccb *ccBalancerWrapper) watcher() { - for { - select { - case u := <-ccb.updateCh.Get(): - ccb.updateCh.Load() - if ccb.closed.HasFired() { - break - } - switch update := u.(type) { - case *ccStateUpdate: - ccb.handleClientConnStateChange(update.ccs) - case *scStateUpdate: - ccb.handleSubConnStateChange(update) - case *exitIdleUpdate: - ccb.handleExitIdle() - case *resolverErrorUpdate: - ccb.handleResolverError(update.err) - case *switchToUpdate: - ccb.handleSwitchTo(update.name) - case *subConnUpdate: - ccb.handleRemoveSubConn(update.acbw) - default: - logger.Errorf("ccBalancerWrapper.watcher: unknown update %+v, type %T", update, update) - } - case <-ccb.closed.Done(): - } - - if ccb.closed.HasFired() { - ccb.handleClose() - return - } - } -} - // updateClientConnState is invoked by grpc to push a ClientConnState update to // the underlying balancer. -// -// Unlike other methods invoked by grpc to push updates to the underlying -// balancer, this method cannot simply push the update onto the update channel -// and return. It needs to return the error returned by the underlying balancer -// back to grpc which propagates that to the resolver. func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error { - ccb.updateCh.Put(&ccStateUpdate{ccs: ccs}) - - var res interface{} - select { - case res = <-ccb.resultCh.Get(): - ccb.resultCh.Load() - case <-ccb.closed.Done(): - // Return early if the balancer wrapper is closed while we are waiting for - // the underlying balancer to process a ClientConnState update. - return nil - } - // If the returned error is nil, attempting to type assert to error leads to - // panic. So, this needs to handled separately. - if res == nil { - return nil - } - return res.(error) -} - -// handleClientConnStateChange handles a ClientConnState update from the update -// channel and invokes the appropriate method on the underlying balancer. -// -// If the addresses specified in the update contain addresses of type "grpclb" -// and the selected LB policy is not "grpclb", these addresses will be filtered -// out and ccs will be modified with the updated address list. -func (ccb *ccBalancerWrapper) handleClientConnStateChange(ccs *balancer.ClientConnState) { - if ccb.curBalancerName != grpclbName { - // Filter any grpclb addresses since we don't have the grpclb balancer. - var addrs []resolver.Address - for _, addr := range ccs.ResolverState.Addresses { - if addr.Type == resolver.GRPCLB { - continue + ccb.mu.Lock() + errCh := make(chan error, 1) + // Here and everywhere else where Schedule() is called, it is done with the + // lock held. But the lock guards only the scheduling part. The actual + // callback is called asynchronously without the lock being held. + ok := ccb.serializer.Schedule(func(_ context.Context) { + // If the addresses specified in the update contain addresses of type + // "grpclb" and the selected LB policy is not "grpclb", these addresses + // will be filtered out and ccs will be modified with the updated + // address list. + if ccb.curBalancerName != grpclbName { + var addrs []resolver.Address + for _, addr := range ccs.ResolverState.Addresses { + if addr.Type == resolver.GRPCLB { + continue + } + addrs = append(addrs, addr) } - addrs = append(addrs, addr) + ccs.ResolverState.Addresses = addrs } - ccs.ResolverState.Addresses = addrs + errCh <- ccb.balancer.UpdateClientConnState(*ccs) + }) + if !ok { + // If we are unable to schedule a function with the serializer, it + // indicates that it has been closed. A serializer is only closed when + // the wrapper is closed or is in idle. + ccb.mu.Unlock() + return fmt.Errorf("grpc: cannot send state update to a closed or idle balancer") } - ccb.resultCh.Put(ccb.balancer.UpdateClientConnState(*ccs)) + ccb.mu.Unlock() + + // We get here only if the above call to Schedule succeeds, in which case it + // is guaranteed that the scheduled function will run. Therefore it is safe + // to block on this channel. + err := <-errCh + if logger.V(2) && err != nil { + logger.Infof("error from balancer.UpdateClientConnState: %v", err) + } + return err } // updateSubConnState is invoked by grpc to push a subConn state update to the // underlying balancer. func (ccb *ccBalancerWrapper) updateSubConnState(sc balancer.SubConn, s connectivity.State, err error) { - // When updating addresses for a SubConn, if the address in use is not in - // the new addresses, the old ac will be tearDown() and a new ac will be - // created. tearDown() generates a state change with Shutdown state, we - // don't want the balancer to receive this state change. So before - // tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and - // this function will be called with (nil, Shutdown). We don't need to call - // balancer method in this case. - if sc == nil { - return - } - ccb.updateCh.Put(&scStateUpdate{ - sc: sc, - state: s, - err: err, + ccb.mu.Lock() + ccb.serializer.Schedule(func(_ context.Context) { + ccb.balancer.UpdateSubConnState(sc, balancer.SubConnState{ConnectivityState: s, ConnectionError: err}) }) -} - -// handleSubConnStateChange handles a SubConnState update from the update -// channel and invokes the appropriate method on the underlying balancer. -func (ccb *ccBalancerWrapper) handleSubConnStateChange(update *scStateUpdate) { - ccb.balancer.UpdateSubConnState(update.sc, balancer.SubConnState{ConnectivityState: update.state, ConnectionError: update.err}) -} - -func (ccb *ccBalancerWrapper) exitIdle() { - ccb.updateCh.Put(&exitIdleUpdate{}) -} - -func (ccb *ccBalancerWrapper) handleExitIdle() { - if ccb.cc.GetState() != connectivity.Idle { - return - } - ccb.balancer.ExitIdle() + ccb.mu.Unlock() } func (ccb *ccBalancerWrapper) resolverError(err error) { - ccb.updateCh.Put(&resolverErrorUpdate{err: err}) -} - -func (ccb *ccBalancerWrapper) handleResolverError(err error) { - ccb.balancer.ResolverError(err) + ccb.mu.Lock() + ccb.serializer.Schedule(func(_ context.Context) { + ccb.balancer.ResolverError(err) + }) + ccb.mu.Unlock() } // switchTo is invoked by grpc to instruct the balancer wrapper to switch to the @@ -248,24 +163,27 @@ func (ccb *ccBalancerWrapper) handleResolverError(err error) { // the ccBalancerWrapper keeps track of the current LB policy name, and skips // the graceful balancer switching process if the name does not change. func (ccb *ccBalancerWrapper) switchTo(name string) { - ccb.updateCh.Put(&switchToUpdate{name: name}) + ccb.mu.Lock() + ccb.serializer.Schedule(func(_ context.Context) { + // TODO: Other languages use case-sensitive balancer registries. We should + // switch as well. See: https://github.com/grpc/grpc-go/issues/5288. + if strings.EqualFold(ccb.curBalancerName, name) { + return + } + ccb.buildLoadBalancingPolicy(name) + }) + ccb.mu.Unlock() } -// handleSwitchTo handles a balancer switch update from the update channel. It -// calls the SwitchTo() method on the gracefulswitch.Balancer with a -// balancer.Builder corresponding to name. If no balancer.Builder is registered -// for the given name, it uses the default LB policy which is "pick_first". -func (ccb *ccBalancerWrapper) handleSwitchTo(name string) { - // TODO: Other languages use case-insensitive balancer registries. We should - // switch as well. See: https://github.com/grpc/grpc-go/issues/5288. - if strings.EqualFold(ccb.curBalancerName, name) { - return - } - - // TODO: Ensure that name is a registered LB policy when we get here. - // We currently only validate the `loadBalancingConfig` field. We need to do - // the same for the `loadBalancingPolicy` field and reject the service config - // if the specified policy is not registered. +// buildLoadBalancingPolicy performs the following: +// - retrieve a balancer builder for the given name. Use the default LB +// policy, pick_first, if no LB policy with name is found in the registry. +// - instruct the gracefulswitch balancer to switch to the above builder. This +// will actually build the new balancer. +// - update the `curBalancerName` field +// +// Must be called from a serializer callback. +func (ccb *ccBalancerWrapper) buildLoadBalancingPolicy(name string) { builder := balancer.Get(name) if builder == nil { channelz.Warningf(logger, ccb.cc.channelzID, "Channel switches to new LB policy %q, since the specified LB policy %q was not registered", PickFirstBalancerName, name) @@ -281,26 +199,114 @@ func (ccb *ccBalancerWrapper) handleSwitchTo(name string) { ccb.curBalancerName = builder.Name() } -// handleRemoveSucConn handles a request from the underlying balancer to remove -// a subConn. -// -// See comments in RemoveSubConn() for more details. -func (ccb *ccBalancerWrapper) handleRemoveSubConn(acbw *acBalancerWrapper) { - ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain) +func (ccb *ccBalancerWrapper) close() { + channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: closing") + ccb.closeBalancer(ccbModeClosed) } -func (ccb *ccBalancerWrapper) close() { - ccb.closed.Fire() - <-ccb.done.Done() +// enterIdleMode is invoked by grpc when the channel enters idle mode upon +// expiry of idle_timeout. This call blocks until the balancer is closed. +func (ccb *ccBalancerWrapper) enterIdleMode() { + channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: entering idle mode") + ccb.closeBalancer(ccbModeIdle) +} + +// closeBalancer is invoked when the channel is being closed or when it enters +// idle mode upon expiry of idle_timeout. +func (ccb *ccBalancerWrapper) closeBalancer(m ccbMode) { + ccb.mu.Lock() + if ccb.mode == ccbModeClosed || ccb.mode == ccbModeIdle { + ccb.mu.Unlock() + return + } + + ccb.mode = m + done := ccb.serializer.Done + b := ccb.balancer + ok := ccb.serializer.Schedule(func(_ context.Context) { + // Close the serializer to ensure that no more calls from gRPC are sent + // to the balancer. + ccb.serializerCancel() + // Empty the current balancer name because we don't have a balancer + // anymore and also so that we act on the next call to switchTo by + // creating a new balancer specified by the new resolver. + ccb.curBalancerName = "" + }) + if !ok { + ccb.mu.Unlock() + return + } + ccb.mu.Unlock() + + // Give enqueued callbacks a chance to finish. + <-done + // Spawn a goroutine to close the balancer (since it may block trying to + // cleanup all allocated resources) and return early. + go b.Close() } -func (ccb *ccBalancerWrapper) handleClose() { - ccb.balancer.Close() - ccb.done.Fire() +// exitIdleMode is invoked by grpc when the channel exits idle mode either +// because of an RPC or because of an invocation of the Connect() API. This +// recreates the balancer that was closed previously when entering idle mode. +// +// If the channel is not in idle mode, we know for a fact that we are here as a +// result of the user calling the Connect() method on the ClientConn. In this +// case, we can simply forward the call to the underlying balancer, instructing +// it to reconnect to the backends. +func (ccb *ccBalancerWrapper) exitIdleMode() { + ccb.mu.Lock() + if ccb.mode == ccbModeClosed { + // Request to exit idle is a no-op when wrapper is already closed. + ccb.mu.Unlock() + return + } + + if ccb.mode == ccbModeIdle { + // Recreate the serializer which was closed when we entered idle. + ctx, cancel := context.WithCancel(context.Background()) + ccb.serializer = grpcsync.NewCallbackSerializer(ctx) + ccb.serializerCancel = cancel + } + + // The ClientConn guarantees that mutual exclusion between close() and + // exitIdleMode(), and since we just created a new serializer, we can be + // sure that the below function will be scheduled. + done := make(chan struct{}) + ccb.serializer.Schedule(func(_ context.Context) { + defer close(done) + + ccb.mu.Lock() + defer ccb.mu.Unlock() + + if ccb.mode != ccbModeIdle { + ccb.balancer.ExitIdle() + return + } + + // Gracefulswitch balancer does not support a switchTo operation after + // being closed. Hence we need to create a new one here. + ccb.balancer = gracefulswitch.NewBalancer(ccb, ccb.opts) + ccb.mode = ccbModeActive + channelz.Info(logger, ccb.cc.channelzID, "ccBalancerWrapper: exiting idle mode") + + }) + ccb.mu.Unlock() + + <-done +} + +func (ccb *ccBalancerWrapper) isIdleOrClosed() bool { + ccb.mu.Lock() + defer ccb.mu.Unlock() + return ccb.mode == ccbModeIdle || ccb.mode == ccbModeClosed } func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) { - if len(addrs) <= 0 { + if ccb.isIdleOrClosed() { + return nil, fmt.Errorf("grpc: cannot create SubConn when balancer is closed or idle") + } + + if len(addrs) == 0 { return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list") } ac, err := ccb.cc.newAddrConn(addrs, opts) @@ -309,31 +315,35 @@ func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer return nil, err } acbw := &acBalancerWrapper{ac: ac, producers: make(map[balancer.ProducerBuilder]*refCountedProducer)} - acbw.ac.mu.Lock() ac.acbw = acbw - acbw.ac.mu.Unlock() return acbw, nil } func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) { - // Before we switched the ccBalancerWrapper to use gracefulswitch.Balancer, it - // was required to handle the RemoveSubConn() method asynchronously by pushing - // the update onto the update channel. This was done to avoid a deadlock as - // switchBalancer() was holding cc.mu when calling Close() on the old - // balancer, which would in turn call RemoveSubConn(). - // - // With the use of gracefulswitch.Balancer in ccBalancerWrapper, handling this - // asynchronously is probably not required anymore since the switchTo() method - // handles the balancer switch by pushing the update onto the channel. - // TODO(easwars): Handle this inline. + if ccb.isIdleOrClosed() { + // It it safe to ignore this call when the balancer is closed or in idle + // because the ClientConn takes care of closing the connections. + // + // Not returning early from here when the balancer is closed or in idle + // leads to a deadlock though, because of the following sequence of + // calls when holding cc.mu: + // cc.exitIdleMode --> ccb.enterIdleMode --> gsw.Close --> + // ccb.RemoveAddrConn --> cc.removeAddrConn + return + } + acbw, ok := sc.(*acBalancerWrapper) if !ok { return } - ccb.updateCh.Put(&subConnUpdate{acbw: acbw}) + ccb.cc.removeAddrConn(acbw.ac, errConnDrain) } func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resolver.Address) { + if ccb.isIdleOrClosed() { + return + } + acbw, ok := sc.(*acBalancerWrapper) if !ok { return @@ -342,6 +352,10 @@ func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resol } func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) { + if ccb.isIdleOrClosed() { + return + } + // Update picker before updating state. Even though the ordering here does // not matter, it can lead to multiple calls of Pick in the common start-up // case where we wait for ready and then perform an RPC. If the picker is @@ -352,6 +366,10 @@ func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) { } func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOptions) { + if ccb.isIdleOrClosed() { + return + } + ccb.cc.resolveNow(o) } @@ -362,71 +380,31 @@ func (ccb *ccBalancerWrapper) Target() string { // acBalancerWrapper is a wrapper on top of ac for balancers. // It implements balancer.SubConn interface. type acBalancerWrapper struct { + ac *addrConn // read-only + mu sync.Mutex - ac *addrConn producers map[balancer.ProducerBuilder]*refCountedProducer } -func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { - acbw.mu.Lock() - defer acbw.mu.Unlock() - if len(addrs) <= 0 { - acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain) - return - } - if !acbw.ac.tryUpdateAddrs(addrs) { - cc := acbw.ac.cc - opts := acbw.ac.scopts - acbw.ac.mu.Lock() - // Set old ac.acbw to nil so the Shutdown state update will be ignored - // by balancer. - // - // TODO(bar) the state transition could be wrong when tearDown() old ac - // and creating new ac, fix the transition. - acbw.ac.acbw = nil - acbw.ac.mu.Unlock() - acState := acbw.ac.getState() - acbw.ac.cc.removeAddrConn(acbw.ac, errConnDrain) - - if acState == connectivity.Shutdown { - return - } +func (acbw *acBalancerWrapper) String() string { + return fmt.Sprintf("SubConn(id:%d)", acbw.ac.channelzID.Int()) +} - newAC, err := cc.newAddrConn(addrs, opts) - if err != nil { - channelz.Warningf(logger, acbw.ac.channelzID, "acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err) - return - } - acbw.ac = newAC - newAC.mu.Lock() - newAC.acbw = acbw - newAC.mu.Unlock() - if acState != connectivity.Idle { - go newAC.connect() - } - } +func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { + acbw.ac.updateAddrs(addrs) } func (acbw *acBalancerWrapper) Connect() { - acbw.mu.Lock() - defer acbw.mu.Unlock() go acbw.ac.connect() } -func (acbw *acBalancerWrapper) getAddrConn() *addrConn { - acbw.mu.Lock() - defer acbw.mu.Unlock() - return acbw.ac -} - -var errSubConnNotReady = status.Error(codes.Unavailable, "SubConn not currently connected") - // NewStream begins a streaming RPC on the addrConn. If the addrConn is not -// ready, returns errSubConnNotReady. +// ready, blocks until it is or ctx expires. Returns an error when the context +// expires or the addrConn is shut down. func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) { - transport := acbw.ac.getReadyTransport() - if transport == nil { - return nil, errSubConnNotReady + transport, err := acbw.ac.getTransport(ctx) + if err != nil { + return nil, err } return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...) } diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go index 8cd89dab9..ec2c2fa14 100644 --- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc v4.22.0 // source: grpc/binlog/v1/binarylog.proto diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go index 9e20e4d38..e6a1dc5d7 100644 --- a/vendor/google.golang.org/grpc/call.go +++ b/vendor/google.golang.org/grpc/call.go @@ -27,6 +27,11 @@ import ( // // All errors returned by Invoke are compatible with the status package. func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error { + if err := cc.idlenessMgr.onCallBegin(); err != nil { + return err + } + defer cc.idlenessMgr.onCallEnd() + // allow interceptor to see all applicable call options, which means those // configured as defaults from dial option as well as per-call options opts = combine(cc.dopts.callOptions, opts) diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index b9cc05507..95a7459b0 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -24,7 +24,6 @@ import ( "fmt" "math" "net/url" - "reflect" "strings" "sync" "sync/atomic" @@ -69,6 +68,9 @@ var ( errConnDrain = errors.New("grpc: the connection is drained") // errConnClosing indicates that the connection is closing. errConnClosing = errors.New("grpc: the connection is closing") + // errConnIdling indicates the the connection is being closed as the channel + // is moving to an idle mode due to inactivity. + errConnIdling = errors.New("grpc: the connection is closing due to channel idleness") // invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default // service config. invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid" @@ -134,17 +136,29 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires // e.g. to use dns resolver, a "dns:///" prefix should be applied to the target. func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) { cc := &ClientConn{ - target: target, - csMgr: &connectivityStateManager{}, - conns: make(map[*addrConn]struct{}), - dopts: defaultDialOptions(), - blockingpicker: newPickerWrapper(), - czData: new(channelzData), - firstResolveEvent: grpcsync.NewEvent(), - } + target: target, + csMgr: &connectivityStateManager{}, + conns: make(map[*addrConn]struct{}), + dopts: defaultDialOptions(), + czData: new(channelzData), + } + + // We start the channel off in idle mode, but kick it out of idle at the end + // of this method, instead of waiting for the first RPC. Other gRPC + // implementations do wait for the first RPC to kick the channel out of + // idle. But doing so would be a major behavior change for our users who are + // used to seeing the channel active after Dial. + // + // Taking this approach of kicking it out of idle at the end of this method + // allows us to share the code between channel creation and exiting idle + // mode. This will also make it easy for us to switch to starting the + // channel off in idle, if at all we ever get to do that. + cc.idlenessState = ccIdlenessStateIdle + cc.retryThrottler.Store((*retryThrottler)(nil)) cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{nil}) cc.ctx, cc.cancel = context.WithCancel(context.Background()) + cc.exitIdleCond = sync.NewCond(&cc.mu) disableGlobalOpts := false for _, opt := range opts { @@ -173,40 +187,11 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * } }() - pid := cc.dopts.channelzParentID - cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, pid, target) - ted := &channelz.TraceEventDesc{ - Desc: "Channel created", - Severity: channelz.CtInfo, - } - if cc.dopts.channelzParentID != nil { - ted.Parent = &channelz.TraceEventDesc{ - Desc: fmt.Sprintf("Nested Channel(id:%d) created", cc.channelzID.Int()), - Severity: channelz.CtInfo, - } - } - channelz.AddTraceEvent(logger, cc.channelzID, 1, ted) - cc.csMgr.channelzID = cc.channelzID + // Register ClientConn with channelz. + cc.channelzRegistration(target) - if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil { - return nil, errNoTransportSecurity - } - if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil { - return nil, errTransportCredsAndBundle - } - if cc.dopts.copts.CredsBundle != nil && cc.dopts.copts.CredsBundle.TransportCredentials() == nil { - return nil, errNoTransportCredsInBundle - } - transportCreds := cc.dopts.copts.TransportCredentials - if transportCreds == nil { - transportCreds = cc.dopts.copts.CredsBundle.TransportCredentials() - } - if transportCreds.Info().SecurityProtocol == "insecure" { - for _, cd := range cc.dopts.copts.PerRPCCredentials { - if cd.RequireTransportSecurity() { - return nil, errTransportCredentialsMissing - } - } + if err := cc.validateTransportCredentials(); err != nil { + return nil, err } if cc.dopts.defaultServiceConfigRawJSON != nil { @@ -244,35 +229,19 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * } }() - scSet := false - if cc.dopts.scChan != nil { - // Try to get an initial service config. - select { - case sc, ok := <-cc.dopts.scChan: - if ok { - cc.sc = &sc - cc.safeConfigSelector.UpdateConfigSelector(&defaultConfigSelector{&sc}) - scSet = true - } - default: - } - } if cc.dopts.bs == nil { cc.dopts.bs = backoff.DefaultExponential } // Determine the resolver to use. - resolverBuilder, err := cc.parseTargetAndFindResolver() - if err != nil { + if err := cc.parseTargetAndFindResolver(); err != nil { return nil, err } - cc.authority, err = determineAuthority(cc.parsedTarget.Endpoint(), cc.target, cc.dopts) - if err != nil { + if err = cc.determineAuthority(); err != nil { return nil, err } - channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority) - if cc.dopts.scChan != nil && !scSet { + if cc.dopts.scChan != nil { // Blocking wait for the initial service config. select { case sc, ok := <-cc.dopts.scChan: @@ -288,57 +257,224 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * go cc.scWatcher() } + // This creates the name resolver, load balancer, blocking picker etc. + if err := cc.exitIdleMode(); err != nil { + return nil, err + } + + // Configure idleness support with configured idle timeout or default idle + // timeout duration. Idleness can be explicitly disabled by the user, by + // setting the dial option to 0. + cc.idlenessMgr = newIdlenessManager(cc, cc.dopts.idleTimeout) + + // Return early for non-blocking dials. + if !cc.dopts.block { + return cc, nil + } + + // A blocking dial blocks until the clientConn is ready. + for { + s := cc.GetState() + if s == connectivity.Idle { + cc.Connect() + } + if s == connectivity.Ready { + return cc, nil + } else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure { + if err = cc.connectionError(); err != nil { + terr, ok := err.(interface { + Temporary() bool + }) + if ok && !terr.Temporary() { + return nil, err + } + } + } + if !cc.WaitForStateChange(ctx, s) { + // ctx got timeout or canceled. + if err = cc.connectionError(); err != nil && cc.dopts.returnLastError { + return nil, err + } + return nil, ctx.Err() + } + } +} + +// addTraceEvent is a helper method to add a trace event on the channel. If the +// channel is a nested one, the same event is also added on the parent channel. +func (cc *ClientConn) addTraceEvent(msg string) { + ted := &channelz.TraceEventDesc{ + Desc: fmt.Sprintf("Channel %s", msg), + Severity: channelz.CtInfo, + } + if cc.dopts.channelzParentID != nil { + ted.Parent = &channelz.TraceEventDesc{ + Desc: fmt.Sprintf("Nested channel(id:%d) %s", cc.channelzID.Int(), msg), + Severity: channelz.CtInfo, + } + } + channelz.AddTraceEvent(logger, cc.channelzID, 0, ted) +} + +// exitIdleMode moves the channel out of idle mode by recreating the name +// resolver and load balancer. +func (cc *ClientConn) exitIdleMode() error { + cc.mu.Lock() + if cc.conns == nil { + cc.mu.Unlock() + return errConnClosing + } + if cc.idlenessState != ccIdlenessStateIdle { + cc.mu.Unlock() + logger.Info("ClientConn asked to exit idle mode when not in idle mode") + return nil + } + + defer func() { + // When Close() and exitIdleMode() race against each other, one of the + // following two can happen: + // - Close() wins the race and runs first. exitIdleMode() runs after, and + // sees that the ClientConn is already closed and hence returns early. + // - exitIdleMode() wins the race and runs first and recreates the balancer + // and releases the lock before recreating the resolver. If Close() runs + // in this window, it will wait for exitIdleMode to complete. + // + // We achieve this synchronization using the below condition variable. + cc.mu.Lock() + cc.idlenessState = ccIdlenessStateActive + cc.exitIdleCond.Signal() + cc.mu.Unlock() + }() + + cc.idlenessState = ccIdlenessStateExitingIdle + exitedIdle := false + if cc.blockingpicker == nil { + cc.blockingpicker = newPickerWrapper() + } else { + cc.blockingpicker.exitIdleMode() + exitedIdle = true + } + var credsClone credentials.TransportCredentials if creds := cc.dopts.copts.TransportCredentials; creds != nil { credsClone = creds.Clone() } - cc.balancerWrapper = newCCBalancerWrapper(cc, balancer.BuildOptions{ - DialCreds: credsClone, - CredsBundle: cc.dopts.copts.CredsBundle, - Dialer: cc.dopts.copts.Dialer, - Authority: cc.authority, - CustomUserAgent: cc.dopts.copts.UserAgent, - ChannelzParentID: cc.channelzID, - Target: cc.parsedTarget, - }) + if cc.balancerWrapper == nil { + cc.balancerWrapper = newCCBalancerWrapper(cc, balancer.BuildOptions{ + DialCreds: credsClone, + CredsBundle: cc.dopts.copts.CredsBundle, + Dialer: cc.dopts.copts.Dialer, + Authority: cc.authority, + CustomUserAgent: cc.dopts.copts.UserAgent, + ChannelzParentID: cc.channelzID, + Target: cc.parsedTarget, + }) + } else { + cc.balancerWrapper.exitIdleMode() + } + cc.firstResolveEvent = grpcsync.NewEvent() + cc.mu.Unlock() - // Build the resolver. - rWrapper, err := newCCResolverWrapper(cc, resolverBuilder) - if err != nil { - return nil, fmt.Errorf("failed to build resolver: %v", err) + // This needs to be called without cc.mu because this builds a new resolver + // which might update state or report error inline which needs to be handled + // by cc.updateResolverState() which also grabs cc.mu. + if err := cc.initResolverWrapper(credsClone); err != nil { + return err } + + if exitedIdle { + cc.addTraceEvent("exiting idle mode") + } + return nil +} + +// enterIdleMode puts the channel in idle mode, and as part of it shuts down the +// name resolver, load balancer and any subchannels. +func (cc *ClientConn) enterIdleMode() error { cc.mu.Lock() - cc.resolverWrapper = rWrapper + if cc.conns == nil { + cc.mu.Unlock() + return ErrClientConnClosing + } + if cc.idlenessState != ccIdlenessStateActive { + logger.Error("ClientConn asked to enter idle mode when not active") + return nil + } + + // cc.conns == nil is a proxy for the ClientConn being closed. So, instead + // of setting it to nil here, we recreate the map. This also means that we + // don't have to do this when exiting idle mode. + conns := cc.conns + cc.conns = make(map[*addrConn]struct{}) + + // TODO: Currently, we close the resolver wrapper upon entering idle mode + // and create a new one upon exiting idle mode. This means that the + // `cc.resolverWrapper` field would be overwritten everytime we exit idle + // mode. While this means that we need to hold `cc.mu` when accessing + // `cc.resolverWrapper`, it makes the code simpler in the wrapper. We should + // try to do the same for the balancer and picker wrappers too. + cc.resolverWrapper.close() + cc.blockingpicker.enterIdleMode() + cc.balancerWrapper.enterIdleMode() + cc.csMgr.updateState(connectivity.Idle) + cc.idlenessState = ccIdlenessStateIdle cc.mu.Unlock() - // A blocking dial blocks until the clientConn is ready. - if cc.dopts.block { - for { - cc.Connect() - s := cc.GetState() - if s == connectivity.Ready { - break - } else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure { - if err = cc.connectionError(); err != nil { - terr, ok := err.(interface { - Temporary() bool - }) - if ok && !terr.Temporary() { - return nil, err - } - } - } - if !cc.WaitForStateChange(ctx, s) { - // ctx got timeout or canceled. - if err = cc.connectionError(); err != nil && cc.dopts.returnLastError { - return nil, err - } - return nil, ctx.Err() + go func() { + cc.addTraceEvent("entering idle mode") + for ac := range conns { + ac.tearDown(errConnIdling) + } + }() + return nil +} + +// validateTransportCredentials performs a series of checks on the configured +// transport credentials. It returns a non-nil error if any of these conditions +// are met: +// - no transport creds and no creds bundle is configured +// - both transport creds and creds bundle are configured +// - creds bundle is configured, but it lacks a transport credentials +// - insecure transport creds configured alongside call creds that require +// transport level security +// +// If none of the above conditions are met, the configured credentials are +// deemed valid and a nil error is returned. +func (cc *ClientConn) validateTransportCredentials() error { + if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil { + return errNoTransportSecurity + } + if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil { + return errTransportCredsAndBundle + } + if cc.dopts.copts.CredsBundle != nil && cc.dopts.copts.CredsBundle.TransportCredentials() == nil { + return errNoTransportCredsInBundle + } + transportCreds := cc.dopts.copts.TransportCredentials + if transportCreds == nil { + transportCreds = cc.dopts.copts.CredsBundle.TransportCredentials() + } + if transportCreds.Info().SecurityProtocol == "insecure" { + for _, cd := range cc.dopts.copts.PerRPCCredentials { + if cd.RequireTransportSecurity() { + return errTransportCredentialsMissing } } } + return nil +} - return cc, nil +// channelzRegistration registers the newly created ClientConn with channelz and +// stores the returned identifier in `cc.channelzID` and `cc.csMgr.channelzID`. +// A channelz trace event is emitted for ClientConn creation. If the newly +// created ClientConn is a nested one, i.e a valid parent ClientConn ID is +// specified via a dial option, the trace event is also added to the parent. +// +// Doesn't grab cc.mu as this method is expected to be called only at Dial time. +func (cc *ClientConn) channelzRegistration(target string) { + cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, cc.dopts.channelzParentID, target) + cc.addTraceEvent("created") + cc.csMgr.channelzID = cc.channelzID } // chainUnaryClientInterceptors chains all unary client interceptors into one. @@ -484,7 +620,9 @@ type ClientConn struct { authority string // See determineAuthority(). dopts dialOptions // Default and user specified dial options. channelzID *channelz.Identifier // Channelz identifier for the channel. + resolverBuilder resolver.Builder // See parseTargetAndFindResolver(). balancerWrapper *ccBalancerWrapper // Uses gracefulswitch.balancer underneath. + idlenessMgr idlenessManager // The following provide their own synchronization, and therefore don't // require cc.mu to be held to access them. @@ -505,11 +643,31 @@ type ClientConn struct { sc *ServiceConfig // Latest service config received from the resolver. conns map[*addrConn]struct{} // Set to nil on close. mkp keepalive.ClientParameters // May be updated upon receipt of a GoAway. + idlenessState ccIdlenessState // Tracks idleness state of the channel. + exitIdleCond *sync.Cond // Signalled when channel exits idle. lceMu sync.Mutex // protects lastConnectionError lastConnectionError error } +// ccIdlenessState tracks the idleness state of the channel. +// +// Channels start off in `active` and move to `idle` after a period of +// inactivity. When moving back to `active` upon an incoming RPC, they +// transition through `exiting_idle`. This state is useful for synchronization +// with Close(). +// +// This state tracking is mostly for self-protection. The idlenessManager is +// expected to keep track of the state as well, and is expected not to call into +// the ClientConn unnecessarily. +type ccIdlenessState int8 + +const ( + ccIdlenessStateActive ccIdlenessState = iota + ccIdlenessStateIdle + ccIdlenessStateExitingIdle +) + // WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or // ctx expires. A true value is returned in former case and false in latter. // @@ -549,7 +707,10 @@ func (cc *ClientConn) GetState() connectivity.State { // Notice: This API is EXPERIMENTAL and may be changed or removed in a later // release. func (cc *ClientConn) Connect() { - cc.balancerWrapper.exitIdle() + cc.exitIdleMode() + // If the ClientConn was not in idle mode, we need to call ExitIdle on the + // LB policy so that connections can be created. + cc.balancerWrapper.exitIdleMode() } func (cc *ClientConn) scWatcher() { @@ -718,6 +879,7 @@ func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSub dopts: cc.dopts, czData: new(channelzData), resetBackoff: make(chan struct{}), + stateChan: make(chan struct{}), } ac.ctx, ac.cancel = context.WithCancel(cc.ctx) // Track ac in cc. This needs to be done before any getTransport(...) is called. @@ -811,9 +973,6 @@ func (ac *addrConn) connect() error { ac.mu.Unlock() return nil } - // Update connectivity state within the lock to prevent subsequent or - // concurrent calls from resetting the transport more than once. - ac.updateConnectivityState(connectivity.Connecting, nil) ac.mu.Unlock() ac.resetTransport() @@ -832,58 +991,62 @@ func equalAddresses(a, b []resolver.Address) bool { return true } -// tryUpdateAddrs tries to update ac.addrs with the new addresses list. -// -// If ac is TransientFailure, it updates ac.addrs and returns true. The updated -// addresses will be picked up by retry in the next iteration after backoff. -// -// If ac is Shutdown or Idle, it updates ac.addrs and returns true. -// -// If the addresses is the same as the old list, it does nothing and returns -// true. -// -// If ac is Connecting, it returns false. The caller should tear down the ac and -// create a new one. Note that the backoff will be reset when this happens. -// -// If ac is Ready, it checks whether current connected address of ac is in the -// new addrs list. -// - If true, it updates ac.addrs and returns true. The ac will keep using -// the existing connection. -// - If false, it does nothing and returns false. -func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool { +// updateAddrs updates ac.addrs with the new addresses list and handles active +// connections or connection attempts. +func (ac *addrConn) updateAddrs(addrs []resolver.Address) { ac.mu.Lock() - defer ac.mu.Unlock() - channelz.Infof(logger, ac.channelzID, "addrConn: tryUpdateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs) + channelz.Infof(logger, ac.channelzID, "addrConn: updateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs) + + if equalAddresses(ac.addrs, addrs) { + ac.mu.Unlock() + return + } + + ac.addrs = addrs + if ac.state == connectivity.Shutdown || ac.state == connectivity.TransientFailure || ac.state == connectivity.Idle { - ac.addrs = addrs - return true + // We were not connecting, so do nothing but update the addresses. + ac.mu.Unlock() + return } - if equalAddresses(ac.addrs, addrs) { - return true + if ac.state == connectivity.Ready { + // Try to find the connected address. + for _, a := range addrs { + a.ServerName = ac.cc.getServerName(a) + if a.Equal(ac.curAddr) { + // We are connected to a valid address, so do nothing but + // update the addresses. + ac.mu.Unlock() + return + } + } } - if ac.state == connectivity.Connecting { - return false - } + // We are either connected to the wrong address or currently connecting. + // Stop the current iteration and restart. - // ac.state is Ready, try to find the connected address. - var curAddrFound bool - for _, a := range addrs { - a.ServerName = ac.cc.getServerName(a) - if reflect.DeepEqual(ac.curAddr, a) { - curAddrFound = true - break - } + ac.cancel() + ac.ctx, ac.cancel = context.WithCancel(ac.cc.ctx) + + // We have to defer here because GracefulClose => Close => onClose, which + // requires locking ac.mu. + if ac.transport != nil { + defer ac.transport.GracefulClose() + ac.transport = nil } - channelz.Infof(logger, ac.channelzID, "addrConn: tryUpdateAddrs curAddrFound: %v", curAddrFound) - if curAddrFound { - ac.addrs = addrs + + if len(addrs) == 0 { + ac.updateConnectivityState(connectivity.Idle, nil) } - return curAddrFound + ac.mu.Unlock() + + // Since we were connecting/connected, we should start a new connection + // attempt. + go ac.resetTransport() } // getServerName determines the serverName to be used in the connection @@ -1036,39 +1199,40 @@ func (cc *ClientConn) Close() error { cc.mu.Unlock() return ErrClientConnClosing } + + for cc.idlenessState == ccIdlenessStateExitingIdle { + cc.exitIdleCond.Wait() + } + conns := cc.conns cc.conns = nil cc.csMgr.updateState(connectivity.Shutdown) + pWrapper := cc.blockingpicker rWrapper := cc.resolverWrapper - cc.resolverWrapper = nil bWrapper := cc.balancerWrapper + idlenessMgr := cc.idlenessMgr cc.mu.Unlock() // The order of closing matters here since the balancer wrapper assumes the // picker is closed before it is closed. - cc.blockingpicker.close() + if pWrapper != nil { + pWrapper.close() + } if bWrapper != nil { bWrapper.close() } if rWrapper != nil { rWrapper.close() } + if idlenessMgr != nil { + idlenessMgr.close() + } for ac := range conns { ac.tearDown(ErrClientConnClosing) } - ted := &channelz.TraceEventDesc{ - Desc: "Channel deleted", - Severity: channelz.CtInfo, - } - if cc.dopts.channelzParentID != nil { - ted.Parent = &channelz.TraceEventDesc{ - Desc: fmt.Sprintf("Nested channel(id:%d) deleted", cc.channelzID.Int()), - Severity: channelz.CtInfo, - } - } - channelz.AddTraceEvent(logger, cc.channelzID, 0, ted) + cc.addTraceEvent("deleted") // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add // trace reference to the entity being deleted, and thus prevent it from being // deleted right away. @@ -1098,7 +1262,8 @@ type addrConn struct { addrs []resolver.Address // All addresses that the resolver resolved to. // Use updateConnectivityState for updating addrConn's connectivity state. - state connectivity.State + state connectivity.State + stateChan chan struct{} // closed and recreated on every state change. backoffIdx int // Needs to be stateful for resetConnectBackoff. resetBackoff chan struct{} @@ -1112,6 +1277,9 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) if ac.state == s { return } + // When changing states, reset the state change channel. + close(ac.stateChan) + ac.stateChan = make(chan struct{}) ac.state = s if lastErr == nil { channelz.Infof(logger, ac.channelzID, "Subchannel Connectivity change to %v", s) @@ -1137,7 +1305,8 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) { func (ac *addrConn) resetTransport() { ac.mu.Lock() - if ac.state == connectivity.Shutdown { + acCtx := ac.ctx + if acCtx.Err() != nil { ac.mu.Unlock() return } @@ -1165,15 +1334,14 @@ func (ac *addrConn) resetTransport() { ac.updateConnectivityState(connectivity.Connecting, nil) ac.mu.Unlock() - if err := ac.tryAllAddrs(addrs, connectDeadline); err != nil { + if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil { ac.cc.resolveNow(resolver.ResolveNowOptions{}) // After exhausting all addresses, the addrConn enters // TRANSIENT_FAILURE. - ac.mu.Lock() - if ac.state == connectivity.Shutdown { - ac.mu.Unlock() + if acCtx.Err() != nil { return } + ac.mu.Lock() ac.updateConnectivityState(connectivity.TransientFailure, err) // Backoff. @@ -1188,13 +1356,13 @@ func (ac *addrConn) resetTransport() { ac.mu.Unlock() case <-b: timer.Stop() - case <-ac.ctx.Done(): + case <-acCtx.Done(): timer.Stop() return } ac.mu.Lock() - if ac.state != connectivity.Shutdown { + if acCtx.Err() == nil { ac.updateConnectivityState(connectivity.Idle, err) } ac.mu.Unlock() @@ -1209,14 +1377,13 @@ func (ac *addrConn) resetTransport() { // tryAllAddrs tries to creates a connection to the addresses, and stop when at // the first successful one. It returns an error if no address was successfully // connected, or updates ac appropriately with the new transport. -func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.Time) error { +func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, connectDeadline time.Time) error { var firstConnErr error for _, addr := range addrs { - ac.mu.Lock() - if ac.state == connectivity.Shutdown { - ac.mu.Unlock() + if ctx.Err() != nil { return errConnClosing } + ac.mu.Lock() ac.cc.mu.RLock() ac.dopts.copts.KeepaliveParams = ac.cc.mkp @@ -1230,7 +1397,7 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T channelz.Infof(logger, ac.channelzID, "Subchannel picks a new address %q to connect", addr.Addr) - err := ac.createTransport(addr, copts, connectDeadline) + err := ac.createTransport(ctx, addr, copts, connectDeadline) if err == nil { return nil } @@ -1247,19 +1414,20 @@ func (ac *addrConn) tryAllAddrs(addrs []resolver.Address, connectDeadline time.T // createTransport creates a connection to addr. It returns an error if the // address was not successfully connected, or updates ac appropriately with the // new transport. -func (ac *addrConn) createTransport(addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error { +func (ac *addrConn) createTransport(ctx context.Context, addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error { addr.ServerName = ac.cc.getServerName(addr) - hctx, hcancel := context.WithCancel(ac.ctx) + hctx, hcancel := context.WithCancel(ctx) onClose := func(r transport.GoAwayReason) { ac.mu.Lock() defer ac.mu.Unlock() // adjust params based on GoAwayReason ac.adjustParams(r) - if ac.state == connectivity.Shutdown { - // Already shut down. tearDown() already cleared the transport and - // canceled hctx via ac.ctx, and we expected this connection to be - // closed, so do nothing here. + if ctx.Err() != nil { + // Already shut down or connection attempt canceled. tearDown() or + // updateAddrs() already cleared the transport and canceled hctx + // via ac.ctx, and we expected this connection to be closed, so do + // nothing here. return } hcancel() @@ -1278,7 +1446,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne ac.updateConnectivityState(connectivity.Idle, nil) } - connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline) + connectCtx, cancel := context.WithDeadline(ctx, connectDeadline) defer cancel() copts.ChannelzParentID = ac.channelzID @@ -1295,7 +1463,7 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne ac.mu.Lock() defer ac.mu.Unlock() - if ac.state == connectivity.Shutdown { + if ctx.Err() != nil { // This can happen if the subConn was removed while in `Connecting` // state. tearDown() would have set the state to `Shutdown`, but // would not have closed the transport since ac.transport would not @@ -1307,6 +1475,9 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne // The error we pass to Close() is immaterial since there are no open // streams at this point, so no trailers with error details will be sent // out. We just need to pass a non-nil error. + // + // This can also happen when updateAddrs is called during a connection + // attempt. go newTr.Close(transport.ErrConnClosing) return nil } @@ -1414,6 +1585,29 @@ func (ac *addrConn) getReadyTransport() transport.ClientTransport { return nil } +// getTransport waits until the addrconn is ready and returns the transport. +// If the context expires first, returns an appropriate status. If the +// addrConn is stopped first, returns an Unavailable status error. +func (ac *addrConn) getTransport(ctx context.Context) (transport.ClientTransport, error) { + for ctx.Err() == nil { + ac.mu.Lock() + t, state, sc := ac.transport, ac.state, ac.stateChan + ac.mu.Unlock() + if state == connectivity.Ready { + return t, nil + } + if state == connectivity.Shutdown { + return nil, status.Errorf(codes.Unavailable, "SubConn shutting down") + } + + select { + case <-ctx.Done(): + case <-sc: + } + } + return nil, status.FromContextError(ctx.Err()).Err() +} + // tearDown starts to tear down the addrConn. // // Note that tearDown doesn't remove ac from ac.cc.conns, so the addrConn struct @@ -1565,7 +1759,14 @@ func (cc *ClientConn) connectionError() error { return cc.lastConnectionError } -func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) { +// parseTargetAndFindResolver parses the user's dial target and stores the +// parsed target in `cc.parsedTarget`. +// +// The resolver to use is determined based on the scheme in the parsed target +// and the same is stored in `cc.resolverBuilder`. +// +// Doesn't grab cc.mu as this method is expected to be called only at Dial time. +func (cc *ClientConn) parseTargetAndFindResolver() error { channelz.Infof(logger, cc.channelzID, "original dial target is: %q", cc.target) var rb resolver.Builder @@ -1577,7 +1778,8 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) { rb = cc.getResolver(parsedTarget.URL.Scheme) if rb != nil { cc.parsedTarget = parsedTarget - return rb, nil + cc.resolverBuilder = rb + return nil } } @@ -1592,15 +1794,16 @@ func (cc *ClientConn) parseTargetAndFindResolver() (resolver.Builder, error) { parsedTarget, err = parseTarget(canonicalTarget) if err != nil { channelz.Infof(logger, cc.channelzID, "dial target %q parse failed: %v", canonicalTarget, err) - return nil, err + return err } channelz.Infof(logger, cc.channelzID, "parsed dial target is: %+v", parsedTarget) rb = cc.getResolver(parsedTarget.URL.Scheme) if rb == nil { - return nil, fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme) + return fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme) } cc.parsedTarget = parsedTarget - return rb, nil + cc.resolverBuilder = rb + return nil } // parseTarget uses RFC 3986 semantics to parse the given target into a @@ -1623,7 +1826,15 @@ func parseTarget(target string) (resolver.Target, error) { // - user specified authority override using `WithAuthority` dial option // - creds' notion of server name for the authentication handshake // - endpoint from dial target of the form "scheme://[authority]/endpoint" -func determineAuthority(endpoint, target string, dopts dialOptions) (string, error) { +// +// Stores the determined authority in `cc.authority`. +// +// Returns a non-nil error if the authority returned by the transport +// credentials do not match the authority configured through the dial option. +// +// Doesn't grab cc.mu as this method is expected to be called only at Dial time. +func (cc *ClientConn) determineAuthority() error { + dopts := cc.dopts // Historically, we had two options for users to specify the serverName or // authority for a channel. One was through the transport credentials // (either in its constructor, or through the OverrideServerName() method). @@ -1640,25 +1851,58 @@ func determineAuthority(endpoint, target string, dopts dialOptions) (string, err } authorityFromDialOption := dopts.authority if (authorityFromCreds != "" && authorityFromDialOption != "") && authorityFromCreds != authorityFromDialOption { - return "", fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption) + return fmt.Errorf("ClientConn's authority from transport creds %q and dial option %q don't match", authorityFromCreds, authorityFromDialOption) } + endpoint := cc.parsedTarget.Endpoint() + target := cc.target switch { case authorityFromDialOption != "": - return authorityFromDialOption, nil + cc.authority = authorityFromDialOption case authorityFromCreds != "": - return authorityFromCreds, nil + cc.authority = authorityFromCreds case strings.HasPrefix(target, "unix:") || strings.HasPrefix(target, "unix-abstract:"): // TODO: remove when the unix resolver implements optional interface to // return channel authority. - return "localhost", nil + cc.authority = "localhost" case strings.HasPrefix(endpoint, ":"): - return "localhost" + endpoint, nil + cc.authority = "localhost" + endpoint default: // TODO: Define an optional interface on the resolver builder to return // the channel authority given the user's dial target. For resolvers // which don't implement this interface, we will use the endpoint from // "scheme://authority/endpoint" as the default authority. - return endpoint, nil + cc.authority = endpoint + } + channelz.Infof(logger, cc.channelzID, "Channel authority set to %q", cc.authority) + return nil +} + +// initResolverWrapper creates a ccResolverWrapper, which builds the name +// resolver. This method grabs the lock to assign the newly built resolver +// wrapper to the cc.resolverWrapper field. +func (cc *ClientConn) initResolverWrapper(creds credentials.TransportCredentials) error { + rw, err := newCCResolverWrapper(cc, ccResolverWrapperOpts{ + target: cc.parsedTarget, + builder: cc.resolverBuilder, + bOpts: resolver.BuildOptions{ + DisableServiceConfig: cc.dopts.disableServiceConfig, + DialCreds: creds, + CredsBundle: cc.dopts.copts.CredsBundle, + Dialer: cc.dopts.copts.Dialer, + }, + channelzID: cc.channelzID, + }) + if err != nil { + return fmt.Errorf("failed to build resolver: %v", err) } + // Resolver implementations may report state update or error inline when + // built (or right after), and this is handled in cc.updateResolverState. + // Also, an error from the resolver might lead to a re-resolution request + // from the balancer, which is handled in resolveNow() where + // `cc.resolverWrapper` is accessed. Hence, we need to hold the lock here. + cc.mu.Lock() + cc.resolverWrapper = rw + cc.mu.Unlock() + return nil } diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go index e9d6852fd..15a3d5102 100644 --- a/vendor/google.golang.org/grpc/dialoptions.go +++ b/vendor/google.golang.org/grpc/dialoptions.go @@ -77,6 +77,7 @@ type dialOptions struct { defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON. defaultServiceConfigRawJSON *string resolvers []resolver.Builder + idleTimeout time.Duration } // DialOption configures how we set up the connection. @@ -295,6 +296,9 @@ func withBackoff(bs internalbackoff.Strategy) DialOption { // WithBlock returns a DialOption which makes callers of Dial block until the // underlying connection is up. Without this, Dial returns immediately and // connecting the server happens in background. +// +// Use of this feature is not recommended. For more information, please see: +// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md func WithBlock() DialOption { return newFuncDialOption(func(o *dialOptions) { o.block = true @@ -306,6 +310,9 @@ func WithBlock() DialOption { // the context.DeadlineExceeded error. // Implies WithBlock() // +// Use of this feature is not recommended. For more information, please see: +// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md +// // # Experimental // // Notice: This API is EXPERIMENTAL and may be changed or removed in a @@ -448,6 +455,9 @@ func withBinaryLogger(bl binarylog.Logger) DialOption { // FailOnNonTempDialError only affects the initial dial, and does not do // anything useful unless you are also using WithBlock(). // +// Use of this feature is not recommended. For more information, please see: +// https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md +// // # Experimental // // Notice: This API is EXPERIMENTAL and may be changed or removed in a @@ -646,3 +656,23 @@ func WithResolvers(rs ...resolver.Builder) DialOption { o.resolvers = append(o.resolvers, rs...) }) } + +// WithIdleTimeout returns a DialOption that configures an idle timeout for the +// channel. If the channel is idle for the configured timeout, i.e there are no +// ongoing RPCs and no new RPCs are initiated, the channel will enter idle mode +// and as a result the name resolver and load balancer will be shut down. The +// channel will exit idle mode when the Connect() method is called or when an +// RPC is initiated. +// +// By default this feature is disabled, which can also be explicitly configured +// by passing zero to this function. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func WithIdleTimeout(d time.Duration) DialOption { + return newFuncDialOption(func(o *dialOptions) { + o.idleTimeout = d + }) +} diff --git a/vendor/google.golang.org/grpc/idle.go b/vendor/google.golang.org/grpc/idle.go new file mode 100644 index 000000000..dc3dc72f6 --- /dev/null +++ b/vendor/google.golang.org/grpc/idle.go @@ -0,0 +1,287 @@ +/* + * + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package grpc + +import ( + "fmt" + "math" + "sync" + "sync/atomic" + "time" +) + +// For overriding in unit tests. +var timeAfterFunc = func(d time.Duration, f func()) *time.Timer { + return time.AfterFunc(d, f) +} + +// idlenessEnforcer is the functionality provided by grpc.ClientConn to enter +// and exit from idle mode. +type idlenessEnforcer interface { + exitIdleMode() error + enterIdleMode() error +} + +// idlenessManager defines the functionality required to track RPC activity on a +// channel. +type idlenessManager interface { + onCallBegin() error + onCallEnd() + close() +} + +type noopIdlenessManager struct{} + +func (noopIdlenessManager) onCallBegin() error { return nil } +func (noopIdlenessManager) onCallEnd() {} +func (noopIdlenessManager) close() {} + +// idlenessManagerImpl implements the idlenessManager interface. It uses atomic +// operations to synchronize access to shared state and a mutex to guarantee +// mutual exclusion in a critical section. +type idlenessManagerImpl struct { + // State accessed atomically. + lastCallEndTime int64 // Unix timestamp in nanos; time when the most recent RPC completed. + activeCallsCount int32 // Count of active RPCs; -math.MaxInt32 means channel is idle or is trying to get there. + activeSinceLastTimerCheck int32 // Boolean; True if there was an RPC since the last timer callback. + closed int32 // Boolean; True when the manager is closed. + + // Can be accessed without atomics or mutex since these are set at creation + // time and read-only after that. + enforcer idlenessEnforcer // Functionality provided by grpc.ClientConn. + timeout int64 // Idle timeout duration nanos stored as an int64. + + // idleMu is used to guarantee mutual exclusion in two scenarios: + // - Opposing intentions: + // - a: Idle timeout has fired and handleIdleTimeout() is trying to put + // the channel in idle mode because the channel has been inactive. + // - b: At the same time an RPC is made on the channel, and onCallBegin() + // is trying to prevent the channel from going idle. + // - Competing intentions: + // - The channel is in idle mode and there are multiple RPCs starting at + // the same time, all trying to move the channel out of idle. Only one + // of them should succeed in doing so, while the other RPCs should + // piggyback on the first one and be successfully handled. + idleMu sync.RWMutex + actuallyIdle bool + timer *time.Timer +} + +// newIdlenessManager creates a new idleness manager implementation for the +// given idle timeout. +func newIdlenessManager(enforcer idlenessEnforcer, idleTimeout time.Duration) idlenessManager { + if idleTimeout == 0 { + return noopIdlenessManager{} + } + + i := &idlenessManagerImpl{ + enforcer: enforcer, + timeout: int64(idleTimeout), + } + i.timer = timeAfterFunc(idleTimeout, i.handleIdleTimeout) + return i +} + +// resetIdleTimer resets the idle timer to the given duration. This method +// should only be called from the timer callback. +func (i *idlenessManagerImpl) resetIdleTimer(d time.Duration) { + i.idleMu.Lock() + defer i.idleMu.Unlock() + + if i.timer == nil { + // Only close sets timer to nil. We are done. + return + } + + // It is safe to ignore the return value from Reset() because this method is + // only ever called from the timer callback, which means the timer has + // already fired. + i.timer.Reset(d) +} + +// handleIdleTimeout is the timer callback that is invoked upon expiry of the +// configured idle timeout. The channel is considered inactive if there are no +// ongoing calls and no RPC activity since the last time the timer fired. +func (i *idlenessManagerImpl) handleIdleTimeout() { + if i.isClosed() { + return + } + + if atomic.LoadInt32(&i.activeCallsCount) > 0 { + i.resetIdleTimer(time.Duration(i.timeout)) + return + } + + // There has been activity on the channel since we last got here. Reset the + // timer and return. + if atomic.LoadInt32(&i.activeSinceLastTimerCheck) == 1 { + // Set the timer to fire after a duration of idle timeout, calculated + // from the time the most recent RPC completed. + atomic.StoreInt32(&i.activeSinceLastTimerCheck, 0) + i.resetIdleTimer(time.Duration(atomic.LoadInt64(&i.lastCallEndTime) + i.timeout - time.Now().UnixNano())) + return + } + + // This CAS operation is extremely likely to succeed given that there has + // been no activity since the last time we were here. Setting the + // activeCallsCount to -math.MaxInt32 indicates to onCallBegin() that the + // channel is either in idle mode or is trying to get there. + if !atomic.CompareAndSwapInt32(&i.activeCallsCount, 0, -math.MaxInt32) { + // This CAS operation can fail if an RPC started after we checked for + // activity at the top of this method, or one was ongoing from before + // the last time we were here. In both case, reset the timer and return. + i.resetIdleTimer(time.Duration(i.timeout)) + return + } + + // Now that we've set the active calls count to -math.MaxInt32, it's time to + // actually move to idle mode. + if i.tryEnterIdleMode() { + // Successfully entered idle mode. No timer needed until we exit idle. + return + } + + // Failed to enter idle mode due to a concurrent RPC that kept the channel + // active, or because of an error from the channel. Undo the attempt to + // enter idle, and reset the timer to try again later. + atomic.AddInt32(&i.activeCallsCount, math.MaxInt32) + i.resetIdleTimer(time.Duration(i.timeout)) +} + +// tryEnterIdleMode instructs the channel to enter idle mode. But before +// that, it performs a last minute check to ensure that no new RPC has come in, +// making the channel active. +// +// Return value indicates whether or not the channel moved to idle mode. +// +// Holds idleMu which ensures mutual exclusion with exitIdleMode. +func (i *idlenessManagerImpl) tryEnterIdleMode() bool { + i.idleMu.Lock() + defer i.idleMu.Unlock() + + if atomic.LoadInt32(&i.activeCallsCount) != -math.MaxInt32 { + // We raced and lost to a new RPC. Very rare, but stop entering idle. + return false + } + if atomic.LoadInt32(&i.activeSinceLastTimerCheck) == 1 { + // An very short RPC could have come in (and also finished) after we + // checked for calls count and activity in handleIdleTimeout(), but + // before the CAS operation. So, we need to check for activity again. + return false + } + + // No new RPCs have come in since we last set the active calls count value + // -math.MaxInt32 in the timer callback. And since we have the lock, it is + // safe to enter idle mode now. + if err := i.enforcer.enterIdleMode(); err != nil { + logger.Errorf("Failed to enter idle mode: %v", err) + return false + } + + // Successfully entered idle mode. + i.actuallyIdle = true + return true +} + +// onCallBegin is invoked at the start of every RPC. +func (i *idlenessManagerImpl) onCallBegin() error { + if i.isClosed() { + return nil + } + + if atomic.AddInt32(&i.activeCallsCount, 1) > 0 { + // Channel is not idle now. Set the activity bit and allow the call. + atomic.StoreInt32(&i.activeSinceLastTimerCheck, 1) + return nil + } + + // Channel is either in idle mode or is in the process of moving to idle + // mode. Attempt to exit idle mode to allow this RPC. + if err := i.exitIdleMode(); err != nil { + // Undo the increment to calls count, and return an error causing the + // RPC to fail. + atomic.AddInt32(&i.activeCallsCount, -1) + return err + } + + atomic.StoreInt32(&i.activeSinceLastTimerCheck, 1) + return nil +} + +// exitIdleMode instructs the channel to exit idle mode. +// +// Holds idleMu which ensures mutual exclusion with tryEnterIdleMode. +func (i *idlenessManagerImpl) exitIdleMode() error { + i.idleMu.Lock() + defer i.idleMu.Unlock() + + if !i.actuallyIdle { + // This can happen in two scenarios: + // - handleIdleTimeout() set the calls count to -math.MaxInt32 and called + // tryEnterIdleMode(). But before the latter could grab the lock, an RPC + // came in and onCallBegin() noticed that the calls count is negative. + // - Channel is in idle mode, and multiple new RPCs come in at the same + // time, all of them notice a negative calls count in onCallBegin and get + // here. The first one to get the lock would got the channel to exit idle. + // + // Either way, nothing to do here. + return nil + } + + if err := i.enforcer.exitIdleMode(); err != nil { + return fmt.Errorf("channel failed to exit idle mode: %v", err) + } + + // Undo the idle entry process. This also respects any new RPC attempts. + atomic.AddInt32(&i.activeCallsCount, math.MaxInt32) + i.actuallyIdle = false + + // Start a new timer to fire after the configured idle timeout. + i.timer = timeAfterFunc(time.Duration(i.timeout), i.handleIdleTimeout) + return nil +} + +// onCallEnd is invoked at the end of every RPC. +func (i *idlenessManagerImpl) onCallEnd() { + if i.isClosed() { + return + } + + // Record the time at which the most recent call finished. + atomic.StoreInt64(&i.lastCallEndTime, time.Now().UnixNano()) + + // Decrement the active calls count. This count can temporarily go negative + // when the timer callback is in the process of moving the channel to idle + // mode, but one or more RPCs come in and complete before the timer callback + // can get done with the process of moving to idle mode. + atomic.AddInt32(&i.activeCallsCount, -1) +} + +func (i *idlenessManagerImpl) isClosed() bool { + return atomic.LoadInt32(&i.closed) == 1 +} + +func (i *idlenessManagerImpl) close() { + atomic.StoreInt32(&i.closed, 1) + + i.idleMu.Lock() + i.timer.Stop() + i.timer = nil + i.idleMu.Unlock() +} diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go index af03a40d9..755fdebc1 100644 --- a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go +++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go @@ -32,6 +32,9 @@ var grpclogLogger = grpclog.Component("binarylog") // Logger specifies MethodLoggers for method names with a Log call that // takes a context. +// +// This is used in the 1.0 release of gcp/observability, and thus must not be +// deleted or changed. type Logger interface { GetMethodLogger(methodName string) MethodLogger } diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go index 56fcf008d..6c3f63221 100644 --- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go +++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go @@ -49,6 +49,9 @@ func (g *callIDGenerator) reset() { var idGen callIDGenerator // MethodLogger is the sub-logger for each method. +// +// This is used in the 1.0 release of gcp/observability, and thus must not be +// deleted or changed. type MethodLogger interface { Log(context.Context, LogEntryConfig) } @@ -65,6 +68,9 @@ type TruncatingMethodLogger struct { } // NewTruncatingMethodLogger returns a new truncating method logger. +// +// This is used in the 1.0 release of gcp/observability, and thus must not be +// deleted or changed. func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger { return &TruncatingMethodLogger{ headerMaxLen: h, @@ -145,6 +151,9 @@ func (ml *TruncatingMethodLogger) truncateMessage(msgPb *binlogpb.Message) (trun } // LogEntryConfig represents the configuration for binary log entry. +// +// This is used in the 1.0 release of gcp/observability, and thus must not be +// deleted or changed. type LogEntryConfig interface { toProto() *binlogpb.GrpcLogEntry } diff --git a/vendor/google.golang.org/grpc/internal/buffer/unbounded.go b/vendor/google.golang.org/grpc/internal/buffer/unbounded.go index 9f6a0c120..81c2f5fd7 100644 --- a/vendor/google.golang.org/grpc/internal/buffer/unbounded.go +++ b/vendor/google.golang.org/grpc/internal/buffer/unbounded.go @@ -35,6 +35,7 @@ import "sync" // internal/transport/transport.go for an example of this. type Unbounded struct { c chan interface{} + closed bool mu sync.Mutex backlog []interface{} } @@ -47,16 +48,18 @@ func NewUnbounded() *Unbounded { // Put adds t to the unbounded buffer. func (b *Unbounded) Put(t interface{}) { b.mu.Lock() + defer b.mu.Unlock() + if b.closed { + return + } if len(b.backlog) == 0 { select { case b.c <- t: - b.mu.Unlock() return default: } } b.backlog = append(b.backlog, t) - b.mu.Unlock() } // Load sends the earliest buffered data, if any, onto the read channel @@ -64,6 +67,10 @@ func (b *Unbounded) Put(t interface{}) { // value from the read channel. func (b *Unbounded) Load() { b.mu.Lock() + defer b.mu.Unlock() + if b.closed { + return + } if len(b.backlog) > 0 { select { case b.c <- b.backlog[0]: @@ -72,7 +79,6 @@ func (b *Unbounded) Load() { default: } } - b.mu.Unlock() } // Get returns a read channel on which values added to the buffer, via Put(), @@ -80,6 +86,20 @@ func (b *Unbounded) Load() { // // Upon reading a value from this channel, users are expected to call Load() to // send the next buffered value onto the channel if there is any. +// +// If the unbounded buffer is closed, the read channel returned by this method +// is closed. func (b *Unbounded) Get() <-chan interface{} { return b.c } + +// Close closes the unbounded buffer. +func (b *Unbounded) Close() { + b.mu.Lock() + defer b.mu.Unlock() + if b.closed { + return + } + b.closed = true + close(b.c) +} diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 5ba9d94d4..80fd5c7d2 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -36,6 +36,10 @@ var ( // "GRPC_RING_HASH_CAP". This does not override the default bounds // checking which NACKs configs specifying ring sizes > 8*1024*1024 (~8M). RingHashCap = uint64FromEnv("GRPC_RING_HASH_CAP", 4096, 1, 8*1024*1024) + // PickFirstLBConfig is set if we should support configuration of the + // pick_first LB policy, which can be enabled by setting the environment + // variable "GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG" to "true". + PickFirstLBConfig = boolFromEnv("GRPC_EXPERIMENTAL_PICKFIRST_LB_CONFIG", false) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/vendor/google.golang.org/grpc/internal/envconfig/observability.go b/vendor/google.golang.org/grpc/internal/envconfig/observability.go index 821dd0a7c..dd314cfb1 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/observability.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/observability.go @@ -28,9 +28,15 @@ const ( var ( // ObservabilityConfig is the json configuration for the gcp/observability // package specified directly in the envObservabilityConfig env var. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. ObservabilityConfig = os.Getenv(envObservabilityConfig) // ObservabilityConfigFile is the json configuration for the // gcp/observability specified in a file with the location specified in // envObservabilityConfigFile env var. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. ObservabilityConfigFile = os.Getenv(envObservabilityConfigFile) ) diff --git a/vendor/google.golang.org/grpc/internal/envconfig/xds.go b/vendor/google.golang.org/grpc/internal/envconfig/xds.go index 04136882c..02b4b6a1c 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/xds.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/xds.go @@ -61,11 +61,10 @@ var ( // have a brand new API on the server-side and users explicitly need to use // the new API to get security integration on the server. XDSClientSideSecurity = boolFromEnv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", true) - // XDSAggregateAndDNS indicates whether processing of aggregated cluster - // and DNS cluster is enabled, which can be enabled by setting the - // environment variable - // "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" to - // "true". + // XDSAggregateAndDNS indicates whether processing of aggregated cluster and + // DNS cluster is enabled, which can be disabled by setting the environment + // variable "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" + // to "false". XDSAggregateAndDNS = boolFromEnv("GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER", true) // XDSRBAC indicates whether xDS configured RBAC HTTP Filter is enabled, @@ -79,14 +78,18 @@ var ( // XDSFederation indicates whether federation support is enabled, which can // be enabled by setting the environment variable // "GRPC_EXPERIMENTAL_XDS_FEDERATION" to "true". - XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", false) + XDSFederation = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FEDERATION", true) // XDSRLS indicates whether processing of Cluster Specifier plugins and - // support for the RLS CLuster Specifier is enabled, which can be enabled by + // support for the RLS CLuster Specifier is enabled, which can be disabled by // setting the environment variable "GRPC_EXPERIMENTAL_XDS_RLS_LB" to - // "true". - XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", false) + // "false". + XDSRLS = boolFromEnv("GRPC_EXPERIMENTAL_XDS_RLS_LB", true) // C2PResolverTestOnlyTrafficDirectorURI is the TD URI for testing. C2PResolverTestOnlyTrafficDirectorURI = os.Getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI") + // XDSCustomLBPolicy indicates whether Custom LB Policies are enabled, which + // can be disabled by setting the environment variable + // "GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG" to "false". + XDSCustomLBPolicy = boolFromEnv("GRPC_EXPERIMENTAL_XDS_CUSTOM_LB_CONFIG", true) ) diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go index 517ea7064..d08e3e907 100644 --- a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go +++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go @@ -72,3 +72,17 @@ func Uint64() uint64 { defer mu.Unlock() return r.Uint64() } + +// Uint32 implements rand.Uint32 on the grpcrand global source. +func Uint32() uint32 { + mu.Lock() + defer mu.Unlock() + return r.Uint32() +} + +// Shuffle implements rand.Shuffle on the grpcrand global source. +var Shuffle = func(n int, f func(int, int)) { + mu.Lock() + defer mu.Unlock() + r.Shuffle(n, f) +} diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go new file mode 100644 index 000000000..37b8d4117 --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go @@ -0,0 +1,119 @@ +/* + * + * Copyright 2022 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package grpcsync + +import ( + "context" + "sync" + + "google.golang.org/grpc/internal/buffer" +) + +// CallbackSerializer provides a mechanism to schedule callbacks in a +// synchronized manner. It provides a FIFO guarantee on the order of execution +// of scheduled callbacks. New callbacks can be scheduled by invoking the +// Schedule() method. +// +// This type is safe for concurrent access. +type CallbackSerializer struct { + // Done is closed once the serializer is shut down completely, i.e all + // scheduled callbacks are executed and the serializer has deallocated all + // its resources. + Done chan struct{} + + callbacks *buffer.Unbounded + closedMu sync.Mutex + closed bool +} + +// NewCallbackSerializer returns a new CallbackSerializer instance. The provided +// context will be passed to the scheduled callbacks. Users should cancel the +// provided context to shutdown the CallbackSerializer. It is guaranteed that no +// callbacks will be added once this context is canceled, and any pending un-run +// callbacks will be executed before the serializer is shut down. +func NewCallbackSerializer(ctx context.Context) *CallbackSerializer { + t := &CallbackSerializer{ + Done: make(chan struct{}), + callbacks: buffer.NewUnbounded(), + } + go t.run(ctx) + return t +} + +// Schedule adds a callback to be scheduled after existing callbacks are run. +// +// Callbacks are expected to honor the context when performing any blocking +// operations, and should return early when the context is canceled. +// +// Return value indicates if the callback was successfully added to the list of +// callbacks to be executed by the serializer. It is not possible to add +// callbacks once the context passed to NewCallbackSerializer is cancelled. +func (t *CallbackSerializer) Schedule(f func(ctx context.Context)) bool { + t.closedMu.Lock() + defer t.closedMu.Unlock() + + if t.closed { + return false + } + t.callbacks.Put(f) + return true +} + +func (t *CallbackSerializer) run(ctx context.Context) { + var backlog []func(context.Context) + + defer close(t.Done) + for ctx.Err() == nil { + select { + case <-ctx.Done(): + // Do nothing here. Next iteration of the for loop will not happen, + // since ctx.Err() would be non-nil. + case callback, ok := <-t.callbacks.Get(): + if !ok { + return + } + t.callbacks.Load() + callback.(func(ctx context.Context))(ctx) + } + } + + // Fetch pending callbacks if any, and execute them before returning from + // this method and closing t.Done. + t.closedMu.Lock() + t.closed = true + backlog = t.fetchPendingCallbacks() + t.callbacks.Close() + t.closedMu.Unlock() + for _, b := range backlog { + b(ctx) + } +} + +func (t *CallbackSerializer) fetchPendingCallbacks() []func(context.Context) { + var backlog []func(context.Context) + for { + select { + case b := <-t.callbacks.Get(): + backlog = append(backlog, b.(func(context.Context))) + t.callbacks.Load() + default: + return backlog + } + } +} diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go index 836b6a3b3..42ff39c84 100644 --- a/vendor/google.golang.org/grpc/internal/internal.go +++ b/vendor/google.golang.org/grpc/internal/internal.go @@ -60,6 +60,9 @@ var ( GetServerCredentials interface{} // func (*grpc.Server) credentials.TransportCredentials // CanonicalString returns the canonical string of the code defined here: // https://github.com/grpc/grpc/blob/master/doc/statuscodes.md. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. CanonicalString interface{} // func (codes.Code) string // DrainServerTransports initiates a graceful close of existing connections // on a gRPC server accepted on the provided listener address. An @@ -69,20 +72,35 @@ var ( // AddGlobalServerOptions adds an array of ServerOption that will be // effective globally for newly created servers. The priority will be: 1. // user-provided; 2. this method; 3. default values. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. AddGlobalServerOptions interface{} // func(opt ...ServerOption) // ClearGlobalServerOptions clears the array of extra ServerOption. This // method is useful in testing and benchmarking. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. ClearGlobalServerOptions func() // AddGlobalDialOptions adds an array of DialOption that will be effective // globally for newly created client channels. The priority will be: 1. // user-provided; 2. this method; 3. default values. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. AddGlobalDialOptions interface{} // func(opt ...DialOption) // DisableGlobalDialOptions returns a DialOption that prevents the // ClientConn from applying the global DialOptions (set via // AddGlobalDialOptions). + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. DisableGlobalDialOptions interface{} // func() grpc.DialOption // ClearGlobalDialOptions clears the array of extra DialOption. This // method is useful in testing and benchmarking. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. ClearGlobalDialOptions func() // JoinDialOptions combines the dial options passed as arguments into a // single dial option. @@ -93,9 +111,15 @@ var ( // WithBinaryLogger returns a DialOption that specifies the binary logger // for a ClientConn. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. WithBinaryLogger interface{} // func(binarylog.Logger) grpc.DialOption // BinaryLogger returns a ServerOption that can set the binary logger for a // server. + // + // This is used in the 1.0 release of gcp/observability, and thus must not be + // deleted or changed. BinaryLogger interface{} // func(binarylog.Logger) grpc.ServerOption // NewXDSResolverWithConfigForTesting creates a new xds resolver builder using diff --git a/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go b/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go new file mode 100644 index 000000000..11d82afcc --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/serviceconfig/duration.go @@ -0,0 +1,130 @@ +/* + * + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package serviceconfig + +import ( + "encoding/json" + "fmt" + "math" + "strconv" + "strings" + "time" +) + +// Duration defines JSON marshal and unmarshal methods to conform to the +// protobuf JSON spec defined [here]. +// +// [here]: https://protobuf.dev/reference/protobuf/google.protobuf/#duration +type Duration time.Duration + +func (d Duration) String() string { + return fmt.Sprint(time.Duration(d)) +} + +// MarshalJSON converts from d to a JSON string output. +func (d Duration) MarshalJSON() ([]byte, error) { + ns := time.Duration(d).Nanoseconds() + sec := ns / int64(time.Second) + ns = ns % int64(time.Second) + + var sign string + if sec < 0 || ns < 0 { + sign, sec, ns = "-", -1*sec, -1*ns + } + + // Generated output always contains 0, 3, 6, or 9 fractional digits, + // depending on required precision. + str := fmt.Sprintf("%s%d.%09d", sign, sec, ns) + str = strings.TrimSuffix(str, "000") + str = strings.TrimSuffix(str, "000") + str = strings.TrimSuffix(str, ".000") + return []byte(fmt.Sprintf("\"%ss\"", str)), nil +} + +// UnmarshalJSON unmarshals b as a duration JSON string into d. +func (d *Duration) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + if !strings.HasSuffix(s, "s") { + return fmt.Errorf("malformed duration %q: missing seconds unit", s) + } + neg := false + if s[0] == '-' { + neg = true + s = s[1:] + } + ss := strings.SplitN(s[:len(s)-1], ".", 3) + if len(ss) > 2 { + return fmt.Errorf("malformed duration %q: too many decimals", s) + } + // hasDigits is set if either the whole or fractional part of the number is + // present, since both are optional but one is required. + hasDigits := false + var sec, ns int64 + if len(ss[0]) > 0 { + var err error + if sec, err = strconv.ParseInt(ss[0], 10, 64); err != nil { + return fmt.Errorf("malformed duration %q: %v", s, err) + } + // Maximum seconds value per the durationpb spec. + const maxProtoSeconds = 315_576_000_000 + if sec > maxProtoSeconds { + return fmt.Errorf("out of range: %q", s) + } + hasDigits = true + } + if len(ss) == 2 && len(ss[1]) > 0 { + if len(ss[1]) > 9 { + return fmt.Errorf("malformed duration %q: too many digits after decimal", s) + } + var err error + if ns, err = strconv.ParseInt(ss[1], 10, 64); err != nil { + return fmt.Errorf("malformed duration %q: %v", s, err) + } + for i := 9; i > len(ss[1]); i-- { + ns *= 10 + } + hasDigits = true + } + if !hasDigits { + return fmt.Errorf("malformed duration %q: contains no numbers", s) + } + + if neg { + sec *= -1 + ns *= -1 + } + + // Maximum/minimum seconds/nanoseconds representable by Go's time.Duration. + const maxSeconds = math.MaxInt64 / int64(time.Second) + const maxNanosAtMaxSeconds = math.MaxInt64 % int64(time.Second) + const minSeconds = math.MinInt64 / int64(time.Second) + const minNanosAtMinSeconds = math.MinInt64 % int64(time.Second) + + if sec > maxSeconds || (sec == maxSeconds && ns >= maxNanosAtMaxSeconds) { + *d = Duration(math.MaxInt64) + } else if sec < minSeconds || (sec == minSeconds && ns <= minNanosAtMinSeconds) { + *d = Duration(math.MinInt64) + } else { + *d = Duration(sec*int64(time.Second) + ns) + } + return nil +} diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index c343c23a5..be5a9c81e 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -30,6 +30,7 @@ import ( "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/status" ) @@ -488,12 +489,13 @@ type loopyWriter struct { bdpEst *bdpEstimator draining bool conn net.Conn + logger *grpclog.PrefixLogger // Side-specific handlers ssGoAwayHandler func(*goAway) (bool, error) } -func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn) *loopyWriter { +func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn, logger *grpclog.PrefixLogger) *loopyWriter { var buf bytes.Buffer l := &loopyWriter{ side: s, @@ -507,6 +509,7 @@ func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimato hEnc: hpack.NewEncoder(&buf), bdpEst: bdpEst, conn: conn, + logger: logger, } return l } @@ -536,8 +539,8 @@ const minBatchSize = 1000 // left open to allow the I/O error to be encountered by the reader instead. func (l *loopyWriter) run() (err error) { defer func() { - if logger.V(logLevel) { - logger.Infof("transport: loopyWriter exiting with error: %v", err) + if l.logger.V(logLevel) { + l.logger.Infof("loopyWriter exiting with error: %v", err) } if !isIOError(err) { l.framer.writer.Flush() @@ -636,8 +639,8 @@ func (l *loopyWriter) headerHandler(h *headerFrame) error { if l.side == serverSide { str, ok := l.estdStreams[h.streamID] if !ok { - if logger.V(logLevel) { - logger.Warningf("transport: loopy doesn't recognize the stream: %d", h.streamID) + if l.logger.V(logLevel) { + l.logger.Infof("Unrecognized streamID %d in loopyWriter", h.streamID) } return nil } @@ -692,8 +695,8 @@ func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.He l.hBuf.Reset() for _, f := range hf { if err := l.hEnc.WriteField(f); err != nil { - if logger.V(logLevel) { - logger.Warningf("transport: loopyWriter.writeHeader encountered error while encoding headers: %v", err) + if l.logger.V(logLevel) { + l.logger.Warningf("Encountered error while encoding headers: %v", err) } } } diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go index e6626bf96..98f80e3fa 100644 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go @@ -39,6 +39,7 @@ import ( "golang.org/x/net/http2" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" @@ -83,6 +84,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s contentSubtype: contentSubtype, stats: stats, } + st.logger = prefixLoggerForServerHandlerTransport(st) if v := r.Header.Get("grpc-timeout"); v != "" { to, err := decodeTimeout(v) @@ -150,13 +152,14 @@ type serverHandlerTransport struct { // TODO make sure this is consistent across handler_server and http2_server contentSubtype string - stats []stats.Handler + stats []stats.Handler + logger *grpclog.PrefixLogger } func (ht *serverHandlerTransport) Close(err error) { ht.closeOnce.Do(func() { - if logger.V(logLevel) { - logger.Infof("Closing serverHandlerTransport: %v", err) + if ht.logger.V(logLevel) { + ht.logger.Infof("Closing: %v", err) } close(ht.closedCh) }) @@ -450,7 +453,7 @@ func (ht *serverHandlerTransport) IncrMsgSent() {} func (ht *serverHandlerTransport) IncrMsgRecv() {} -func (ht *serverHandlerTransport) Drain() { +func (ht *serverHandlerTransport) Drain(debugData string) { panic("Drain() is not implemented") } diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index 9826feb8c..326bf0848 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -38,6 +38,7 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" icredentials "google.golang.org/grpc/internal/credentials" + "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" imetadata "google.golang.org/grpc/internal/metadata" @@ -145,6 +146,7 @@ type http2Client struct { bufferPool *bufferPool connectionID uint64 + logger *grpclog.PrefixLogger } func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr resolver.Address, useProxy bool, grpcUA string) (net.Conn, error) { @@ -244,7 +246,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts if err := connectCtx.Err(); err != nil { // connectCtx expired before exiting the function. Hard close the connection. if logger.V(logLevel) { - logger.Infof("newClientTransport: aborting due to connectCtx: %v", err) + logger.Infof("Aborting due to connect deadline expiring: %v", err) } conn.Close() } @@ -346,6 +348,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts bufferPool: newBufferPool(), onClose: onClose, } + t.logger = prefixLoggerForClientTransport(t) // Add peer information to the http2client context. t.ctx = peer.NewContext(t.ctx, t.getPeer()) @@ -444,7 +447,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts return nil, err } go func() { - t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn) + t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) t.loopy.run() close(t.writerDone) }() @@ -782,7 +785,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, s.id = h.streamID s.fc = &inFlow{limit: uint32(t.initialWindowSize)} t.mu.Lock() - if t.activeStreams == nil { // Can be niled from Close(). + if t.state == draining || t.activeStreams == nil { // Can be niled from Close(). t.mu.Unlock() return false // Don't create a stream if the transport is already closed. } @@ -859,8 +862,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, } } if transportDrainRequired { - if logger.V(logLevel) { - logger.Infof("transport: t.nextID > MaxStreamID. Draining") + if t.logger.V(logLevel) { + t.logger.Infof("Draining transport: t.nextID > MaxStreamID") } t.GracefulClose() } @@ -952,8 +955,8 @@ func (t *http2Client) Close(err error) { t.mu.Unlock() return } - if logger.V(logLevel) { - logger.Infof("transport: closing: %v", err) + if t.logger.V(logLevel) { + t.logger.Infof("Closing: %v", err) } // Call t.onClose ASAP to prevent the client from attempting to create new // streams. @@ -1009,8 +1012,8 @@ func (t *http2Client) GracefulClose() { t.mu.Unlock() return } - if logger.V(logLevel) { - logger.Infof("transport: GracefulClose called") + if t.logger.V(logLevel) { + t.logger.Infof("GracefulClose called") } t.onClose(GoAwayInvalid) t.state = draining @@ -1174,8 +1177,8 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { } statusCode, ok := http2ErrConvTab[f.ErrCode] if !ok { - if logger.V(logLevel) { - logger.Warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error: %v", f.ErrCode) + if t.logger.V(logLevel) { + t.logger.Infof("Received a RST_STREAM frame with code %q, but found no mapped gRPC status", f.ErrCode) } statusCode = codes.Unknown } @@ -1334,7 +1337,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { // setGoAwayReason sets the value of t.goAwayReason based // on the GoAway frame received. -// It expects a lock on transport's mutext to be held by +// It expects a lock on transport's mutex to be held by // the caller. func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) { t.goAwayReason = GoAwayNoReason diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index 99ae1a737..ec4eef213 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -35,7 +35,9 @@ import ( "github.com/golang/protobuf/proto" "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" + "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" + "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/internal/syscall" "google.golang.org/grpc/codes" @@ -129,6 +131,8 @@ type http2Server struct { // This lock may not be taken if mu is already held. maxStreamMu sync.Mutex maxStreamID uint32 // max stream ID ever seen + + logger *grpclog.PrefixLogger } // NewServerTransport creates a http2 transport with conn and configuration @@ -167,15 +171,10 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, ID: http2.SettingMaxFrameSize, Val: http2MaxFrameLen, }} - // TODO(zhaoq): Have a better way to signal "no limit" because 0 is - // permitted in the HTTP2 spec. - maxStreams := config.MaxStreams - if maxStreams == 0 { - maxStreams = math.MaxUint32 - } else { + if config.MaxStreams != math.MaxUint32 { isettings = append(isettings, http2.Setting{ ID: http2.SettingMaxConcurrentStreams, - Val: maxStreams, + Val: config.MaxStreams, }) } dynamicWindow := true @@ -254,7 +253,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, framer: framer, readerDone: make(chan struct{}), writerDone: make(chan struct{}), - maxStreams: maxStreams, + maxStreams: config.MaxStreams, inTapHandle: config.InTapHandle, fc: &trInFlow{limit: uint32(icwz)}, state: reachable, @@ -267,6 +266,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, czData: new(channelzData), bufferPool: newBufferPool(), } + t.logger = prefixLoggerForServerTransport(t) // Add peer information to the http2server context. t.ctx = peer.NewContext(t.ctx, t.getPeer()) @@ -331,7 +331,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, t.handleSettings(sf) go func() { - t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn) + t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler t.loopy.run() close(t.writerDone) @@ -425,8 +425,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( // "Transports must consider requests containing the Connection header // as malformed." - A41 case "connection": - if logger.V(logLevel) { - logger.Errorf("transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec") + if t.logger.V(logLevel) { + t.logger.Infof("Received a HEADERS frame with a :connection header which makes the request malformed, as per the HTTP/2 spec") } protocolError = true default: @@ -436,7 +436,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( v, err := decodeMetadataHeader(hf.Name, hf.Value) if err != nil { headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err) - logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err) + t.logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err) break } mdata[hf.Name] = append(mdata[hf.Name], v) @@ -450,8 +450,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( // error, this takes precedence over a client not speaking gRPC. if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 { errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"])) - if logger.V(logLevel) { - logger.Errorf("transport: %v", errMsg) + if t.logger.V(logLevel) { + t.logger.Infof("Aborting the stream early: %v", errMsg) } t.controlBuf.put(&earlyAbortStream{ httpStatus: http.StatusBadRequest, @@ -545,9 +545,9 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( } if httpMethod != http.MethodPost { t.mu.Unlock() - errMsg := fmt.Sprintf("http2Server.operateHeaders parsed a :method field: %v which should be POST", httpMethod) - if logger.V(logLevel) { - logger.Infof("transport: %v", errMsg) + errMsg := fmt.Sprintf("Received a HEADERS frame with :method %q which should be POST", httpMethod) + if t.logger.V(logLevel) { + t.logger.Infof("Aborting the stream early: %v", errMsg) } t.controlBuf.put(&earlyAbortStream{ httpStatus: 405, @@ -563,8 +563,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( var err error if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: s.method}); err != nil { t.mu.Unlock() - if logger.V(logLevel) { - logger.Infof("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err) + if t.logger.V(logLevel) { + t.logger.Infof("Aborting the stream early due to InTapHandle failure: %v", err) } stat, ok := status.FromError(err) if !ok { @@ -638,8 +638,8 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context. atomic.StoreInt64(&t.lastRead, time.Now().UnixNano()) if err != nil { if se, ok := err.(http2.StreamError); ok { - if logger.V(logLevel) { - logger.Warningf("transport: http2Server.HandleStreams encountered http2.StreamError: %v", se) + if t.logger.V(logLevel) { + t.logger.Warningf("Encountered http2.StreamError: %v", se) } t.mu.Lock() s := t.activeStreams[se.StreamID] @@ -682,8 +682,8 @@ func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context. case *http2.GoAwayFrame: // TODO: Handle GoAway from the client appropriately. default: - if logger.V(logLevel) { - logger.Errorf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame) + if t.logger.V(logLevel) { + t.logger.Infof("Received unsupported frame type %T", frame) } } } @@ -942,8 +942,8 @@ func (t *http2Server) checkForHeaderListSize(it interface{}) bool { var sz int64 for _, f := range hdrFrame.hf { if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) { - if logger.V(logLevel) { - logger.Errorf("header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize) + if t.logger.V(logLevel) { + t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize) } return false } @@ -1056,7 +1056,7 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error { stBytes, err := proto.Marshal(p) if err != nil { // TODO: return error instead, when callers are able to handle it. - logger.Errorf("transport: failed to marshal rpc status: %v, error: %v", p, err) + t.logger.Errorf("Failed to marshal rpc status: %s, error: %v", pretty.ToJSON(p), err) } else { headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)}) } @@ -1161,18 +1161,18 @@ func (t *http2Server) keepalive() { if val <= 0 { // The connection has been idle for a duration of keepalive.MaxConnectionIdle or more. // Gracefully close the connection. - t.Drain() + t.Drain("max_idle") return } idleTimer.Reset(val) case <-ageTimer.C: - t.Drain() + t.Drain("max_age") ageTimer.Reset(t.kp.MaxConnectionAgeGrace) select { case <-ageTimer.C: // Close the connection after grace period. - if logger.V(logLevel) { - logger.Infof("transport: closing server transport due to maximum connection age.") + if t.logger.V(logLevel) { + t.logger.Infof("Closing server transport due to maximum connection age") } t.controlBuf.put(closeConnection{}) case <-t.done: @@ -1223,8 +1223,8 @@ func (t *http2Server) Close(err error) { t.mu.Unlock() return } - if logger.V(logLevel) { - logger.Infof("transport: closing: %v", err) + if t.logger.V(logLevel) { + t.logger.Infof("Closing: %v", err) } t.state = closing streams := t.activeStreams @@ -1232,8 +1232,8 @@ func (t *http2Server) Close(err error) { t.mu.Unlock() t.controlBuf.finish() close(t.done) - if err := t.conn.Close(); err != nil && logger.V(logLevel) { - logger.Infof("transport: error closing conn during Close: %v", err) + if err := t.conn.Close(); err != nil && t.logger.V(logLevel) { + t.logger.Infof("Error closing underlying net.Conn during Close: %v", err) } channelz.RemoveEntry(t.channelzID) // Cancel all active streams. @@ -1313,14 +1313,14 @@ func (t *http2Server) RemoteAddr() net.Addr { return t.remoteAddr } -func (t *http2Server) Drain() { +func (t *http2Server) Drain(debugData string) { t.mu.Lock() defer t.mu.Unlock() if t.drainEvent != nil { return } t.drainEvent = grpcsync.NewEvent() - t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte{}, headsUp: true}) + t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte(debugData), headsUp: true}) } var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}} @@ -1362,7 +1362,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { // originated before the GoAway reaches the client. // After getting the ack or timer expiration send out another GoAway this // time with an ID of the max stream server intends to process. - if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte{}); err != nil { + if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, g.debugData); err != nil { return false, err } if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil { diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go index 8fcae4f4d..19cbb18f5 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http_util.go +++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go @@ -38,7 +38,6 @@ import ( "golang.org/x/net/http2/hpack" spb "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" "google.golang.org/grpc/status" ) @@ -86,7 +85,6 @@ var ( // 504 Gateway timeout - UNAVAILABLE. http.StatusGatewayTimeout: codes.Unavailable, } - logger = grpclog.Component("transport") ) // isReservedHeader checks whether hdr belongs to HTTP2 headers diff --git a/vendor/google.golang.org/grpc/internal/transport/logging.go b/vendor/google.golang.org/grpc/internal/transport/logging.go new file mode 100644 index 000000000..42ed2b07a --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/transport/logging.go @@ -0,0 +1,40 @@ +/* + * + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package transport + +import ( + "fmt" + + "google.golang.org/grpc/grpclog" + internalgrpclog "google.golang.org/grpc/internal/grpclog" +) + +var logger = grpclog.Component("transport") + +func prefixLoggerForServerTransport(p *http2Server) *internalgrpclog.PrefixLogger { + return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-transport %p] ", p)) +} + +func prefixLoggerForServerHandlerTransport(p *serverHandlerTransport) *internalgrpclog.PrefixLogger { + return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[server-handler-transport %p] ", p)) +} + +func prefixLoggerForClientTransport(p *http2Client) *internalgrpclog.PrefixLogger { + return internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf("[client-transport %p] ", p)) +} diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 1b7d7fabc..aa1c89659 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -726,7 +726,7 @@ type ServerTransport interface { RemoteAddr() net.Addr // Drain notifies the client this ServerTransport stops accepting new RPCs. - Drain() + Drain(debugData string) // IncrMsgSent increments the number of message sent through this transport. IncrMsgSent() diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go index c525dc070..02f975951 100644 --- a/vendor/google.golang.org/grpc/picker_wrapper.go +++ b/vendor/google.golang.org/grpc/picker_wrapper.go @@ -36,6 +36,7 @@ import ( type pickerWrapper struct { mu sync.Mutex done bool + idle bool blockingCh chan struct{} picker balancer.Picker } @@ -47,7 +48,11 @@ func newPickerWrapper() *pickerWrapper { // updatePicker is called by UpdateBalancerState. It unblocks all blocked pick. func (pw *pickerWrapper) updatePicker(p balancer.Picker) { pw.mu.Lock() - if pw.done { + if pw.done || pw.idle { + // There is a small window where a picker update from the LB policy can + // race with the channel going to idle mode. If the picker is idle here, + // it is because the channel asked it to do so, and therefore it is sage + // to ignore the update from the LB policy. pw.mu.Unlock() return } @@ -63,10 +68,8 @@ func (pw *pickerWrapper) updatePicker(p balancer.Picker) { // - wraps the done function in the passed in result to increment the calls // failed or calls succeeded channelz counter before invoking the actual // done function. -func doneChannelzWrapper(acw *acBalancerWrapper, result *balancer.PickResult) { - acw.mu.Lock() - ac := acw.ac - acw.mu.Unlock() +func doneChannelzWrapper(acbw *acBalancerWrapper, result *balancer.PickResult) { + ac := acbw.ac ac.incrCallsStarted() done := result.Done result.Done = func(b balancer.DoneInfo) { @@ -152,14 +155,14 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. return nil, balancer.PickResult{}, status.Error(codes.Unavailable, err.Error()) } - acw, ok := pickResult.SubConn.(*acBalancerWrapper) + acbw, ok := pickResult.SubConn.(*acBalancerWrapper) if !ok { logger.Errorf("subconn returned from pick is type %T, not *acBalancerWrapper", pickResult.SubConn) continue } - if t := acw.getAddrConn().getReadyTransport(); t != nil { + if t := acbw.ac.getReadyTransport(); t != nil { if channelz.IsOn() { - doneChannelzWrapper(acw, &pickResult) + doneChannelzWrapper(acbw, &pickResult) return t, pickResult, nil } return t, pickResult, nil @@ -187,6 +190,25 @@ func (pw *pickerWrapper) close() { close(pw.blockingCh) } +func (pw *pickerWrapper) enterIdleMode() { + pw.mu.Lock() + defer pw.mu.Unlock() + if pw.done { + return + } + pw.idle = true +} + +func (pw *pickerWrapper) exitIdleMode() { + pw.mu.Lock() + defer pw.mu.Unlock() + if pw.done { + return + } + pw.blockingCh = make(chan struct{}) + pw.idle = false +} + // dropError is a wrapper error that indicates the LB policy wishes to drop the // RPC and not retry it. type dropError struct { diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/pickfirst.go index fc91b4d26..abe266b02 100644 --- a/vendor/google.golang.org/grpc/pickfirst.go +++ b/vendor/google.golang.org/grpc/pickfirst.go @@ -19,11 +19,15 @@ package grpc import ( + "encoding/json" "errors" "fmt" "google.golang.org/grpc/balancer" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/internal/envconfig" + "google.golang.org/grpc/internal/grpcrand" + "google.golang.org/grpc/serviceconfig" ) // PickFirstBalancerName is the name of the pick_first balancer. @@ -43,10 +47,28 @@ func (*pickfirstBuilder) Name() string { return PickFirstBalancerName } +type pfConfig struct { + serviceconfig.LoadBalancingConfig `json:"-"` + + // If set to true, instructs the LB policy to shuffle the order of the list + // of addresses received from the name resolver before attempting to + // connect to them. + ShuffleAddressList bool `json:"shuffleAddressList"` +} + +func (*pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { + cfg := &pfConfig{} + if err := json.Unmarshal(js, cfg); err != nil { + return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err) + } + return cfg, nil +} + type pickfirstBalancer struct { state connectivity.State cc balancer.ClientConn subConn balancer.SubConn + cfg *pfConfig } func (b *pickfirstBalancer) ResolverError(err error) { @@ -69,7 +91,8 @@ func (b *pickfirstBalancer) ResolverError(err error) { } func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error { - if len(state.ResolverState.Addresses) == 0 { + addrs := state.ResolverState.Addresses + if len(addrs) == 0 { // The resolver reported an empty address list. Treat it like an error by // calling b.ResolverError. if b.subConn != nil { @@ -82,12 +105,23 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState return balancer.ErrBadResolverState } + if state.BalancerConfig != nil { + cfg, ok := state.BalancerConfig.(*pfConfig) + if !ok { + return fmt.Errorf("pickfirstBalancer: received nil or illegal BalancerConfig (type %T): %v", state.BalancerConfig, state.BalancerConfig) + } + b.cfg = cfg + } + + if envconfig.PickFirstLBConfig && b.cfg != nil && b.cfg.ShuffleAddressList { + grpcrand.Shuffle(len(addrs), func(i, j int) { addrs[i], addrs[j] = addrs[j], addrs[i] }) + } if b.subConn != nil { - b.cc.UpdateAddresses(b.subConn, state.ResolverState.Addresses) + b.cc.UpdateAddresses(b.subConn, addrs) return nil } - subConn, err := b.cc.NewSubConn(state.ResolverState.Addresses, balancer.NewSubConnOptions{}) + subConn, err := b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{}) if err != nil { if logger.V(2) { logger.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err) @@ -119,7 +153,6 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b } return } - b.state = state.ConnectivityState if state.ConnectivityState == connectivity.Shutdown { b.subConn = nil return @@ -132,11 +165,21 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b Picker: &picker{result: balancer.PickResult{SubConn: subConn}}, }) case connectivity.Connecting: + if b.state == connectivity.TransientFailure { + // We stay in TransientFailure until we are Ready. See A62. + return + } b.cc.UpdateState(balancer.State{ ConnectivityState: state.ConnectivityState, Picker: &picker{err: balancer.ErrNoSubConnAvailable}, }) case connectivity.Idle: + if b.state == connectivity.TransientFailure { + // We stay in TransientFailure until we are Ready. Also kick the + // subConn out of Idle into Connecting. See A62. + b.subConn.Connect() + return + } b.cc.UpdateState(balancer.State{ ConnectivityState: state.ConnectivityState, Picker: &idlePicker{subConn: subConn}, @@ -147,6 +190,7 @@ func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state b Picker: &picker{err: state.ConnectionError}, }) } + b.state = state.ConnectivityState } func (b *pickfirstBalancer) Close() { diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go index 6215e5ef2..353c10b69 100644 --- a/vendor/google.golang.org/grpc/resolver/resolver.go +++ b/vendor/google.golang.org/grpc/resolver/resolver.go @@ -22,13 +22,13 @@ package resolver import ( "context" + "fmt" "net" "net/url" "strings" "google.golang.org/grpc/attributes" "google.golang.org/grpc/credentials" - "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/serviceconfig" ) @@ -124,7 +124,7 @@ type Address struct { Attributes *attributes.Attributes // BalancerAttributes contains arbitrary data about this address intended - // for consumption by the LB policy. These attribes do not affect SubConn + // for consumption by the LB policy. These attributes do not affect SubConn // creation, connection establishment, handshaking, etc. BalancerAttributes *attributes.Attributes @@ -151,7 +151,17 @@ func (a Address) Equal(o Address) bool { // String returns JSON formatted string representation of the address. func (a Address) String() string { - return pretty.ToJSON(a) + var sb strings.Builder + sb.WriteString(fmt.Sprintf("{Addr: %q, ", a.Addr)) + sb.WriteString(fmt.Sprintf("ServerName: %q, ", a.ServerName)) + if a.Attributes != nil { + sb.WriteString(fmt.Sprintf("Attributes: %v, ", a.Attributes.String())) + } + if a.BalancerAttributes != nil { + sb.WriteString(fmt.Sprintf("BalancerAttributes: %v", a.BalancerAttributes.String())) + } + sb.WriteString("}") + return sb.String() } // BuildOptions includes additional information for the builder to create diff --git a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go index 05a9d4e0b..b408b3688 100644 --- a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go +++ b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go @@ -19,11 +19,11 @@ package grpc import ( + "context" "strings" "sync" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/pretty" @@ -31,129 +31,192 @@ import ( "google.golang.org/grpc/serviceconfig" ) +// resolverStateUpdater wraps the single method used by ccResolverWrapper to +// report a state update from the actual resolver implementation. +type resolverStateUpdater interface { + updateResolverState(s resolver.State, err error) error +} + // ccResolverWrapper is a wrapper on top of cc for resolvers. // It implements resolver.ClientConn interface. type ccResolverWrapper struct { - cc *ClientConn - resolverMu sync.Mutex - resolver resolver.Resolver - done *grpcsync.Event - curState resolver.State + // The following fields are initialized when the wrapper is created and are + // read-only afterwards, and therefore can be accessed without a mutex. + cc resolverStateUpdater + channelzID *channelz.Identifier + ignoreServiceConfig bool + opts ccResolverWrapperOpts + serializer *grpcsync.CallbackSerializer // To serialize all incoming calls. + serializerCancel context.CancelFunc // To close the serializer, accessed only from close(). + + // All incoming (resolver --> gRPC) calls are guaranteed to execute in a + // mutually exclusive manner as they are scheduled on the serializer. + // Fields accessed *only* in these serializer callbacks, can therefore be + // accessed without a mutex. + curState resolver.State + + // mu guards access to the below fields. + mu sync.Mutex + closed bool + resolver resolver.Resolver // Accessed only from outgoing calls. +} - incomingMu sync.Mutex // Synchronizes all the incoming calls. +// ccResolverWrapperOpts wraps the arguments to be passed when creating a new +// ccResolverWrapper. +type ccResolverWrapperOpts struct { + target resolver.Target // User specified dial target to resolve. + builder resolver.Builder // Resolver builder to use. + bOpts resolver.BuildOptions // Resolver build options to use. + channelzID *channelz.Identifier // Channelz identifier for the channel. } // newCCResolverWrapper uses the resolver.Builder to build a Resolver and // returns a ccResolverWrapper object which wraps the newly built resolver. -func newCCResolverWrapper(cc *ClientConn, rb resolver.Builder) (*ccResolverWrapper, error) { +func newCCResolverWrapper(cc resolverStateUpdater, opts ccResolverWrapperOpts) (*ccResolverWrapper, error) { + ctx, cancel := context.WithCancel(context.Background()) ccr := &ccResolverWrapper{ - cc: cc, - done: grpcsync.NewEvent(), - } - - var credsClone credentials.TransportCredentials - if creds := cc.dopts.copts.TransportCredentials; creds != nil { - credsClone = creds.Clone() - } - rbo := resolver.BuildOptions{ - DisableServiceConfig: cc.dopts.disableServiceConfig, - DialCreds: credsClone, - CredsBundle: cc.dopts.copts.CredsBundle, - Dialer: cc.dopts.copts.Dialer, - } - - var err error - // We need to hold the lock here while we assign to the ccr.resolver field - // to guard against a data race caused by the following code path, - // rb.Build-->ccr.ReportError-->ccr.poll-->ccr.resolveNow, would end up - // accessing ccr.resolver which is being assigned here. - ccr.resolverMu.Lock() - defer ccr.resolverMu.Unlock() - ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, rbo) + cc: cc, + channelzID: opts.channelzID, + ignoreServiceConfig: opts.bOpts.DisableServiceConfig, + opts: opts, + serializer: grpcsync.NewCallbackSerializer(ctx), + serializerCancel: cancel, + } + + // Cannot hold the lock at build time because the resolver can send an + // update or error inline and these incoming calls grab the lock to schedule + // a callback in the serializer. + r, err := opts.builder.Build(opts.target, ccr, opts.bOpts) if err != nil { + cancel() return nil, err } + + // Any error reported by the resolver at build time that leads to a + // re-resolution request from the balancer is dropped by grpc until we + // return from this function. So, we don't have to handle pending resolveNow + // requests here. + ccr.mu.Lock() + ccr.resolver = r + ccr.mu.Unlock() + return ccr, nil } func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) { - ccr.resolverMu.Lock() - if !ccr.done.HasFired() { - ccr.resolver.ResolveNow(o) + ccr.mu.Lock() + defer ccr.mu.Unlock() + + // ccr.resolver field is set only after the call to Build() returns. But in + // the process of building, the resolver may send an error update which when + // propagated to the balancer may result in a re-resolution request. + if ccr.closed || ccr.resolver == nil { + return } - ccr.resolverMu.Unlock() + ccr.resolver.ResolveNow(o) } func (ccr *ccResolverWrapper) close() { - ccr.resolverMu.Lock() - ccr.resolver.Close() - ccr.done.Fire() - ccr.resolverMu.Unlock() + ccr.mu.Lock() + if ccr.closed { + ccr.mu.Unlock() + return + } + + channelz.Info(logger, ccr.channelzID, "Closing the name resolver") + + // Close the serializer to ensure that no more calls from the resolver are + // handled, before actually closing the resolver. + ccr.serializerCancel() + ccr.closed = true + r := ccr.resolver + ccr.mu.Unlock() + + // Give enqueued callbacks a chance to finish. + <-ccr.serializer.Done + + // Spawn a goroutine to close the resolver (since it may block trying to + // cleanup all allocated resources) and return early. + go r.Close() +} + +// serializerScheduleLocked is a convenience method to schedule a function to be +// run on the serializer while holding ccr.mu. +func (ccr *ccResolverWrapper) serializerScheduleLocked(f func(context.Context)) { + ccr.mu.Lock() + ccr.serializer.Schedule(f) + ccr.mu.Unlock() } +// UpdateState is called by resolver implementations to report new state to gRPC +// which includes addresses and service config. func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error { - ccr.incomingMu.Lock() - defer ccr.incomingMu.Unlock() - if ccr.done.HasFired() { + errCh := make(chan error, 1) + ok := ccr.serializer.Schedule(func(context.Context) { + ccr.addChannelzTraceEvent(s) + ccr.curState = s + if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState { + errCh <- balancer.ErrBadResolverState + return + } + errCh <- nil + }) + if !ok { + // The only time when Schedule() fail to add the callback to the + // serializer is when the serializer is closed, and this happens only + // when the resolver wrapper is closed. return nil } - ccr.addChannelzTraceEvent(s) - ccr.curState = s - if err := ccr.cc.updateResolverState(ccr.curState, nil); err == balancer.ErrBadResolverState { - return balancer.ErrBadResolverState - } - return nil + return <-errCh } +// ReportError is called by resolver implementations to report errors +// encountered during name resolution to gRPC. func (ccr *ccResolverWrapper) ReportError(err error) { - ccr.incomingMu.Lock() - defer ccr.incomingMu.Unlock() - if ccr.done.HasFired() { - return - } - channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: reporting error to cc: %v", err) - ccr.cc.updateResolverState(resolver.State{}, err) + ccr.serializerScheduleLocked(func(_ context.Context) { + channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: reporting error to cc: %v", err) + ccr.cc.updateResolverState(resolver.State{}, err) + }) } -// NewAddress is called by the resolver implementation to send addresses to gRPC. +// NewAddress is called by the resolver implementation to send addresses to +// gRPC. func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) { - ccr.incomingMu.Lock() - defer ccr.incomingMu.Unlock() - if ccr.done.HasFired() { - return - } - ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig}) - ccr.curState.Addresses = addrs - ccr.cc.updateResolverState(ccr.curState, nil) + ccr.serializerScheduleLocked(func(_ context.Context) { + ccr.addChannelzTraceEvent(resolver.State{Addresses: addrs, ServiceConfig: ccr.curState.ServiceConfig}) + ccr.curState.Addresses = addrs + ccr.cc.updateResolverState(ccr.curState, nil) + }) } // NewServiceConfig is called by the resolver implementation to send service // configs to gRPC. func (ccr *ccResolverWrapper) NewServiceConfig(sc string) { - ccr.incomingMu.Lock() - defer ccr.incomingMu.Unlock() - if ccr.done.HasFired() { - return - } - channelz.Infof(logger, ccr.cc.channelzID, "ccResolverWrapper: got new service config: %s", sc) - if ccr.cc.dopts.disableServiceConfig { - channelz.Info(logger, ccr.cc.channelzID, "Service config lookups disabled; ignoring config") - return - } - scpr := parseServiceConfig(sc) - if scpr.Err != nil { - channelz.Warningf(logger, ccr.cc.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err) - return - } - ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr}) - ccr.curState.ServiceConfig = scpr - ccr.cc.updateResolverState(ccr.curState, nil) + ccr.serializerScheduleLocked(func(_ context.Context) { + channelz.Infof(logger, ccr.channelzID, "ccResolverWrapper: got new service config: %s", sc) + if ccr.ignoreServiceConfig { + channelz.Info(logger, ccr.channelzID, "Service config lookups disabled; ignoring config") + return + } + scpr := parseServiceConfig(sc) + if scpr.Err != nil { + channelz.Warningf(logger, ccr.channelzID, "ccResolverWrapper: error parsing service config: %v", scpr.Err) + return + } + ccr.addChannelzTraceEvent(resolver.State{Addresses: ccr.curState.Addresses, ServiceConfig: scpr}) + ccr.curState.ServiceConfig = scpr + ccr.cc.updateResolverState(ccr.curState, nil) + }) } +// ParseServiceConfig is called by resolver implementations to parse a JSON +// representation of the service config. func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult { return parseServiceConfig(scJSON) } +// addChannelzTraceEvent adds a channelz trace event containing the new +// state received from resolver implementations. func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) { var updates []string var oldSC, newSC *ServiceConfig @@ -172,5 +235,5 @@ func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) { } else if len(ccr.curState.Addresses) == 0 && len(s.Addresses) > 0 { updates = append(updates, "resolver returned new addresses") } - channelz.Infof(logger, ccr.cc.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; ")) + channelz.Infof(logger, ccr.channelzID, "Resolver state updated: %s (%v)", pretty.ToJSON(s), strings.Join(updates, "; ")) } diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index 087b9ad7c..8869cc906 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -43,7 +43,6 @@ import ( "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/channelz" - "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/transport" @@ -116,12 +115,6 @@ type serviceInfo struct { mdata interface{} } -type serverWorkerData struct { - st transport.ServerTransport - wg *sync.WaitGroup - stream *transport.Stream -} - // Server is a gRPC server to serve RPC requests. type Server struct { opts serverOptions @@ -146,7 +139,7 @@ type Server struct { channelzID *channelz.Identifier czData *channelzData - serverWorkerChannels []chan *serverWorkerData + serverWorkerChannel chan func() } type serverOptions struct { @@ -178,6 +171,7 @@ type serverOptions struct { } var defaultServerOptions = serverOptions{ + maxConcurrentStreams: math.MaxUint32, maxReceiveMessageSize: defaultServerMaxReceiveMessageSize, maxSendMessageSize: defaultServerMaxSendMessageSize, connectionTimeout: 120 * time.Second, @@ -388,6 +382,9 @@ func MaxSendMsgSize(m int) ServerOption { // MaxConcurrentStreams returns a ServerOption that will apply a limit on the number // of concurrent streams to each ServerTransport. func MaxConcurrentStreams(n uint32) ServerOption { + if n == 0 { + n = math.MaxUint32 + } return newFuncServerOption(func(o *serverOptions) { o.maxConcurrentStreams = n }) @@ -561,40 +558,33 @@ func NumStreamWorkers(numServerWorkers uint32) ServerOption { const serverWorkerResetThreshold = 1 << 16 // serverWorkers blocks on a *transport.Stream channel forever and waits for -// data to be fed by serveStreams. This allows different requests to be +// data to be fed by serveStreams. This allows multiple requests to be // processed by the same goroutine, removing the need for expensive stack // re-allocations (see the runtime.morestack problem [1]). // // [1] https://github.com/golang/go/issues/18138 -func (s *Server) serverWorker(ch chan *serverWorkerData) { - // To make sure all server workers don't reset at the same time, choose a - // random number of iterations before resetting. - threshold := serverWorkerResetThreshold + grpcrand.Intn(serverWorkerResetThreshold) - for completed := 0; completed < threshold; completed++ { - data, ok := <-ch +func (s *Server) serverWorker() { + for completed := 0; completed < serverWorkerResetThreshold; completed++ { + f, ok := <-s.serverWorkerChannel if !ok { return } - s.handleStream(data.st, data.stream, s.traceInfo(data.st, data.stream)) - data.wg.Done() + f() } - go s.serverWorker(ch) + go s.serverWorker() } -// initServerWorkers creates worker goroutines and channels to process incoming +// initServerWorkers creates worker goroutines and a channel to process incoming // connections to reduce the time spent overall on runtime.morestack. func (s *Server) initServerWorkers() { - s.serverWorkerChannels = make([]chan *serverWorkerData, s.opts.numServerWorkers) + s.serverWorkerChannel = make(chan func()) for i := uint32(0); i < s.opts.numServerWorkers; i++ { - s.serverWorkerChannels[i] = make(chan *serverWorkerData) - go s.serverWorker(s.serverWorkerChannels[i]) + go s.serverWorker() } } func (s *Server) stopServerWorkers() { - for i := uint32(0); i < s.opts.numServerWorkers; i++ { - close(s.serverWorkerChannels[i]) - } + close(s.serverWorkerChannel) } // NewServer creates a gRPC server which has no service registered and has not @@ -898,7 +888,7 @@ func (s *Server) drainServerTransports(addr string) { s.mu.Lock() conns := s.conns[addr] for st := range conns { - st.Drain() + st.Drain("") } s.mu.Unlock() } @@ -946,26 +936,26 @@ func (s *Server) serveStreams(st transport.ServerTransport) { defer st.Close(errors.New("finished serving streams for the server transport")) var wg sync.WaitGroup - var roundRobinCounter uint32 + streamQuota := newHandlerQuota(s.opts.maxConcurrentStreams) st.HandleStreams(func(stream *transport.Stream) { wg.Add(1) + + streamQuota.acquire() + f := func() { + defer streamQuota.release() + defer wg.Done() + s.handleStream(st, stream, s.traceInfo(st, stream)) + } + if s.opts.numServerWorkers > 0 { - data := &serverWorkerData{st: st, wg: &wg, stream: stream} select { - case s.serverWorkerChannels[atomic.AddUint32(&roundRobinCounter, 1)%s.opts.numServerWorkers] <- data: + case s.serverWorkerChannel <- f: + return default: // If all stream workers are busy, fallback to the default code path. - go func() { - s.handleStream(st, stream, s.traceInfo(st, stream)) - wg.Done() - }() } - } else { - go func() { - defer wg.Done() - s.handleStream(st, stream, s.traceInfo(st, stream)) - }() } + go f() }, func(ctx context.Context, method string) context.Context { if !EnableTracing { return ctx @@ -1054,7 +1044,7 @@ func (s *Server) addConn(addr string, st transport.ServerTransport) bool { if s.drain { // Transport added after we drained our existing conns: drain it // immediately. - st.Drain() + st.Drain("") } if s.conns[addr] == nil { @@ -1864,7 +1854,7 @@ func (s *Server) GracefulStop() { if !s.drain { for _, conns := range s.conns { for st := range conns { - st.Drain() + st.Drain("graceful_stop") } } s.drain = true @@ -2060,3 +2050,32 @@ func validateSendCompressor(name, clientCompressors string) error { } return fmt.Errorf("client does not support compressor %q", name) } + +// atomicSemaphore implements a blocking, counting semaphore. acquire should be +// called synchronously; release may be called asynchronously. +type atomicSemaphore struct { + n int64 + wait chan struct{} +} + +func (q *atomicSemaphore) acquire() { + if atomic.AddInt64(&q.n, -1) < 0 { + // We ran out of quota. Block until a release happens. + <-q.wait + } +} + +func (q *atomicSemaphore) release() { + // N.B. the "<= 0" check below should allow for this to work with multiple + // concurrent calls to acquire, but also note that with synchronous calls to + // acquire, as our system does, n will never be less than -1. There are + // fairness issues (queuing) to consider if this was to be generalized. + if atomic.AddInt64(&q.n, 1) <= 0 { + // An acquire was waiting on us. Unblock it. + q.wait <- struct{}{} + } +} + +func newHandlerQuota(n uint32) *atomicSemaphore { + return &atomicSemaphore{n: int64(n), wait: make(chan struct{}, 1)} +} diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go index f22acace4..0df11fc09 100644 --- a/vendor/google.golang.org/grpc/service_config.go +++ b/vendor/google.golang.org/grpc/service_config.go @@ -23,8 +23,6 @@ import ( "errors" "fmt" "reflect" - "strconv" - "strings" "time" "google.golang.org/grpc/codes" @@ -106,8 +104,8 @@ type healthCheckConfig struct { type jsonRetryPolicy struct { MaxAttempts int - InitialBackoff string - MaxBackoff string + InitialBackoff internalserviceconfig.Duration + MaxBackoff internalserviceconfig.Duration BackoffMultiplier float64 RetryableStatusCodes []codes.Code } @@ -129,50 +127,6 @@ type retryThrottlingPolicy struct { TokenRatio float64 } -func parseDuration(s *string) (*time.Duration, error) { - if s == nil { - return nil, nil - } - if !strings.HasSuffix(*s, "s") { - return nil, fmt.Errorf("malformed duration %q", *s) - } - ss := strings.SplitN((*s)[:len(*s)-1], ".", 3) - if len(ss) > 2 { - return nil, fmt.Errorf("malformed duration %q", *s) - } - // hasDigits is set if either the whole or fractional part of the number is - // present, since both are optional but one is required. - hasDigits := false - var d time.Duration - if len(ss[0]) > 0 { - i, err := strconv.ParseInt(ss[0], 10, 32) - if err != nil { - return nil, fmt.Errorf("malformed duration %q: %v", *s, err) - } - d = time.Duration(i) * time.Second - hasDigits = true - } - if len(ss) == 2 && len(ss[1]) > 0 { - if len(ss[1]) > 9 { - return nil, fmt.Errorf("malformed duration %q", *s) - } - f, err := strconv.ParseInt(ss[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("malformed duration %q: %v", *s, err) - } - for i := 9; i > len(ss[1]); i-- { - f *= 10 - } - d += time.Duration(f) - hasDigits = true - } - if !hasDigits { - return nil, fmt.Errorf("malformed duration %q", *s) - } - - return &d, nil -} - type jsonName struct { Service string Method string @@ -201,7 +155,7 @@ func (j jsonName) generatePath() (string, error) { type jsonMC struct { Name *[]jsonName WaitForReady *bool - Timeout *string + Timeout *internalserviceconfig.Duration MaxRequestMessageBytes *int64 MaxResponseMessageBytes *int64 RetryPolicy *jsonRetryPolicy @@ -252,15 +206,10 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { if m.Name == nil { continue } - d, err := parseDuration(m.Timeout) - if err != nil { - logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) - return &serviceconfig.ParseResult{Err: err} - } mc := MethodConfig{ WaitForReady: m.WaitForReady, - Timeout: d, + Timeout: (*time.Duration)(m.Timeout), } if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil { logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) @@ -312,18 +261,10 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol if jrp == nil { return nil, nil } - ib, err := parseDuration(&jrp.InitialBackoff) - if err != nil { - return nil, err - } - mb, err := parseDuration(&jrp.MaxBackoff) - if err != nil { - return nil, err - } if jrp.MaxAttempts <= 1 || - *ib <= 0 || - *mb <= 0 || + jrp.InitialBackoff <= 0 || + jrp.MaxBackoff <= 0 || jrp.BackoffMultiplier <= 0 || len(jrp.RetryableStatusCodes) == 0 { logger.Warningf("grpc: ignoring retry policy %v due to illegal configuration", jrp) @@ -332,8 +273,8 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol rp := &internalserviceconfig.RetryPolicy{ MaxAttempts: jrp.MaxAttempts, - InitialBackoff: *ib, - MaxBackoff: *mb, + InitialBackoff: time.Duration(jrp.InitialBackoff), + MaxBackoff: time.Duration(jrp.MaxBackoff), BackoffMultiplier: jrp.BackoffMultiplier, RetryableStatusCodes: make(map[codes.Code]bool), } diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go index 623be39f2..bcf2e4d81 100644 --- a/vendor/google.golang.org/grpc/status/status.go +++ b/vendor/google.golang.org/grpc/status/status.go @@ -77,9 +77,18 @@ func FromProto(s *spb.Status) *Status { // FromError returns a Status representation of err. // // - If err was produced by this package or implements the method `GRPCStatus() -// *Status`, the appropriate Status is returned. +// *Status` and `GRPCStatus()` does not return nil, or if err wraps a type +// satisfying this, the Status from `GRPCStatus()` is returned. For wrapped +// errors, the message returned contains the entire err.Error() text and not +// just the wrapped status. In that case, ok is true. // -// - If err is nil, a Status is returned with codes.OK and no message. +// - If err is nil, a Status is returned with codes.OK and no message, and ok +// is true. +// +// - If err implements the method `GRPCStatus() *Status` and `GRPCStatus()` +// returns nil (which maps to Codes.OK), or if err wraps a type +// satisfying this, a Status is returned with codes.Unknown and err's +// Error() message, and ok is false. // // - Otherwise, err is an error not compatible with this package. In this // case, a Status is returned with codes.Unknown and err's Error() message, @@ -88,10 +97,29 @@ func FromError(err error) (s *Status, ok bool) { if err == nil { return nil, true } - if se, ok := err.(interface { - GRPCStatus() *Status - }); ok { - return se.GRPCStatus(), true + type grpcstatus interface{ GRPCStatus() *Status } + if gs, ok := err.(grpcstatus); ok { + if gs.GRPCStatus() == nil { + // Error has status nil, which maps to codes.OK. There + // is no sensible behavior for this, so we turn it into + // an error with codes.Unknown and discard the existing + // status. + return New(codes.Unknown, err.Error()), false + } + return gs.GRPCStatus(), true + } + var gs grpcstatus + if errors.As(err, &gs) { + if gs.GRPCStatus() == nil { + // Error wraps an error that has status nil, which maps + // to codes.OK. There is no sensible behavior for this, + // so we turn it into an error with codes.Unknown and + // discard the existing status. + return New(codes.Unknown, err.Error()), false + } + p := gs.GRPCStatus().Proto() + p.Message = err.Error() + return status.FromProto(p), true } return New(codes.Unknown, err.Error()), false } @@ -103,19 +131,16 @@ func Convert(err error) *Status { return s } -// Code returns the Code of the error if it is a Status error, codes.OK if err -// is nil, or codes.Unknown otherwise. +// Code returns the Code of the error if it is a Status error or if it wraps a +// Status error. If that is not the case, it returns codes.OK if err is nil, or +// codes.Unknown otherwise. func Code(err error) codes.Code { // Don't use FromError to avoid allocation of OK status. if err == nil { return codes.OK } - if se, ok := err.(interface { - GRPCStatus() *Status - }); ok { - return se.GRPCStatus().Code() - } - return codes.Unknown + + return Convert(err).Code() } // FromContextError converts a context error or wrapped context error into a diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index d1226a412..10092685b 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -123,6 +123,9 @@ type ClientStream interface { // calling RecvMsg on the same stream at the same time, but it is not safe // to call SendMsg on the same stream in different goroutines. It is also // not safe to call CloseSend concurrently with SendMsg. + // + // It is not safe to modify the message after calling SendMsg. Tracing + // libraries and stats handlers may use the message lazily. SendMsg(m interface{}) error // RecvMsg blocks until it receives a message into m or the stream is // done. It returns io.EOF when the stream completes successfully. On @@ -152,6 +155,11 @@ type ClientStream interface { // If none of the above happen, a goroutine and a context will be leaked, and grpc // will not call the optionally-configured stats handler with a stats.End message. func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) { + if err := cc.idlenessMgr.onCallBegin(); err != nil { + return nil, err + } + defer cc.idlenessMgr.onCallEnd() + // allow interceptor to see all applicable call options, which means those // configured as defaults from dial option as well as per-call options opts = combine(cc.dopts.callOptions, opts) @@ -469,7 +477,7 @@ func (a *csAttempt) newStream() error { // It is safe to overwrite the csAttempt's context here, since all state // maintained in it are local to the attempt. When the attempt has to be // retried, a new instance of csAttempt will be created. - if a.pickResult.Metatada != nil { + if a.pickResult.Metadata != nil { // We currently do not have a function it the metadata package which // merges given metadata with existing metadata in a context. Existing // function `AppendToOutgoingContext()` takes a variadic argument of key @@ -479,7 +487,7 @@ func (a *csAttempt) newStream() error { // in a form passable to AppendToOutgoingContext(), or create a version // of AppendToOutgoingContext() that accepts a metadata.MD. md, _ := metadata.FromOutgoingContext(a.ctx) - md = metadata.Join(md, a.pickResult.Metatada) + md = metadata.Join(md, a.pickResult.Metadata) a.ctx = metadata.NewOutgoingContext(a.ctx, md) } @@ -1265,14 +1273,19 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin as.p = &parser{r: s} ac.incrCallsStarted() if desc != unaryStreamDesc { - // Listen on cc and stream contexts to cleanup when the user closes the - // ClientConn or cancels the stream context. In all other cases, an error - // should already be injected into the recv buffer by the transport, which - // the client will eventually receive, and then we will cancel the stream's - // context in clientStream.finish. + // Listen on stream context to cleanup when the stream context is + // canceled. Also listen for the addrConn's context in case the + // addrConn is closed or reconnects to a different address. In all + // other cases, an error should already be injected into the recv + // buffer by the transport, which the client will eventually receive, + // and then we will cancel the stream's context in + // addrConnStream.finish. go func() { + ac.mu.Lock() + acCtx := ac.ctx + ac.mu.Unlock() select { - case <-ac.ctx.Done(): + case <-acCtx.Done(): as.finish(status.Error(codes.Canceled, "grpc: the SubConn is closing")) case <-ctx.Done(): as.finish(toRPCErr(ctx.Err())) diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 3c6e3c911..3cc754062 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.54.0" +const Version = "1.56.3" diff --git a/vendor/modules.txt b/vendor/modules.txt index 7ac34b8ba..a7692a179 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -166,9 +166,11 @@ github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/proto github.com/gogo/protobuf/protoc-gen-gogo/descriptor github.com/gogo/protobuf/sortkeys -# github.com/golang/glog v1.0.0 -## explicit; go 1.11 +# github.com/golang/glog v1.1.0 +## explicit; go 1.18 github.com/golang/glog +github.com/golang/glog/internal/logsink +github.com/golang/glog/internal/stackdump # github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da ## explicit github.com/golang/groupcache/lru @@ -597,7 +599,7 @@ google.golang.org/appengine/urlfetch # google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 ## explicit; go 1.19 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.54.0 +# google.golang.org/grpc v1.56.3 ## explicit; go 1.17 google.golang.org/grpc google.golang.org/grpc/attributes From 9d789d7f61937bbf5fdc300c9e0d92414ddc166c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:24:00 +0000 Subject: [PATCH 25/61] Bump golang.org/x/crypto from 0.14.0 to 0.17.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 8 +- go.sum | 16 ++-- .../golang.org/x/sys/execabs/execabs_go118.go | 1 - .../golang.org/x/sys/execabs/execabs_go119.go | 1 - .../golang.org/x/sys/plan9/pwd_go15_plan9.go | 1 - vendor/golang.org/x/sys/plan9/pwd_plan9.go | 1 - vendor/golang.org/x/sys/plan9/race.go | 1 - vendor/golang.org/x/sys/plan9/race0.go | 1 - vendor/golang.org/x/sys/plan9/str.go | 1 - vendor/golang.org/x/sys/plan9/syscall.go | 1 - .../x/sys/plan9/zsyscall_plan9_386.go | 1 - .../x/sys/plan9/zsyscall_plan9_amd64.go | 1 - .../x/sys/plan9/zsyscall_plan9_arm.go | 1 - vendor/golang.org/x/sys/unix/aliases.go | 2 - vendor/golang.org/x/sys/unix/asm_aix_ppc64.s | 1 - vendor/golang.org/x/sys/unix/asm_bsd_386.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_amd64.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_arm.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_arm64.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s | 2 - .../golang.org/x/sys/unix/asm_bsd_riscv64.s | 2 - vendor/golang.org/x/sys/unix/asm_linux_386.s | 1 - .../golang.org/x/sys/unix/asm_linux_amd64.s | 1 - vendor/golang.org/x/sys/unix/asm_linux_arm.s | 1 - .../golang.org/x/sys/unix/asm_linux_arm64.s | 3 - .../golang.org/x/sys/unix/asm_linux_loong64.s | 3 - .../golang.org/x/sys/unix/asm_linux_mips64x.s | 3 - .../golang.org/x/sys/unix/asm_linux_mipsx.s | 3 - .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 3 - .../golang.org/x/sys/unix/asm_linux_riscv64.s | 2 - .../golang.org/x/sys/unix/asm_linux_s390x.s | 3 - .../x/sys/unix/asm_openbsd_mips64.s | 1 - .../golang.org/x/sys/unix/asm_solaris_amd64.s | 1 - vendor/golang.org/x/sys/unix/asm_zos_s390x.s | 3 - vendor/golang.org/x/sys/unix/cap_freebsd.go | 1 - vendor/golang.org/x/sys/unix/constants.go | 1 - vendor/golang.org/x/sys/unix/dev_aix_ppc.go | 1 - vendor/golang.org/x/sys/unix/dev_aix_ppc64.go | 1 - vendor/golang.org/x/sys/unix/dev_zos.go | 1 - vendor/golang.org/x/sys/unix/dirent.go | 1 - vendor/golang.org/x/sys/unix/endian_big.go | 1 - vendor/golang.org/x/sys/unix/endian_little.go | 1 - vendor/golang.org/x/sys/unix/env_unix.go | 1 - vendor/golang.org/x/sys/unix/epoll_zos.go | 1 - vendor/golang.org/x/sys/unix/fcntl.go | 3 +- .../x/sys/unix/fcntl_linux_32bit.go | 1 - vendor/golang.org/x/sys/unix/fdset.go | 1 - vendor/golang.org/x/sys/unix/fstatfs_zos.go | 1 - vendor/golang.org/x/sys/unix/gccgo.go | 1 - vendor/golang.org/x/sys/unix/gccgo_c.c | 1 - .../x/sys/unix/gccgo_linux_amd64.go | 1 - vendor/golang.org/x/sys/unix/ifreq_linux.go | 1 - vendor/golang.org/x/sys/unix/ioctl_linux.go | 5 + vendor/golang.org/x/sys/unix/ioctl_signed.go | 1 - .../golang.org/x/sys/unix/ioctl_unsigned.go | 1 - vendor/golang.org/x/sys/unix/ioctl_zos.go | 1 - vendor/golang.org/x/sys/unix/mkerrors.sh | 4 +- vendor/golang.org/x/sys/unix/mmap_nomremap.go | 1 - vendor/golang.org/x/sys/unix/mremap.go | 1 - vendor/golang.org/x/sys/unix/pagesize_unix.go | 1 - .../golang.org/x/sys/unix/pledge_openbsd.go | 92 ++++--------------- vendor/golang.org/x/sys/unix/ptrace_darwin.go | 1 - vendor/golang.org/x/sys/unix/ptrace_ios.go | 1 - vendor/golang.org/x/sys/unix/race.go | 1 - vendor/golang.org/x/sys/unix/race0.go | 1 - .../x/sys/unix/readdirent_getdents.go | 1 - .../x/sys/unix/readdirent_getdirentries.go | 1 - vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 1 - .../x/sys/unix/sockcmsg_unix_other.go | 1 - vendor/golang.org/x/sys/unix/syscall.go | 1 - vendor/golang.org/x/sys/unix/syscall_aix.go | 4 +- .../golang.org/x/sys/unix/syscall_aix_ppc.go | 1 - .../x/sys/unix/syscall_aix_ppc64.go | 1 - vendor/golang.org/x/sys/unix/syscall_bsd.go | 3 +- .../x/sys/unix/syscall_darwin_amd64.go | 1 - .../x/sys/unix/syscall_darwin_arm64.go | 1 - .../x/sys/unix/syscall_darwin_libSystem.go | 1 - .../x/sys/unix/syscall_dragonfly_amd64.go | 1 - .../x/sys/unix/syscall_freebsd_386.go | 1 - .../x/sys/unix/syscall_freebsd_amd64.go | 1 - .../x/sys/unix/syscall_freebsd_arm.go | 1 - .../x/sys/unix/syscall_freebsd_arm64.go | 1 - .../x/sys/unix/syscall_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/syscall_hurd.go | 1 - .../golang.org/x/sys/unix/syscall_hurd_386.go | 1 - .../golang.org/x/sys/unix/syscall_illumos.go | 1 - vendor/golang.org/x/sys/unix/syscall_linux.go | 33 ++++--- .../x/sys/unix/syscall_linux_386.go | 1 - .../x/sys/unix/syscall_linux_alarm.go | 2 - .../x/sys/unix/syscall_linux_amd64.go | 1 - .../x/sys/unix/syscall_linux_amd64_gc.go | 1 - .../x/sys/unix/syscall_linux_arm.go | 1 - .../x/sys/unix/syscall_linux_arm64.go | 1 - .../golang.org/x/sys/unix/syscall_linux_gc.go | 1 - .../x/sys/unix/syscall_linux_gc_386.go | 1 - .../x/sys/unix/syscall_linux_gc_arm.go | 1 - .../x/sys/unix/syscall_linux_gccgo_386.go | 1 - .../x/sys/unix/syscall_linux_gccgo_arm.go | 1 - .../x/sys/unix/syscall_linux_loong64.go | 1 - .../x/sys/unix/syscall_linux_mips64x.go | 2 - .../x/sys/unix/syscall_linux_mipsx.go | 2 - .../x/sys/unix/syscall_linux_ppc.go | 1 - .../x/sys/unix/syscall_linux_ppc64x.go | 2 - .../x/sys/unix/syscall_linux_riscv64.go | 1 - .../x/sys/unix/syscall_linux_s390x.go | 1 - .../x/sys/unix/syscall_linux_sparc64.go | 1 - .../x/sys/unix/syscall_netbsd_386.go | 1 - .../x/sys/unix/syscall_netbsd_amd64.go | 1 - .../x/sys/unix/syscall_netbsd_arm.go | 1 - .../x/sys/unix/syscall_netbsd_arm64.go | 1 - .../golang.org/x/sys/unix/syscall_openbsd.go | 28 ++++-- .../x/sys/unix/syscall_openbsd_386.go | 1 - .../x/sys/unix/syscall_openbsd_amd64.go | 1 - .../x/sys/unix/syscall_openbsd_arm.go | 1 - .../x/sys/unix/syscall_openbsd_arm64.go | 1 - .../x/sys/unix/syscall_openbsd_libc.go | 1 - .../x/sys/unix/syscall_openbsd_ppc64.go | 1 - .../x/sys/unix/syscall_openbsd_riscv64.go | 1 - .../golang.org/x/sys/unix/syscall_solaris.go | 5 +- .../x/sys/unix/syscall_solaris_amd64.go | 1 - vendor/golang.org/x/sys/unix/syscall_unix.go | 1 - .../golang.org/x/sys/unix/syscall_unix_gc.go | 2 - .../x/sys/unix/syscall_unix_gc_ppc64x.go | 3 - .../x/sys/unix/syscall_zos_s390x.go | 3 +- vendor/golang.org/x/sys/unix/sysvshm_linux.go | 1 - vendor/golang.org/x/sys/unix/sysvshm_unix.go | 1 - .../x/sys/unix/sysvshm_unix_other.go | 1 - vendor/golang.org/x/sys/unix/timestruct.go | 1 - .../golang.org/x/sys/unix/unveil_openbsd.go | 41 +++++---- vendor/golang.org/x/sys/unix/xattr_bsd.go | 1 - .../golang.org/x/sys/unix/zerrors_aix_ppc.go | 1 - .../x/sys/unix/zerrors_aix_ppc64.go | 1 - .../x/sys/unix/zerrors_darwin_amd64.go | 1 - .../x/sys/unix/zerrors_darwin_arm64.go | 1 - .../x/sys/unix/zerrors_dragonfly_amd64.go | 1 - .../x/sys/unix/zerrors_freebsd_386.go | 1 - .../x/sys/unix/zerrors_freebsd_amd64.go | 1 - .../x/sys/unix/zerrors_freebsd_arm.go | 1 - .../x/sys/unix/zerrors_freebsd_arm64.go | 1 - .../x/sys/unix/zerrors_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/zerrors_linux.go | 14 ++- .../x/sys/unix/zerrors_linux_386.go | 1 - .../x/sys/unix/zerrors_linux_amd64.go | 1 - .../x/sys/unix/zerrors_linux_arm.go | 1 - .../x/sys/unix/zerrors_linux_arm64.go | 1 - .../x/sys/unix/zerrors_linux_loong64.go | 2 +- .../x/sys/unix/zerrors_linux_mips.go | 1 - .../x/sys/unix/zerrors_linux_mips64.go | 1 - .../x/sys/unix/zerrors_linux_mips64le.go | 1 - .../x/sys/unix/zerrors_linux_mipsle.go | 1 - .../x/sys/unix/zerrors_linux_ppc.go | 1 - .../x/sys/unix/zerrors_linux_ppc64.go | 1 - .../x/sys/unix/zerrors_linux_ppc64le.go | 1 - .../x/sys/unix/zerrors_linux_riscv64.go | 4 +- .../x/sys/unix/zerrors_linux_s390x.go | 1 - .../x/sys/unix/zerrors_linux_sparc64.go | 1 - .../x/sys/unix/zerrors_netbsd_386.go | 1 - .../x/sys/unix/zerrors_netbsd_amd64.go | 1 - .../x/sys/unix/zerrors_netbsd_arm.go | 1 - .../x/sys/unix/zerrors_netbsd_arm64.go | 1 - .../x/sys/unix/zerrors_openbsd_386.go | 1 - .../x/sys/unix/zerrors_openbsd_amd64.go | 1 - .../x/sys/unix/zerrors_openbsd_arm.go | 1 - .../x/sys/unix/zerrors_openbsd_arm64.go | 1 - .../x/sys/unix/zerrors_openbsd_mips64.go | 1 - .../x/sys/unix/zerrors_openbsd_ppc64.go | 1 - .../x/sys/unix/zerrors_openbsd_riscv64.go | 1 - .../x/sys/unix/zerrors_solaris_amd64.go | 1 - .../x/sys/unix/zerrors_zos_s390x.go | 1 - .../x/sys/unix/zptrace_armnn_linux.go | 2 - .../x/sys/unix/zptrace_mipsnn_linux.go | 2 - .../x/sys/unix/zptrace_mipsnnle_linux.go | 2 - .../x/sys/unix/zptrace_x86_linux.go | 2 - .../golang.org/x/sys/unix/zsyscall_aix_ppc.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64_gc.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64_gccgo.go | 1 - .../x/sys/unix/zsyscall_darwin_amd64.go | 1 - .../x/sys/unix/zsyscall_darwin_arm64.go | 1 - .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1 - .../x/sys/unix/zsyscall_freebsd_386.go | 1 - .../x/sys/unix/zsyscall_freebsd_amd64.go | 1 - .../x/sys/unix/zsyscall_freebsd_arm.go | 1 - .../x/sys/unix/zsyscall_freebsd_arm64.go | 1 - .../x/sys/unix/zsyscall_freebsd_riscv64.go | 1 - .../x/sys/unix/zsyscall_illumos_amd64.go | 1 - .../golang.org/x/sys/unix/zsyscall_linux.go | 26 +++++- .../x/sys/unix/zsyscall_linux_386.go | 1 - .../x/sys/unix/zsyscall_linux_amd64.go | 1 - .../x/sys/unix/zsyscall_linux_arm.go | 1 - .../x/sys/unix/zsyscall_linux_arm64.go | 1 - .../x/sys/unix/zsyscall_linux_loong64.go | 1 - .../x/sys/unix/zsyscall_linux_mips.go | 1 - .../x/sys/unix/zsyscall_linux_mips64.go | 1 - .../x/sys/unix/zsyscall_linux_mips64le.go | 1 - .../x/sys/unix/zsyscall_linux_mipsle.go | 1 - .../x/sys/unix/zsyscall_linux_ppc.go | 1 - .../x/sys/unix/zsyscall_linux_ppc64.go | 1 - .../x/sys/unix/zsyscall_linux_ppc64le.go | 1 - .../x/sys/unix/zsyscall_linux_riscv64.go | 1 - .../x/sys/unix/zsyscall_linux_s390x.go | 1 - .../x/sys/unix/zsyscall_linux_sparc64.go | 1 - .../x/sys/unix/zsyscall_netbsd_386.go | 1 - .../x/sys/unix/zsyscall_netbsd_amd64.go | 1 - .../x/sys/unix/zsyscall_netbsd_arm.go | 1 - .../x/sys/unix/zsyscall_netbsd_arm64.go | 1 - .../x/sys/unix/zsyscall_openbsd_386.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_386.s | 20 ++++ .../x/sys/unix/zsyscall_openbsd_amd64.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_amd64.s | 20 ++++ .../x/sys/unix/zsyscall_openbsd_arm.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_arm.s | 20 ++++ .../x/sys/unix/zsyscall_openbsd_arm64.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_arm64.s | 20 ++++ .../x/sys/unix/zsyscall_openbsd_mips64.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_mips64.s | 20 ++++ .../x/sys/unix/zsyscall_openbsd_ppc64.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_ppc64.s | 24 +++++ .../x/sys/unix/zsyscall_openbsd_riscv64.go | 72 ++++++++++++++- .../x/sys/unix/zsyscall_openbsd_riscv64.s | 20 ++++ .../x/sys/unix/zsyscall_solaris_amd64.go | 1 - .../x/sys/unix/zsyscall_zos_s390x.go | 1 - .../x/sys/unix/zsysctl_openbsd_386.go | 1 - .../x/sys/unix/zsysctl_openbsd_amd64.go | 1 - .../x/sys/unix/zsysctl_openbsd_arm.go | 1 - .../x/sys/unix/zsysctl_openbsd_arm64.go | 1 - .../x/sys/unix/zsysctl_openbsd_mips64.go | 1 - .../x/sys/unix/zsysctl_openbsd_ppc64.go | 1 - .../x/sys/unix/zsysctl_openbsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_darwin_amd64.go | 1 - .../x/sys/unix/zsysnum_darwin_arm64.go | 1 - .../x/sys/unix/zsysnum_dragonfly_amd64.go | 1 - .../x/sys/unix/zsysnum_freebsd_386.go | 1 - .../x/sys/unix/zsysnum_freebsd_amd64.go | 1 - .../x/sys/unix/zsysnum_freebsd_arm.go | 1 - .../x/sys/unix/zsysnum_freebsd_arm64.go | 1 - .../x/sys/unix/zsysnum_freebsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_linux_386.go | 2 +- .../x/sys/unix/zsysnum_linux_amd64.go | 3 +- .../x/sys/unix/zsysnum_linux_arm.go | 2 +- .../x/sys/unix/zsysnum_linux_arm64.go | 2 +- .../x/sys/unix/zsysnum_linux_loong64.go | 2 +- .../x/sys/unix/zsysnum_linux_mips.go | 2 +- .../x/sys/unix/zsysnum_linux_mips64.go | 2 +- .../x/sys/unix/zsysnum_linux_mips64le.go | 2 +- .../x/sys/unix/zsysnum_linux_mipsle.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc64.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc64le.go | 2 +- .../x/sys/unix/zsysnum_linux_riscv64.go | 2 +- .../x/sys/unix/zsysnum_linux_s390x.go | 2 +- .../x/sys/unix/zsysnum_linux_sparc64.go | 2 +- .../x/sys/unix/zsysnum_netbsd_386.go | 1 - .../x/sys/unix/zsysnum_netbsd_amd64.go | 1 - .../x/sys/unix/zsysnum_netbsd_arm.go | 1 - .../x/sys/unix/zsysnum_netbsd_arm64.go | 1 - .../x/sys/unix/zsysnum_openbsd_386.go | 1 - .../x/sys/unix/zsysnum_openbsd_amd64.go | 1 - .../x/sys/unix/zsysnum_openbsd_arm.go | 1 - .../x/sys/unix/zsysnum_openbsd_arm64.go | 1 - .../x/sys/unix/zsysnum_openbsd_mips64.go | 1 - .../x/sys/unix/zsysnum_openbsd_ppc64.go | 1 - .../x/sys/unix/zsysnum_openbsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_zos_s390x.go | 1 - .../golang.org/x/sys/unix/ztypes_aix_ppc.go | 1 - .../golang.org/x/sys/unix/ztypes_aix_ppc64.go | 1 - .../x/sys/unix/ztypes_darwin_amd64.go | 1 - .../x/sys/unix/ztypes_darwin_arm64.go | 1 - .../x/sys/unix/ztypes_dragonfly_amd64.go | 1 - .../x/sys/unix/ztypes_freebsd_386.go | 1 - .../x/sys/unix/ztypes_freebsd_amd64.go | 1 - .../x/sys/unix/ztypes_freebsd_arm.go | 1 - .../x/sys/unix/ztypes_freebsd_arm64.go | 1 - .../x/sys/unix/ztypes_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/ztypes_linux.go | 45 ++++++++- .../golang.org/x/sys/unix/ztypes_linux_386.go | 1 - .../x/sys/unix/ztypes_linux_amd64.go | 1 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 1 - .../x/sys/unix/ztypes_linux_arm64.go | 1 - .../x/sys/unix/ztypes_linux_loong64.go | 1 - .../x/sys/unix/ztypes_linux_mips.go | 1 - .../x/sys/unix/ztypes_linux_mips64.go | 1 - .../x/sys/unix/ztypes_linux_mips64le.go | 1 - .../x/sys/unix/ztypes_linux_mipsle.go | 1 - .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 1 - .../x/sys/unix/ztypes_linux_ppc64.go | 1 - .../x/sys/unix/ztypes_linux_ppc64le.go | 1 - .../x/sys/unix/ztypes_linux_riscv64.go | 1 - .../x/sys/unix/ztypes_linux_s390x.go | 1 - .../x/sys/unix/ztypes_linux_sparc64.go | 1 - .../x/sys/unix/ztypes_netbsd_386.go | 1 - .../x/sys/unix/ztypes_netbsd_amd64.go | 1 - .../x/sys/unix/ztypes_netbsd_arm.go | 1 - .../x/sys/unix/ztypes_netbsd_arm64.go | 1 - .../x/sys/unix/ztypes_openbsd_386.go | 1 - .../x/sys/unix/ztypes_openbsd_amd64.go | 1 - .../x/sys/unix/ztypes_openbsd_arm.go | 1 - .../x/sys/unix/ztypes_openbsd_arm64.go | 1 - .../x/sys/unix/ztypes_openbsd_mips64.go | 1 - .../x/sys/unix/ztypes_openbsd_ppc64.go | 1 - .../x/sys/unix/ztypes_openbsd_riscv64.go | 1 - .../x/sys/unix/ztypes_solaris_amd64.go | 1 - .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 1 - vendor/golang.org/x/sys/windows/aliases.go | 1 - vendor/golang.org/x/sys/windows/empty.s | 1 - vendor/golang.org/x/sys/windows/eventlog.go | 1 - vendor/golang.org/x/sys/windows/mksyscall.go | 1 - vendor/golang.org/x/sys/windows/race.go | 1 - vendor/golang.org/x/sys/windows/race0.go | 1 - vendor/golang.org/x/sys/windows/service.go | 1 - vendor/golang.org/x/sys/windows/str.go | 1 - vendor/golang.org/x/sys/windows/syscall.go | 1 - .../x/sys/windows/syscall_windows.go | 6 +- .../golang.org/x/sys/windows/types_windows.go | 28 +++++- .../x/sys/windows/zsyscall_windows.go | 28 ++++++ vendor/golang.org/x/term/term_unix.go | 1 - vendor/golang.org/x/term/term_unix_bsd.go | 1 - vendor/golang.org/x/term/term_unix_other.go | 1 - vendor/golang.org/x/term/term_unsupported.go | 1 - .../x/text/secure/bidirule/bidirule10.0.0.go | 1 - .../x/text/secure/bidirule/bidirule9.0.0.go | 1 - .../x/text/unicode/bidi/tables10.0.0.go | 1 - .../x/text/unicode/bidi/tables11.0.0.go | 1 - .../x/text/unicode/bidi/tables12.0.0.go | 1 - .../x/text/unicode/bidi/tables13.0.0.go | 1 - .../x/text/unicode/bidi/tables15.0.0.go | 1 - .../x/text/unicode/bidi/tables9.0.0.go | 1 - .../x/text/unicode/norm/tables10.0.0.go | 1 - .../x/text/unicode/norm/tables11.0.0.go | 1 - .../x/text/unicode/norm/tables12.0.0.go | 1 - .../x/text/unicode/norm/tables13.0.0.go | 1 - .../x/text/unicode/norm/tables15.0.0.go | 1 - .../x/text/unicode/norm/tables9.0.0.go | 1 - vendor/modules.txt | 16 ++-- 334 files changed, 924 insertions(+), 485 deletions(-) diff --git a/go.mod b/go.mod index 07a3178d8..1775f5669 100644 --- a/go.mod +++ b/go.mod @@ -123,15 +123,15 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go4.org v0.0.0-20200104003542-c7e774b10ea0 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/go.sum b/go.sum index dfaf5fdc2..255d55796 100644 --- a/go.sum +++ b/go.sum @@ -472,8 +472,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -624,13 +624,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -639,8 +639,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/vendor/golang.org/x/sys/execabs/execabs_go118.go b/vendor/golang.org/x/sys/execabs/execabs_go118.go index 2000064a8..5627d70e3 100644 --- a/vendor/golang.org/x/sys/execabs/execabs_go118.go +++ b/vendor/golang.org/x/sys/execabs/execabs_go118.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.19 -// +build !go1.19 package execabs diff --git a/vendor/golang.org/x/sys/execabs/execabs_go119.go b/vendor/golang.org/x/sys/execabs/execabs_go119.go index f364b3418..d60ab1b41 100644 --- a/vendor/golang.org/x/sys/execabs/execabs_go119.go +++ b/vendor/golang.org/x/sys/execabs/execabs_go119.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.19 -// +build go1.19 package execabs diff --git a/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go b/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go index c9b69937a..73687de74 100644 --- a/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go +++ b/vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.5 -// +build go1.5 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/pwd_plan9.go b/vendor/golang.org/x/sys/plan9/pwd_plan9.go index 98bf56b73..fb9458218 100644 --- a/vendor/golang.org/x/sys/plan9/pwd_plan9.go +++ b/vendor/golang.org/x/sys/plan9/pwd_plan9.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.5 -// +build !go1.5 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/race.go b/vendor/golang.org/x/sys/plan9/race.go index 62377d2ff..c02d9ed33 100644 --- a/vendor/golang.org/x/sys/plan9/race.go +++ b/vendor/golang.org/x/sys/plan9/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 && race -// +build plan9,race package plan9 diff --git a/vendor/golang.org/x/sys/plan9/race0.go b/vendor/golang.org/x/sys/plan9/race0.go index f8da30876..7b15e15f6 100644 --- a/vendor/golang.org/x/sys/plan9/race0.go +++ b/vendor/golang.org/x/sys/plan9/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 && !race -// +build plan9,!race package plan9 diff --git a/vendor/golang.org/x/sys/plan9/str.go b/vendor/golang.org/x/sys/plan9/str.go index 55fa8d025..ba3e8ff8a 100644 --- a/vendor/golang.org/x/sys/plan9/str.go +++ b/vendor/golang.org/x/sys/plan9/str.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/syscall.go b/vendor/golang.org/x/sys/plan9/syscall.go index 67e5b0115..d631fd664 100644 --- a/vendor/golang.org/x/sys/plan9/syscall.go +++ b/vendor/golang.org/x/sys/plan9/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build plan9 -// +build plan9 // Package plan9 contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go index 3f40b9bd7..f780d5c80 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && 386 -// +build plan9,386 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go index 0e6a96aa4..7de61065f 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && amd64 -// +build plan9,amd64 package plan9 diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go index 244c501b7..ea85780f0 100644 --- a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build plan9 && arm -// +build plan9,arm package plan9 diff --git a/vendor/golang.org/x/sys/unix/aliases.go b/vendor/golang.org/x/sys/unix/aliases.go index abc89c104..e7d3df4bd 100644 --- a/vendor/golang.org/x/sys/unix/aliases.go +++ b/vendor/golang.org/x/sys/unix/aliases.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9 -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos -// +build go1.9 package unix diff --git a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s index db9171c2e..269e173ca 100644 --- a/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s +++ b/vendor/golang.org/x/sys/unix/asm_aix_ppc64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_386.s b/vendor/golang.org/x/sys/unix/asm_bsd_386.s index e0fcd9b3d..a4fcef0e0 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_386.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_386.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd || netbsd || openbsd) && gc -// +build freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s index 2b99c349a..1e63615c5 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_amd64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc -// +build darwin dragonfly freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s index d702d4adc..6496c3100 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (freebsd || netbsd || openbsd) && gc -// +build freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s index fe36a7391..4fd1f54da 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_arm64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s index e5b9a8489..42f7eb9e4 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s index d560019ea..f8902667e 100644 --- a/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s +++ b/vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || freebsd || netbsd || openbsd) && gc -// +build darwin freebsd netbsd openbsd -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_386.s b/vendor/golang.org/x/sys/unix/asm_linux_386.s index 8fd101d07..3b4734870 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_386.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_386.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s index 7ed38e43c..67e29f317 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm.s b/vendor/golang.org/x/sys/unix/asm_linux_arm.s index 8ef1d5140..d6ae269ce 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s index 98ae02760..01e5e253c 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_arm64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_arm64.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && arm64 && gc -// +build linux -// +build arm64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_loong64.s b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s index 565357288..2abf12f6e 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_loong64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_loong64.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && loong64 && gc -// +build linux -// +build loong64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s index 21231d2ce..f84bae712 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mips64x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) && gc -// +build linux -// +build mips64 mips64le -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s index 6783b26c6..f08f62807 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_mipsx.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) && gc -// +build linux -// +build mips mipsle -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s index 19d498934..bdfc024d2 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) && gc -// +build linux -// +build ppc64 ppc64le -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s index e42eb81d5..2e8c99612 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_riscv64.s @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && gc -// +build riscv64 -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s index c46aab339..2c394b11e 100644 --- a/vendor/golang.org/x/sys/unix/asm_linux_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_linux_s390x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && s390x && gc -// +build linux -// +build s390x -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s index 5e7a1169c..fab586a2c 100644 --- a/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s +++ b/vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s index f8c5394c1..f949ec547 100644 --- a/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s +++ b/vendor/golang.org/x/sys/unix/asm_solaris_amd64.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gc -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s index 3b54e1858..2f67ba86d 100644 --- a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x && gc -// +build zos -// +build s390x -// +build gc #include "textflag.h" diff --git a/vendor/golang.org/x/sys/unix/cap_freebsd.go b/vendor/golang.org/x/sys/unix/cap_freebsd.go index 0b7c6adb8..a08657890 100644 --- a/vendor/golang.org/x/sys/unix/cap_freebsd.go +++ b/vendor/golang.org/x/sys/unix/cap_freebsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd -// +build freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/constants.go b/vendor/golang.org/x/sys/unix/constants.go index 394a3965b..6fb7cb77d 100644 --- a/vendor/golang.org/x/sys/unix/constants.go +++ b/vendor/golang.org/x/sys/unix/constants.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go index 65a998508..d78513461 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc -// +build aix,ppc // Functions to access/create device major and minor numbers matching the // encoding used by AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go index 8fc08ad0a..623a5e697 100644 --- a/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/dev_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc64 -// +build aix,ppc64 // Functions to access/create device major and minor numbers matching the // encoding used AIX. diff --git a/vendor/golang.org/x/sys/unix/dev_zos.go b/vendor/golang.org/x/sys/unix/dev_zos.go index a388e59a0..bb6a64fe9 100644 --- a/vendor/golang.org/x/sys/unix/dev_zos.go +++ b/vendor/golang.org/x/sys/unix/dev_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Functions to access/create device major and minor numbers matching the // encoding used by z/OS. diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go index 2499f977b..1ebf11782 100644 --- a/vendor/golang.org/x/sys/unix/dirent.go +++ b/vendor/golang.org/x/sys/unix/dirent.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/endian_big.go b/vendor/golang.org/x/sys/unix/endian_big.go index a52026557..1095fd31d 100644 --- a/vendor/golang.org/x/sys/unix/endian_big.go +++ b/vendor/golang.org/x/sys/unix/endian_big.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64 -// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/endian_little.go b/vendor/golang.org/x/sys/unix/endian_little.go index b0f2bc4ae..b9f0e277b 100644 --- a/vendor/golang.org/x/sys/unix/endian_little.go +++ b/vendor/golang.org/x/sys/unix/endian_little.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. // //go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh -// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh package unix diff --git a/vendor/golang.org/x/sys/unix/env_unix.go b/vendor/golang.org/x/sys/unix/env_unix.go index 29ccc4d13..a96da71f4 100644 --- a/vendor/golang.org/x/sys/unix/env_unix.go +++ b/vendor/golang.org/x/sys/unix/env_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Unix environment variables. diff --git a/vendor/golang.org/x/sys/unix/epoll_zos.go b/vendor/golang.org/x/sys/unix/epoll_zos.go index cedaf7e02..7753fddea 100644 --- a/vendor/golang.org/x/sys/unix/epoll_zos.go +++ b/vendor/golang.org/x/sys/unix/epoll_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl.go b/vendor/golang.org/x/sys/unix/fcntl.go index e9b991258..6200876fb 100644 --- a/vendor/golang.org/x/sys/unix/fcntl.go +++ b/vendor/golang.org/x/sys/unix/fcntl.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || freebsd || linux || netbsd || openbsd -// +build dragonfly freebsd linux netbsd openbsd +//go:build dragonfly || freebsd || linux || netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go index 29d44808b..13b4acd5c 100644 --- a/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go +++ b/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc) -// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/fdset.go b/vendor/golang.org/x/sys/unix/fdset.go index a8068f94f..9e83d18cd 100644 --- a/vendor/golang.org/x/sys/unix/fdset.go +++ b/vendor/golang.org/x/sys/unix/fdset.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/fstatfs_zos.go b/vendor/golang.org/x/sys/unix/fstatfs_zos.go index e377cc9f4..c8bde601e 100644 --- a/vendor/golang.org/x/sys/unix/fstatfs_zos.go +++ b/vendor/golang.org/x/sys/unix/fstatfs_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/gccgo.go b/vendor/golang.org/x/sys/unix/gccgo.go index b06f52d74..aca5721dd 100644 --- a/vendor/golang.org/x/sys/unix/gccgo.go +++ b/vendor/golang.org/x/sys/unix/gccgo.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && !aix && !hurd -// +build gccgo,!aix,!hurd package unix diff --git a/vendor/golang.org/x/sys/unix/gccgo_c.c b/vendor/golang.org/x/sys/unix/gccgo_c.c index f98a1c542..d468b7b47 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_c.c +++ b/vendor/golang.org/x/sys/unix/gccgo_c.c @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && !aix && !hurd -// +build gccgo,!aix,!hurd #include #include diff --git a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go index e60e49a3d..972d61bd7 100644 --- a/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build gccgo && linux && amd64 -// +build gccgo,linux,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/ifreq_linux.go b/vendor/golang.org/x/sys/unix/ifreq_linux.go index 15721a510..848840ae4 100644 --- a/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_linux.go b/vendor/golang.org/x/sys/unix/ioctl_linux.go index 0d12c0851..dbe680eab 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -231,3 +231,8 @@ func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) { func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error { return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value)) } + +// IoctlLoopConfigure configures all loop device parameters in a single step +func IoctlLoopConfigure(fd int, value *LoopConfig) error { + return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value)) +} diff --git a/vendor/golang.org/x/sys/unix/ioctl_signed.go b/vendor/golang.org/x/sys/unix/ioctl_signed.go index 7def9580e..5b0759bd8 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_signed.go +++ b/vendor/golang.org/x/sys/unix/ioctl_signed.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || solaris -// +build aix solaris package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_unsigned.go b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go index 649913d1e..20f470b9d 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_unsigned.go +++ b/vendor/golang.org/x/sys/unix/ioctl_unsigned.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd -// +build darwin dragonfly freebsd hurd linux netbsd openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ioctl_zos.go b/vendor/golang.org/x/sys/unix/ioctl_zos.go index cdc21bf76..c8b2a750f 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_zos.go +++ b/vendor/golang.org/x/sys/unix/ioctl_zos.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 47fa6a7eb..6202638ba 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -519,6 +519,7 @@ ccflags="$@" $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || + $2 == "LOOP_CONFIGURE" || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ || @@ -560,7 +561,7 @@ ccflags="$@" $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || $2 ~ /^CLONE_[A-Z_]+/ || - $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ && + $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ && $2 ~ /^(BPF|DLT)_/ || $2 ~ /^AUDIT_/ || $2 ~ /^(CLOCK|TIMER)_/ || @@ -663,7 +664,6 @@ echo '// mkerrors.sh' "$@" echo '// Code generated by the command above; see README.md. DO NOT EDIT.' echo echo "//go:build ${GOARCH} && ${GOOS}" -echo "// +build ${GOARCH},${GOOS}" echo go tool cgo -godefs -- "$@" _const.go >_error.out cat _error.out | grep -vf _error.grep | grep -vf _signal.grep diff --git a/vendor/golang.org/x/sys/unix/mmap_nomremap.go b/vendor/golang.org/x/sys/unix/mmap_nomremap.go index ca0513632..4b68e5978 100644 --- a/vendor/golang.org/x/sys/unix/mmap_nomremap.go +++ b/vendor/golang.org/x/sys/unix/mmap_nomremap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || openbsd || solaris -// +build aix darwin dragonfly freebsd openbsd solaris package unix diff --git a/vendor/golang.org/x/sys/unix/mremap.go b/vendor/golang.org/x/sys/unix/mremap.go index fa93d0aa9..fd45fe529 100644 --- a/vendor/golang.org/x/sys/unix/mremap.go +++ b/vendor/golang.org/x/sys/unix/mremap.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux || netbsd -// +build linux netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/pagesize_unix.go b/vendor/golang.org/x/sys/unix/pagesize_unix.go index 53f1b4c5b..4d0a3430e 100644 --- a/vendor/golang.org/x/sys/unix/pagesize_unix.go +++ b/vendor/golang.org/x/sys/unix/pagesize_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // For Unix, get the pagesize from the runtime. diff --git a/vendor/golang.org/x/sys/unix/pledge_openbsd.go b/vendor/golang.org/x/sys/unix/pledge_openbsd.go index eb48294b2..6a09af53e 100644 --- a/vendor/golang.org/x/sys/unix/pledge_openbsd.go +++ b/vendor/golang.org/x/sys/unix/pledge_openbsd.go @@ -8,54 +8,31 @@ import ( "errors" "fmt" "strconv" - "syscall" - "unsafe" ) // Pledge implements the pledge syscall. // -// The pledge syscall does not accept execpromises on OpenBSD releases -// before 6.3. -// -// execpromises must be empty when Pledge is called on OpenBSD -// releases predating 6.3, otherwise an error will be returned. +// This changes both the promises and execpromises; use PledgePromises or +// PledgeExecpromises to only change the promises or execpromises +// respectively. // // For more information see pledge(2). func Pledge(promises, execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - pptr, err := syscall.BytePtrFromString(promises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable will hold either a nil unsafe.Pointer or - // an unsafe.Pointer to a string (execpromises). - var expr unsafe.Pointer - - // If we're running on OpenBSD > 6.2, pass execpromises to the syscall. - if maj > 6 || (maj == 6 && min > 2) { - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - expr = unsafe.Pointer(exptr) - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, exptr) } // PledgePromises implements the pledge syscall. @@ -64,30 +41,16 @@ func Pledge(promises, execpromises string) error { // // For more information see pledge(2). func PledgePromises(promises string) error { - maj, min, err := majmin() - if err != nil { - return err - } - - err = pledgeAvailable(maj, min, "") - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - // This variable holds the execpromises and is always nil. - var expr unsafe.Pointer - - pptr, err := syscall.BytePtrFromString(promises) + pptr, err := BytePtrFromString(promises) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) - if e != 0 { - return e - } - - return nil + return pledge(pptr, nil) } // PledgeExecpromises implements the pledge syscall. @@ -96,30 +59,16 @@ func PledgePromises(promises string) error { // // For more information see pledge(2). func PledgeExecpromises(execpromises string) error { - maj, min, err := majmin() - if err != nil { + if err := pledgeAvailable(); err != nil { return err } - err = pledgeAvailable(maj, min, execpromises) + exptr, err := BytePtrFromString(execpromises) if err != nil { return err } - // This variable holds the promises and is always nil. - var pptr unsafe.Pointer - - exptr, err := syscall.BytePtrFromString(execpromises) - if err != nil { - return err - } - - _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0) - if e != 0 { - return e - } - - return nil + return pledge(nil, exptr) } // majmin returns major and minor version number for an OpenBSD system. @@ -147,16 +96,15 @@ func majmin() (major int, minor int, err error) { // pledgeAvailable checks for availability of the pledge(2) syscall // based on the running OpenBSD version. -func pledgeAvailable(maj, min int, execpromises string) error { - // If OpenBSD <= 5.9, pledge is not available. - if (maj == 5 && min != 9) || maj < 5 { - return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min) +func pledgeAvailable() error { + maj, min, err := majmin() + if err != nil { + return err } - // If OpenBSD <= 6.2 and execpromises is not empty, - // return an error - execpromises is not available before 6.3 - if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" { - return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min) + // Require OpenBSD 6.4 as a minimum. + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min) } return nil diff --git a/vendor/golang.org/x/sys/unix/ptrace_darwin.go b/vendor/golang.org/x/sys/unix/ptrace_darwin.go index 463c3eff7..3f0975f3d 100644 --- a/vendor/golang.org/x/sys/unix/ptrace_darwin.go +++ b/vendor/golang.org/x/sys/unix/ptrace_darwin.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package unix diff --git a/vendor/golang.org/x/sys/unix/ptrace_ios.go b/vendor/golang.org/x/sys/unix/ptrace_ios.go index ed0509a01..a4d35db5d 100644 --- a/vendor/golang.org/x/sys/unix/ptrace_ios.go +++ b/vendor/golang.org/x/sys/unix/ptrace_ios.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ios -// +build ios package unix diff --git a/vendor/golang.org/x/sys/unix/race.go b/vendor/golang.org/x/sys/unix/race.go index 6f6c5fec5..714d2aae7 100644 --- a/vendor/golang.org/x/sys/unix/race.go +++ b/vendor/golang.org/x/sys/unix/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin && race) || (linux && race) || (freebsd && race) -// +build darwin,race linux,race freebsd,race package unix diff --git a/vendor/golang.org/x/sys/unix/race0.go b/vendor/golang.org/x/sys/unix/race0.go index 706e1322a..4a9f6634c 100644 --- a/vendor/golang.org/x/sys/unix/race0.go +++ b/vendor/golang.org/x/sys/unix/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos -// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdents.go b/vendor/golang.org/x/sys/unix/readdirent_getdents.go index 4d6257569..dbd2b6ccb 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdents.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdents.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || dragonfly || freebsd || linux || netbsd || openbsd -// +build aix dragonfly freebsd linux netbsd openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go index 2a4ba47c4..130398b6b 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin -// +build darwin package unix diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go index 3865943f6..c3a62dbb1 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Socket control messages diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go index 0840fe4a5..4a1eab37e 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/syscall.go b/vendor/golang.org/x/sys/unix/syscall.go index 63e8c8383..5ea74da98 100644 --- a/vendor/golang.org/x/sys/unix/syscall.go +++ b/vendor/golang.org/x/sys/unix/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos // Package unix contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index e94e6cdac..67ce6cef2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix -// +build aix // Aix system calls. // This file is compiled as ordinary Go code, @@ -107,7 +106,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go index f2871fa95..1fdaa4760 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc -// +build aix,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go index 75718ec0f..c87f9a9f4 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix && ppc64 -// +build aix,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_bsd.go b/vendor/golang.org/x/sys/unix/syscall_bsd.go index 4217de518..a00c3e545 100644 --- a/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd // BSD system call wrappers shared by *BSD based systems // including OS X (Darwin) and FreeBSD. Like the other @@ -317,7 +316,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index b37310ce9..0eaecf5fc 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index d51ec9963..f36c6707c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go index 53c96641f..16dc69937 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && go1.12 -// +build darwin,go1.12 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go index 4e2d32120..14bab6b2d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go index b8da51004..3967bca77 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go index 47155c483..eff19ada2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go index 08932093f..4f24b517a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go index d151a0d0e..ac30759ec 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go index d5cd64b37..aab725ca7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd.go b/vendor/golang.org/x/sys/unix/syscall_hurd.go index 381fd4673..ba46651f8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_hurd.go +++ b/vendor/golang.org/x/sys/unix/syscall_hurd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build hurd -// +build hurd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd_386.go b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go index 7cf54a3e4..df89f9e6b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_hurd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_hurd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && hurd -// +build 386,hurd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_illumos.go b/vendor/golang.org/x/sys/unix/syscall_illumos.go index 87db5a6a8..a863f7052 100644 --- a/vendor/golang.org/x/sys/unix/syscall_illumos.go +++ b/vendor/golang.org/x/sys/unix/syscall_illumos.go @@ -5,7 +5,6 @@ // illumos system calls not present on Solaris. //go:build amd64 && illumos -// +build amd64,illumos package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index fb4e50224..0f85e29e6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -61,15 +61,23 @@ func FanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname string) ( } //sys fchmodat(dirfd int, path string, mode uint32) (err error) - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - // Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior - // and check the flags. Otherwise the mode would be applied to the symlink - // destination which is not what the user expects. - if flags&^AT_SYMLINK_NOFOLLOW != 0 { - return EINVAL - } else if flags&AT_SYMLINK_NOFOLLOW != 0 { - return EOPNOTSUPP +//sys fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + // Linux fchmodat doesn't support the flags parameter, but fchmodat2 does. + // Try fchmodat2 if flags are specified. + if flags != 0 { + err := fchmodat2(dirfd, path, mode, flags) + if err == ENOSYS { + // fchmodat2 isn't available. If the flags are known to be valid, + // return EOPNOTSUPP to indicate that fchmodat doesn't support them. + if flags&^(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EINVAL + } else if flags&(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) != 0 { + return EOPNOTSUPP + } + } + return err } return fchmodat(dirfd, path, mode) } @@ -417,7 +425,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -1301,7 +1310,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { return "", err } } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } func GetsockoptTpacketStats(fd, level, opt int) (*TpacketStats, error) { @@ -2482,3 +2491,5 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { } return attr, nil } + +//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index c7d9945ea..506dafa7b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && linux -// +build 386,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go index 08086ac6a..38d55641b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (386 || amd64 || mips || mipsle || mips64 || mipsle || ppc64 || ppc64le || ppc || s390x || sparc64) -// +build linux -// +build 386 amd64 mips mipsle mips64 mipsle ppc64 ppc64le ppc s390x sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 70601ce36..d557cf8de 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux -// +build amd64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go index 8b0f0f3aa..facdb83b2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && linux && gc -// +build amd64,linux,gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index da2986415..cd2dd797f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && linux -// +build arm,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index f5266689a..cf2ee6c75 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && linux -// +build arm64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go index 2b1168d7d..ffc4c2b63 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gc -// +build linux,gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go index 9843fb489..9ebfdcf44 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gc && 386 -// +build linux,gc,386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go index a6008fccd..5f2b57c4c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gc_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && gc && linux -// +build arm,gc,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go index 7740af242..d1a3ad826 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gccgo && 386 -// +build linux,gccgo,386 package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go index e16a12299..f2f67423e 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && gccgo && arm -// +build linux,gccgo,arm package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go index f6ab02ec1..3d0e98451 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build loong64 && linux -// +build loong64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 93fe59d25..70963a95a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips64 || mips64le) -// +build linux -// +build mips64 mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index aae7f0ffd..c218ebd28 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (mips || mipsle) -// +build linux -// +build mips mipsle package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index 66eff19a3..e6c48500c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && ppc -// +build linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 806aa2574..7286a9aa8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 5e6ceee12..6f5a28894 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && linux -// +build riscv64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index 2f89e8f5d..66f31210d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build s390x && linux -// +build s390x,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index 7ca064ae7..11d1f1698 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build sparc64 && linux -// +build sparc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go index 5199d282f..7a5eb5743 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go index 70a9c52e9..62d8957ae 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go index 3eb5942f9..ce6a06885 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go index fc6ccfd81..d46d689d1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 6f34479b5..b25343c71 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -137,18 +137,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e } func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { - var _p0 unsafe.Pointer + var bufptr *Statfs_t var bufsize uintptr if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) + bufptr = &buf[0] bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } - r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = e1 - } - return + return getfsstat(bufptr, bufsize, flags) } //sysnb getresuid(ruid *_C_int, euid *_C_int, suid *_C_int) @@ -171,6 +166,20 @@ func Getresgid() (rgid, egid, sgid int) { //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL +//sys fcntl(fd int, cmd int, arg int) (n int, err error) +//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) = SYS_FCNTL + +// FcntlInt performs a fcntl syscall on fd with the provided command and argument. +func FcntlInt(fd uintptr, cmd, arg int) (int, error) { + return fcntl(int(fd), cmd, arg) +} + +// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. +func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { + _, err := fcntlPtr(int(fd), cmd, unsafe.Pointer(lk)) + return err +} + //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { @@ -326,4 +335,7 @@ func Uname(uname *Utsname) error { //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys munmap(addr uintptr, length uintptr) (err error) +//sys getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) +//sys pledge(promises *byte, execpromises *byte) (err error) +//sys unveil(path *byte, flags *byte) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go index 6baabcdcb..9ddc89f4f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_386.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go index bab25360e..70a3c96ee 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go index 8eed3c4d4..265caa87f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go index 483dde99d..ac4fda171 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go index 04aa43f41..0a451e6dd 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_libc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build openbsd -// +build openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go index c2796139c..30a308cbb 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_ppc64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go index 23199a7ff..ea954330f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd_riscv64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index b99cfa134..21974af06 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -128,7 +128,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { if n > 0 { sl += _Socklen(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- @@ -157,7 +158,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { if err != nil { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } const ImplementsGetwd = true diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go index 0bd25ef81..e02d8ceae 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build amd64 && solaris -// +build amd64,solaris package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix.go b/vendor/golang.org/x/sys/unix/syscall_unix.go index f6eda2705..77081de8c 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go index b6919ca58..05c95bccf 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc.go @@ -3,8 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin || dragonfly || freebsd || (linux && !ppc64 && !ppc64le) || netbsd || openbsd || solaris) && gc -// +build darwin dragonfly freebsd linux,!ppc64,!ppc64le netbsd openbsd solaris -// +build gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go index f6f707acf..23f39b7af 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go @@ -3,9 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux && (ppc64le || ppc64) && gc -// +build linux -// +build ppc64le ppc64 -// +build gc package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 4596d041c..b473038c6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix @@ -1105,7 +1104,7 @@ func GetsockoptString(fd, level, opt int) (string, error) { return "", err } - return string(buf[:vallen-1]), nil + return ByteSliceToString(buf[:vallen]), nil } func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { diff --git a/vendor/golang.org/x/sys/unix/sysvshm_linux.go b/vendor/golang.org/x/sys/unix/sysvshm_linux.go index 2c3a4437f..4fcd38de2 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_linux.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_linux.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build linux -// +build linux package unix diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/vendor/golang.org/x/sys/unix/sysvshm_unix.go index 5bb41d17b..79a84f18b 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build (darwin && !ios) || linux -// +build darwin,!ios linux package unix diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go index 71bddefdb..9eb0db664 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin && !ios -// +build darwin,!ios package unix diff --git a/vendor/golang.org/x/sys/unix/timestruct.go b/vendor/golang.org/x/sys/unix/timestruct.go index 616b1b284..7997b1902 100644 --- a/vendor/golang.org/x/sys/unix/timestruct.go +++ b/vendor/golang.org/x/sys/unix/timestruct.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package unix diff --git a/vendor/golang.org/x/sys/unix/unveil_openbsd.go b/vendor/golang.org/x/sys/unix/unveil_openbsd.go index 168d5ae77..cb7e598ce 100644 --- a/vendor/golang.org/x/sys/unix/unveil_openbsd.go +++ b/vendor/golang.org/x/sys/unix/unveil_openbsd.go @@ -4,39 +4,48 @@ package unix -import ( - "syscall" - "unsafe" -) +import "fmt" // Unveil implements the unveil syscall. // For more information see unveil(2). // Note that the special case of blocking further // unveil calls is handled by UnveilBlock. func Unveil(path string, flags string) error { - pathPtr, err := syscall.BytePtrFromString(path) - if err != nil { + if err := supportsUnveil(); err != nil { return err } - flagsPtr, err := syscall.BytePtrFromString(flags) + pathPtr, err := BytePtrFromString(path) if err != nil { return err } - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(unsafe.Pointer(pathPtr)), uintptr(unsafe.Pointer(flagsPtr)), 0) - if e != 0 { - return e + flagsPtr, err := BytePtrFromString(flags) + if err != nil { + return err } - return nil + return unveil(pathPtr, flagsPtr) } // UnveilBlock blocks future unveil calls. // For more information see unveil(2). func UnveilBlock() error { - // Both pointers must be nil. - var pathUnsafe, flagsUnsafe unsafe.Pointer - _, _, e := syscall.Syscall(SYS_UNVEIL, uintptr(pathUnsafe), uintptr(flagsUnsafe), 0) - if e != 0 { - return e + if err := supportsUnveil(); err != nil { + return err } + return unveil(nil, nil) +} + +// supportsUnveil checks for availability of the unveil(2) system call based +// on the running OpenBSD version. +func supportsUnveil() error { + maj, min, err := majmin() + if err != nil { + return err + } + + // unveil is not available before 6.4 + if maj < 6 || (maj == 6 && min <= 3) { + return fmt.Errorf("cannot call Unveil on OpenBSD %d.%d", maj, min) + } + return nil } diff --git a/vendor/golang.org/x/sys/unix/xattr_bsd.go b/vendor/golang.org/x/sys/unix/xattr_bsd.go index f5f8e9f36..e16879396 100644 --- a/vendor/golang.org/x/sys/unix/xattr_bsd.go +++ b/vendor/golang.org/x/sys/unix/xattr_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build freebsd || netbsd -// +build freebsd netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go index ca9799b79..2fb219d78 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && aix -// +build ppc,aix // Created by cgo -godefs - DO NOT EDIT // cgo -godefs -- -maix32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go index 200c8c26f..b0e6f5c85 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && aix -// +build ppc64,aix // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -maix64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index 143007627..e40fa8524 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index ab044a742..bb02aa6c0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index 17bba0e44..c0e0f8694 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go index f8c2c5138..6c6923906 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go index 96310c3be..dd9163f8e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go index 777b69def..493a2a793 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go index c557ac2db..8b437b307 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go index 341b4d962..67c02dd57 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index f9c7f479b..c73cfe2f1 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -481,10 +480,13 @@ const ( BPF_FROM_BE = 0x8 BPF_FROM_LE = 0x0 BPF_FS_MAGIC = 0xcafe4a11 + BPF_F_AFTER = 0x10 BPF_F_ALLOW_MULTI = 0x2 BPF_F_ALLOW_OVERRIDE = 0x1 BPF_F_ANY_ALIGNMENT = 0x2 - BPF_F_KPROBE_MULTI_RETURN = 0x1 + BPF_F_BEFORE = 0x8 + BPF_F_ID = 0x20 + BPF_F_NETFILTER_IP_DEFRAG = 0x1 BPF_F_QUERY_EFFECTIVE = 0x1 BPF_F_REPLACE = 0x4 BPF_F_SLEEPABLE = 0x10 @@ -521,6 +523,7 @@ const ( BPF_MAJOR_VERSION = 0x1 BPF_MAXINSNS = 0x1000 BPF_MEM = 0x60 + BPF_MEMSX = 0x80 BPF_MEMWORDS = 0x10 BPF_MINOR_VERSION = 0x1 BPF_MISC = 0x7 @@ -776,6 +779,8 @@ const ( DEVLINK_GENL_MCGRP_CONFIG_NAME = "config" DEVLINK_GENL_NAME = "devlink" DEVLINK_GENL_VERSION = 0x1 + DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO = 0x4 + DEVLINK_PORT_FN_CAP_IPSEC_PACKET = 0x8 DEVLINK_PORT_FN_CAP_MIGRATABLE = 0x2 DEVLINK_PORT_FN_CAP_ROCE = 0x1 DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 @@ -1698,6 +1703,7 @@ const ( KEXEC_ON_CRASH = 0x1 KEXEC_PRESERVE_CONTEXT = 0x2 KEXEC_SEGMENT_MAX = 0x10 + KEXEC_UPDATE_ELFCOREHDR = 0x4 KEYCTL_ASSUME_AUTHORITY = 0x10 KEYCTL_CAPABILITIES = 0x1f KEYCTL_CAPS0_BIG_KEY = 0x10 @@ -1795,6 +1801,7 @@ const ( LOCK_SH = 0x1 LOCK_UN = 0x8 LOOP_CLR_FD = 0x4c01 + LOOP_CONFIGURE = 0x4c0a LOOP_CTL_ADD = 0x4c80 LOOP_CTL_GET_FREE = 0x4c82 LOOP_CTL_REMOVE = 0x4c81 @@ -2275,6 +2282,7 @@ const ( PERF_MEM_LVLNUM_PMEM = 0xe PERF_MEM_LVLNUM_RAM = 0xd PERF_MEM_LVLNUM_SHIFT = 0x21 + PERF_MEM_LVLNUM_UNC = 0x8 PERF_MEM_LVL_HIT = 0x2 PERF_MEM_LVL_IO = 0x1000 PERF_MEM_LVL_L1 = 0x8 @@ -3461,6 +3469,7 @@ const ( XDP_PACKET_HEADROOM = 0x100 XDP_PGOFF_RX_RING = 0x0 XDP_PGOFF_TX_RING = 0x80000000 + XDP_PKT_CONTD = 0x1 XDP_RING_NEED_WAKEUP = 0x1 XDP_RX_RING = 0x2 XDP_SHARED_UMEM = 0x1 @@ -3473,6 +3482,7 @@ const ( XDP_UMEM_REG = 0x4 XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1 XDP_USE_NEED_WAKEUP = 0x8 + XDP_USE_SG = 0x10 XDP_ZEROCOPY = 0x4 XENFS_SUPER_MAGIC = 0xabba1974 XFS_SUPER_MAGIC = 0x58465342 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 30aee00a5..4920821cf 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/386/include -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 8ebfa5127..a0c1e4112 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/amd64/include -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 271a21cdc..c63985560 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/arm/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 910c330a3..47cc62e25 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/arm64/include -fsigned-char _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index a640798c9..27ac4a09e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/loong64/include _const.go @@ -119,6 +118,7 @@ const ( IXOFF = 0x1000 IXON = 0x400 LASX_CTX_MAGIC = 0x41535801 + LBT_CTX_MAGIC = 0x42540001 LSX_CTX_MAGIC = 0x53580001 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 0d5925d34..54694642a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index d72a00e0b..3adb81d75 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips64/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 02ba129f8..2dfe98f0d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mips64le/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 8daa6dd96..f5398f84f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/mipsle/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 63c8fa2f7..c54f152d6 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 930799ec1..76057dc72 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 8605a7dd7..e0c3725e2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/ppc64le/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 95a016f1c..18f2813ed 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/riscv64/include _const.go @@ -228,6 +227,9 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTRACE_GETFDPIC = 0x21 + PTRACE_GETFDPIC_EXEC = 0x0 + PTRACE_GETFDPIC_INTERP = 0x1 RLIMIT_AS = 0x9 RLIMIT_MEMLOCK = 0x8 RLIMIT_NOFILE = 0x7 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 1ae0108f5..11619d4ec 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/s390x/include -fsigned-char _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 1bb7c6333..396d994da 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -Wall -Werror -static -I/tmp/sparc64/include _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go index 72f7420d2..130085df4 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go index 8d4eb0c08..84769a1a3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go index 9eef9749f..602ded003 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -marm _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go index 3b62ba192..efc0406ee 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go index af20e474b..5a6500f83 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m32 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go index 6015fcb2b..a5aeeb979 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go index 8d44955e4..0e9748a72 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go index ae16fe754..4f4449abc 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go index 03d90fe35..76a363f0f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go index 8e2c51b1e..43ca0cdfd 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go index 13d403031..b1b8bb200 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 1afee6a08..d2ddd3176 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && solaris -// +build amd64,solaris // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo -godefs -- -m64 _const.go diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go index fc7d0506f..4dfd2e051 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Hand edited based on zerrors_linux_s390x.go // TODO: auto-generate. diff --git a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go index 97f20ca28..586317c78 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("arm", "arm64"). DO NOT EDIT. //go:build linux && (arm || arm64) -// +build linux -// +build arm arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go index 0b5f79430..d7c881be7 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mips", "mips64"). DO NOT EDIT. //go:build linux && (mips || mips64) -// +build linux -// +build mips mips64 package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go index 2807f7e64..2d2de5d29 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("mipsle", "mips64le"). DO NOT EDIT. //go:build linux && (mipsle || mips64le) -// +build linux -// +build mipsle mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go index 281ea64e3..5adc79fb5 100644 --- a/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go +++ b/vendor/golang.org/x/sys/unix/zptrace_x86_linux.go @@ -1,8 +1,6 @@ // Code generated by linux/mkall.go generatePtracePair("386", "amd64"). DO NOT EDIT. //go:build linux && (386 || amd64) -// +build linux -// +build 386 amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go index d1d1d2331..6ea64a3c0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc -// +build aix,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go index f99a18adc..99ee4399a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 -// +build aix,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go index c4d50ae50..b68a78362 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 && gc -// +build aix,ppc64,gc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go index 6903d3b09..0a87450bf 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build aix && ppc64 && gccgo -// +build aix,ppc64,gccgo package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 1cad561e9..ccb02f240 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build darwin && amd64 -// +build darwin,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index b18edbd0e..1b40b997b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build darwin && arm64 -// +build darwin,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index 0c67df64a..aad65fc79 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build dragonfly && amd64 -// +build dragonfly,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go index e6e05d145..c0096391a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && 386 -// +build freebsd,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go index 7508accac..7664df749 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && amd64 -// +build freebsd,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go index 7b56aead4..ae099182c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && arm -// +build freebsd,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go index cc623dcaa..11fd5d45b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && arm64 -// +build freebsd,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go index 581849197..c3d2d6530 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build freebsd && riscv64 -// +build freebsd,riscv64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go index 6be25cd19..c698cbc01 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build illumos && amd64 -// +build illumos,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 1ff3aec74..1488d2712 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -38,6 +37,21 @@ func fchmodat(dirfd int, path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ioctl(fd int, req uint, arg uintptr) (err error) { _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) if e1 != 0 { @@ -2195,3 +2209,13 @@ func schedGetattr(pid int, attr *SchedAttr, size uint, flags uint) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) { + _, _, e1 := Syscall6(SYS_CACHESTAT, uintptr(fd), uintptr(unsafe.Pointer(crange)), uintptr(unsafe.Pointer(cstat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index 07b549cc2..4def3e9fc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && 386 -// +build linux,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 5f481bf83..fef2bc8ba 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && amd64 -// +build linux,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 824cd52c7..a9fd76a88 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && arm -// +build linux,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index e77aecfe9..460065028 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && arm64 -// +build linux,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go index 806ffd1e1..c8987d264 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && loong64 -// +build linux,loong64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 961a3afb7..921f43061 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips -// +build linux,mips package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index ed05005e9..44f067829 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips64 -// +build linux,mips64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index d365b718f..e7fa0abf0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips64le -// +build linux,mips64le package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index c3f1b8bbd..8c5125675 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mipsle -// +build linux,mipsle package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go index a6574cf98..7392fd45e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc -// +build linux,ppc package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index f40990264..41180434e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64 -// +build linux,ppc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 9dfcc2997..40c6ce7ae 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64le -// +build linux,ppc64le package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 0ab4f2ed7..2cfe34adb 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && riscv64 -// +build linux,riscv64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 6cde32237..61e6f0709 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && s390x -// +build linux,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 5253d65bf..834b84204 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && sparc64 -// +build linux,sparc64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 2df3c5bac..e91ebc14a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && 386 -// +build netbsd,386 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index a60556bab..be28babbc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && amd64 -// +build netbsd,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 9f788917a..fb587e826 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && arm -// +build netbsd,arm package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index 82a4cb2dc..d576438bb 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build netbsd && arm64 -// +build netbsd,arm64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 66b3b6456..a1d061597 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && 386 -// +build openbsd,386 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s index 3dcacd30d..41b561731 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index c5c4cc112..5b2a74097 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && amd64 -// +build openbsd,amd64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s index 2763620b0..4019a656f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 93bfbb328..f6eda1344 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && arm -// +build openbsd,arm package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s index c92231404..ac4af24f9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $4 DATA ·libc_sysctl_trampoline_addr(SB)/4, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $4 +DATA ·libc_fcntl_trampoline_addr(SB)/4, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $4 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $4 DATA ·libc_munmap_trampoline_addr(SB)/4, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $4 +DATA ·libc_getfsstat_trampoline_addr(SB)/4, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $4 DATA ·libc_utimensat_trampoline_addr(SB)/4, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $4 +DATA ·libc_pledge_trampoline_addr(SB)/4, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $4 +DATA ·libc_unveil_trampoline_addr(SB)/4, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index a107b8fda..55df20ae9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && arm64 -// +build openbsd,arm64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s index a6bc32c92..f77d53212 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go index c427de509..8c1155cbc 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && mips64 -// +build openbsd,mips64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s index b4e7bceab..fae140b62 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go index 60c1a99ae..7cc80c58d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && ppc64 -// +build openbsd,ppc64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s index ca3f76600..9d1e0ff06 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -213,6 +213,12 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_fcntl(SB) + RET +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_ppoll(SB) RET @@ -801,8 +807,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_getfsstat(SB) + RET +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_utimensat(SB) RET GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_pledge(SB) + RET +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_unveil(SB) + RET +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go index 52eba360f..0688737f4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build openbsd && riscv64 -// +build openbsd,riscv64 package unix @@ -585,6 +584,32 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fcntl(fd int, cmd int, arg int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_fcntl_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_fcntl_trampoline_addr, uintptr(fd), uintptr(cmd), uintptr(arg)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { r0, _, e1 := syscall_syscall6(libc_ppoll_trampoline_addr, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) n = int(r0) @@ -2213,6 +2238,21 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getfsstat(stat *Statfs_t, bufsize uintptr, flags int) (n int, err error) { + r0, _, e1 := syscall_syscall(libc_getfsstat_trampoline_addr, uintptr(unsafe.Pointer(stat)), uintptr(bufsize), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_getfsstat_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_getfsstat getfsstat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -2229,3 +2269,33 @@ func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error var libc_utimensat_trampoline_addr uintptr //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pledge(promises *byte, execpromises *byte) (err error) { + _, _, e1 := syscall_syscall(libc_pledge_trampoline_addr, uintptr(unsafe.Pointer(promises)), uintptr(unsafe.Pointer(execpromises)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pledge_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pledge pledge "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unveil(path *byte, flags *byte) (err error) { + _, _, e1 := syscall_syscall(libc_unveil_trampoline_addr, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(flags)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_unveil_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_unveil unveil "libc.so" + + diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s index 477a7d5b2..da115f9a4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -178,6 +178,11 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_fcntl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_fcntl(SB) +GLOBL ·libc_fcntl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_fcntl_trampoline_addr(SB)/8, $libc_fcntl_trampoline<>(SB) + TEXT libc_ppoll_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_ppoll(SB) GLOBL ·libc_ppoll_trampoline_addr(SB), RODATA, $8 @@ -668,7 +673,22 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_getfsstat_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_getfsstat(SB) +GLOBL ·libc_getfsstat_trampoline_addr(SB), RODATA, $8 +DATA ·libc_getfsstat_trampoline_addr(SB)/8, $libc_getfsstat_trampoline<>(SB) + TEXT libc_utimensat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_utimensat(SB) GLOBL ·libc_utimensat_trampoline_addr(SB), RODATA, $8 DATA ·libc_utimensat_trampoline_addr(SB)/8, $libc_utimensat_trampoline<>(SB) + +TEXT libc_pledge_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pledge(SB) +GLOBL ·libc_pledge_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pledge_trampoline_addr(SB)/8, $libc_pledge_trampoline<>(SB) + +TEXT libc_unveil_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_unveil(SB) +GLOBL ·libc_unveil_trampoline_addr(SB), RODATA, $8 +DATA ·libc_unveil_trampoline_addr(SB)/8, $libc_unveil_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index b40189464..829b87feb 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build solaris && amd64 -// +build solaris,amd64 package unix diff --git a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go index 1d8fe1d4b..94f011238 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go index 55e048471..3a58ae819 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go index d2243cf83..dcb7a0eb7 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go index 82dc51bd8..db5a7bf13 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go index cbdda1a4a..7be575a77 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go index f55eae1a8..d6e3174c6 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go index e44054470..ee97157d0 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go index a0db82fce..35c3b91d0 100644 --- a/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysctl_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go index f8298ff9b..5edda7687 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go index 5eb433bbf..0dc9e8b4d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go index 703675c0c..308ddf3a1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go index 4e0d96107..418664e3d 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go index 01636b838..34d0b86d7 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go index ad99bc106..b71cf45e2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go index 89dcc4274..e32df1c1e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go index ee37aaa0c..15ad6111f 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 9862853d3..fcf3ecbdd 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux package unix @@ -448,4 +447,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 8901f0f4e..f56dc2504 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux package unix @@ -370,4 +369,6 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 + SYS_MAP_SHADOW_STACK = 453 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 6902c37ee..974bf2467 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux package unix @@ -412,4 +411,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index a6d3dff81..39a2739e2 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux package unix @@ -315,4 +314,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index b18f3f710..cf9c9d77e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux package unix @@ -309,4 +308,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index 0302e5e3d..10b7362ef 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux package unix @@ -432,4 +431,5 @@ const ( SYS_FUTEX_WAITV = 4449 SYS_SET_MEMPOLICY_HOME_NODE = 4450 SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 6693ba4a0..cd4d8b4fd 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux package unix @@ -362,4 +361,5 @@ const ( SYS_FUTEX_WAITV = 5449 SYS_SET_MEMPOLICY_HOME_NODE = 5450 SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index fd93f4987..2c0efca81 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux package unix @@ -362,4 +361,5 @@ const ( SYS_FUTEX_WAITV = 5449 SYS_SET_MEMPOLICY_HOME_NODE = 5450 SYS_CACHESTAT = 5451 + SYS_FCHMODAT2 = 5452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index 760ddcadc..a72e31d39 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux package unix @@ -432,4 +431,5 @@ const ( SYS_FUTEX_WAITV = 4449 SYS_SET_MEMPOLICY_HOME_NODE = 4450 SYS_CACHESTAT = 4451 + SYS_FCHMODAT2 = 4452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index cff2b2555..c7d1e3747 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux package unix @@ -439,4 +438,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index a4b2405d0..f4d4838c8 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux package unix @@ -411,4 +410,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index aca54b4e3..b64f0e591 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux package unix @@ -411,4 +410,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 9d1738d64..95711195a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux package unix @@ -316,4 +315,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 022878dc8..f94e943bc 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux package unix @@ -377,4 +376,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 4100a761c..ba0c2bc51 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux package unix @@ -390,4 +389,5 @@ const ( SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 SYS_CACHESTAT = 451 + SYS_FCHMODAT2 = 452 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go index 3a6699eba..b2aa8cd49 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go index 5677cd4f1..524a1b1c9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go index e784cb6db..d59b943ac 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go index bd4952efa..31e771d53 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go index 597733813..9fd77c6cb 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go index 16af29189..af10af28c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go index f59b18a97..cc2028af4 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go index 721ef5910..c06dd4415 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go index 01c43a01f..9ddbf3e08 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go index f258cfa24..19a6ee413 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go index 07919e0ec..05192a782 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go index 073daad43..b2e308581 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go index 7a8161c1d..3e6d57cae 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && aix -// +build ppc,aix package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go index 07ed733c5..3a219bdce 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && aix -// +build ppc64,aix package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 690cefc3d..091d107f3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && darwin -// +build amd64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 5bffc10ea..28ff4ef74 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && darwin -// +build arm64,darwin package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index d0ba8e9b8..30e405bb4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && dragonfly -// +build amd64,dragonfly package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 29dc48337..6cbd094a3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && freebsd -// +build 386,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 0a89b2890..7c03b6ee7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && freebsd -// +build amd64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index c8666bb15..422107ee8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && freebsd -// +build arm,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 88fb48a88..505a12acf 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && freebsd -// +build arm64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go index 698dc975e..cc986c790 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && freebsd -// +build riscv64,freebsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 18aa70b42..bbf8399ff 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -1,7 +1,6 @@ // Code generated by mkmerge; DO NOT EDIT. //go:build linux -// +build linux package unix @@ -2672,6 +2671,7 @@ const ( BPF_PROG_TYPE_LSM = 0x1d BPF_PROG_TYPE_SK_LOOKUP = 0x1e BPF_PROG_TYPE_SYSCALL = 0x1f + BPF_PROG_TYPE_NETFILTER = 0x20 BPF_CGROUP_INET_INGRESS = 0x0 BPF_CGROUP_INET_EGRESS = 0x1 BPF_CGROUP_INET_SOCK_CREATE = 0x2 @@ -2716,6 +2716,11 @@ const ( BPF_PERF_EVENT = 0x29 BPF_TRACE_KPROBE_MULTI = 0x2a BPF_LSM_CGROUP = 0x2b + BPF_STRUCT_OPS = 0x2c + BPF_NETFILTER = 0x2d + BPF_TCX_INGRESS = 0x2e + BPF_TCX_EGRESS = 0x2f + BPF_TRACE_UPROBE_MULTI = 0x30 BPF_LINK_TYPE_UNSPEC = 0x0 BPF_LINK_TYPE_RAW_TRACEPOINT = 0x1 BPF_LINK_TYPE_TRACING = 0x2 @@ -2726,6 +2731,18 @@ const ( BPF_LINK_TYPE_PERF_EVENT = 0x7 BPF_LINK_TYPE_KPROBE_MULTI = 0x8 BPF_LINK_TYPE_STRUCT_OPS = 0x9 + BPF_LINK_TYPE_NETFILTER = 0xa + BPF_LINK_TYPE_TCX = 0xb + BPF_LINK_TYPE_UPROBE_MULTI = 0xc + BPF_PERF_EVENT_UNSPEC = 0x0 + BPF_PERF_EVENT_UPROBE = 0x1 + BPF_PERF_EVENT_URETPROBE = 0x2 + BPF_PERF_EVENT_KPROBE = 0x3 + BPF_PERF_EVENT_KRETPROBE = 0x4 + BPF_PERF_EVENT_TRACEPOINT = 0x5 + BPF_PERF_EVENT_EVENT = 0x6 + BPF_F_KPROBE_MULTI_RETURN = 0x1 + BPF_F_UPROBE_MULTI_RETURN = 0x1 BPF_ANY = 0x0 BPF_NOEXIST = 0x1 BPF_EXIST = 0x2 @@ -2743,6 +2760,8 @@ const ( BPF_F_MMAPABLE = 0x400 BPF_F_PRESERVE_ELEMS = 0x800 BPF_F_INNER_MAP = 0x1000 + BPF_F_LINK = 0x2000 + BPF_F_PATH_FD = 0x4000 BPF_STATS_RUN_TIME = 0x0 BPF_STACK_BUILD_ID_EMPTY = 0x0 BPF_STACK_BUILD_ID_VALID = 0x1 @@ -2763,6 +2782,7 @@ const ( BPF_F_ZERO_CSUM_TX = 0x2 BPF_F_DONT_FRAGMENT = 0x4 BPF_F_SEQ_NUMBER = 0x8 + BPF_F_NO_TUNNEL_KEY = 0x10 BPF_F_TUNINFO_FLAGS = 0x10 BPF_F_INDEX_MASK = 0xffffffff BPF_F_CURRENT_CPU = 0xffffffff @@ -2779,6 +2799,8 @@ const ( BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 0x10 BPF_F_ADJ_ROOM_NO_CSUM_RESET = 0x20 BPF_F_ADJ_ROOM_ENCAP_L2_ETH = 0x40 + BPF_F_ADJ_ROOM_DECAP_L3_IPV4 = 0x80 + BPF_F_ADJ_ROOM_DECAP_L3_IPV6 = 0x100 BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 0x38 BPF_F_SYSCTL_BASE_NAME = 0x1 @@ -2867,6 +2889,8 @@ const ( BPF_DEVCG_DEV_CHAR = 0x2 BPF_FIB_LOOKUP_DIRECT = 0x1 BPF_FIB_LOOKUP_OUTPUT = 0x2 + BPF_FIB_LOOKUP_SKIP_NEIGH = 0x4 + BPF_FIB_LOOKUP_TBID = 0x8 BPF_FIB_LKUP_RET_SUCCESS = 0x0 BPF_FIB_LKUP_RET_BLACKHOLE = 0x1 BPF_FIB_LKUP_RET_UNREACHABLE = 0x2 @@ -2902,6 +2926,7 @@ const ( BPF_CORE_ENUMVAL_EXISTS = 0xa BPF_CORE_ENUMVAL_VALUE = 0xb BPF_CORE_TYPE_MATCHES = 0xc + BPF_F_TIMER_ABS = 0x1 ) const ( @@ -2980,6 +3005,12 @@ type LoopInfo64 struct { Encrypt_key [32]uint8 Init [2]uint64 } +type LoopConfig struct { + Fd uint32 + Size uint32 + Info LoopInfo64 + _ [8]uint64 +} type TIPCSocketAddr struct { Ref uint32 @@ -5883,3 +5914,15 @@ type SchedAttr struct { } const SizeofSchedAttr = 0x38 + +type Cachestat_t struct { + Cache uint64 + Dirty uint64 + Writeback uint64 + Evicted uint64 + Recently_evicted uint64 +} +type CachestatRange struct { + Off uint64 + Len uint64 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 6d8acbcc5..438a30aff 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux -// +build 386,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 59293c688..adceca355 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux -// +build amd64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 40cfa38c2..eeaa00a37 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux -// +build arm,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 055bc4216..6739aa91d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux -// +build arm64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index f28affbc6..9920ef631 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux -// +build loong64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 9d71e7ccd..2923b799a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux -// +build mips,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index fd5ccd332..ce2750ee4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux -// +build mips64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 7704de77a..3038811d7 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux -// +build mips64le,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index df00b8757..efc6fed18 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux -// +build mipsle,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 0942840db..9a654b75a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux -// +build ppc,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 034874395..40d358e33 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux -// +build ppc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index bad067047..148c6ceb8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux -// +build ppc64le,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 1b4c97c32..72ba81543 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux -// +build riscv64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index aa268d025..71e765508 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux -// +build s390x,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 444045b6c..4abbdb9de 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux -// +build sparc64,linux package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go index 9bc4c8f9d..f22e7947d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && netbsd -// +build 386,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go index bb05f655d..066a7d83d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && netbsd -// +build amd64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go index db40e3a19..439548ec9 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && netbsd -// +build arm,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go index 11121151c..16085d3bb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && netbsd -// +build arm64,netbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index 26eba23b7..afd13a3af 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && openbsd -// +build 386,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index 5a5479886..5d97f1f9b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && openbsd -// +build amd64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index be58c4e1f..34871cdc1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && openbsd -// +build arm,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index 52338266c..5911bceb3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && openbsd -// +build arm64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index 605cfdb12..e4f24f3bc 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && openbsd -// +build mips64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go index d6724c010..ca50a7930 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_ppc64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && openbsd -// +build ppc64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go index ddfd27a43..d7d7f7902 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_openbsd_riscv64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && openbsd -// +build riscv64,openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 0400747c6..14160576d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -2,7 +2,6 @@ // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && solaris -// +build amd64,solaris package unix diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go index aec1efcb3..54f31be63 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build zos && s390x -// +build zos,s390x // Hand edited based on ztypes_linux_s390x.go // TODO: auto-generate. diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go index a20ebea63..ce2d713d6 100644 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ b/vendor/golang.org/x/sys/windows/aliases.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && go1.9 -// +build windows,go1.9 package windows diff --git a/vendor/golang.org/x/sys/windows/empty.s b/vendor/golang.org/x/sys/windows/empty.s index fdbbbcd31..ba64caca5 100644 --- a/vendor/golang.org/x/sys/windows/empty.s +++ b/vendor/golang.org/x/sys/windows/empty.s @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.12 -// +build !go1.12 // This file is here to allow bodyless functions with go:linkname for Go 1.11 // and earlier (see https://golang.org/issue/23311). diff --git a/vendor/golang.org/x/sys/windows/eventlog.go b/vendor/golang.org/x/sys/windows/eventlog.go index 2cd60645e..6c366955d 100644 --- a/vendor/golang.org/x/sys/windows/eventlog.go +++ b/vendor/golang.org/x/sys/windows/eventlog.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/mksyscall.go b/vendor/golang.org/x/sys/windows/mksyscall.go index 8563f79c5..dbcdb090c 100644 --- a/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/mksyscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build generate -// +build generate package windows diff --git a/vendor/golang.org/x/sys/windows/race.go b/vendor/golang.org/x/sys/windows/race.go index 9196b089c..0f1bdc386 100644 --- a/vendor/golang.org/x/sys/windows/race.go +++ b/vendor/golang.org/x/sys/windows/race.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && race -// +build windows,race package windows diff --git a/vendor/golang.org/x/sys/windows/race0.go b/vendor/golang.org/x/sys/windows/race0.go index 7bae4817a..0c78da78b 100644 --- a/vendor/golang.org/x/sys/windows/race0.go +++ b/vendor/golang.org/x/sys/windows/race0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows && !race -// +build windows,!race package windows diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index c44a1b963..a9dc6308d 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/str.go b/vendor/golang.org/x/sys/windows/str.go index 4fc01434e..6a4f9ce6a 100644 --- a/vendor/golang.org/x/sys/windows/str.go +++ b/vendor/golang.org/x/sys/windows/str.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/syscall.go b/vendor/golang.org/x/sys/windows/syscall.go index 8732cdb95..e85ed6b9c 100644 --- a/vendor/golang.org/x/sys/windows/syscall.go +++ b/vendor/golang.org/x/sys/windows/syscall.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build windows -// +build windows // Package windows contains an interface to the low-level operating system // primitives. OS details vary depending on the underlying system, and diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 35cfc57ca..47dc57967 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -155,6 +155,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW //sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW //sys SetDefaultDllDirectories(directoryFlags uint32) (err error) +//sys AddDllDirectory(path *uint16) (cookie uintptr, err error) = kernel32.AddDllDirectory +//sys RemoveDllDirectory(cookie uintptr) (err error) = kernel32.RemoveDllDirectory //sys SetDllDirectory(path string) (err error) = kernel32.SetDllDirectoryW //sys GetVersion() (ver uint32, err error) //sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW @@ -233,6 +235,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys getTickCount64() (ms uint64) = kernel32.GetTickCount64 +//sys GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) //sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW //sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW @@ -969,7 +972,8 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) { if n > 0 { sl += int32(n) + 1 } - if sa.raw.Path[0] == '@' { + if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { + // Check sl > 3 so we don't change unnamed socket behavior. sa.raw.Path[0] = 0 // Don't count trailing NUL for abstract address. sl-- diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index b88dc7c85..359780f6a 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -1094,7 +1094,33 @@ const ( SOMAXCONN = 0x7fffffff - TCP_NODELAY = 1 + TCP_NODELAY = 1 + TCP_EXPEDITED_1122 = 2 + TCP_KEEPALIVE = 3 + TCP_MAXSEG = 4 + TCP_MAXRT = 5 + TCP_STDURG = 6 + TCP_NOURG = 7 + TCP_ATMARK = 8 + TCP_NOSYNRETRIES = 9 + TCP_TIMESTAMPS = 10 + TCP_OFFLOAD_PREFERENCE = 11 + TCP_CONGESTION_ALGORITHM = 12 + TCP_DELAY_FIN_ACK = 13 + TCP_MAXRTMS = 14 + TCP_FASTOPEN = 15 + TCP_KEEPCNT = 16 + TCP_KEEPIDLE = TCP_KEEPALIVE + TCP_KEEPINTVL = 17 + TCP_FAIL_CONNECT_ON_ICMP_ERROR = 18 + TCP_ICMP_ERROR_INFO = 19 + + UDP_NOCHECKSUM = 1 + UDP_SEND_MSG_SIZE = 2 + UDP_RECV_MAX_COALESCED_SIZE = 3 + UDP_CHECKSUM_COVERAGE = 20 + + UDP_COALESCED_INFO = 3 SHUT_RD = 0 SHUT_WR = 1 diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 8b1688de4..146a1f019 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -184,6 +184,7 @@ var ( procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") procCancelIo = modkernel32.NewProc("CancelIo") procCancelIoEx = modkernel32.NewProc("CancelIoEx") @@ -253,6 +254,7 @@ var ( procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetFileTime = modkernel32.NewProc("GetFileTime") procGetFileType = modkernel32.NewProc("GetFileType") procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") @@ -329,6 +331,7 @@ var ( procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory") procReleaseMutex = modkernel32.NewProc("ReleaseMutex") procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procRemoveDllDirectory = modkernel32.NewProc("RemoveDllDirectory") procResetEvent = modkernel32.NewProc("ResetEvent") procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole") procResumeThread = modkernel32.NewProc("ResumeThread") @@ -1604,6 +1607,15 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { return } +func AddDllDirectory(path *uint16) (cookie uintptr, err error) { + r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + cookie = uintptr(r0) + if cookie == 0 { + err = errnoErr(e1) + } + return +} + func AssignProcessToJobObject(job Handle, process Handle) (err error) { r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) if r1 == 0 { @@ -2185,6 +2197,14 @@ func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, return } +func GetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetFileType(filehandle Handle) (n uint32, err error) { r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) n = uint32(r0) @@ -2870,6 +2890,14 @@ func RemoveDirectory(path *uint16) (err error) { return } +func RemoveDllDirectory(cookie uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procRemoveDllDirectory.Addr(), 1, uintptr(cookie), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ResetEvent(event Handle) (err error) { r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) if r1 == 0 { diff --git a/vendor/golang.org/x/term/term_unix.go b/vendor/golang.org/x/term/term_unix.go index 62c2b3f41..1ad0ddfe3 100644 --- a/vendor/golang.org/x/term/term_unix.go +++ b/vendor/golang.org/x/term/term_unix.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package term diff --git a/vendor/golang.org/x/term/term_unix_bsd.go b/vendor/golang.org/x/term/term_unix_bsd.go index 853b3d698..9dbf54629 100644 --- a/vendor/golang.org/x/term/term_unix_bsd.go +++ b/vendor/golang.org/x/term/term_unix_bsd.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build darwin || dragonfly || freebsd || netbsd || openbsd -// +build darwin dragonfly freebsd netbsd openbsd package term diff --git a/vendor/golang.org/x/term/term_unix_other.go b/vendor/golang.org/x/term/term_unix_other.go index 1e8955c93..1b36de799 100644 --- a/vendor/golang.org/x/term/term_unix_other.go +++ b/vendor/golang.org/x/term/term_unix_other.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build aix || linux || solaris || zos -// +build aix linux solaris zos package term diff --git a/vendor/golang.org/x/term/term_unsupported.go b/vendor/golang.org/x/term/term_unsupported.go index f1df85065..3c409e588 100644 --- a/vendor/golang.org/x/term/term_unsupported.go +++ b/vendor/golang.org/x/term/term_unsupported.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !zos && !windows && !solaris && !plan9 -// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!zos,!windows,!solaris,!plan9 package term diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go b/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go index 8a7392c4a..784bb8808 100644 --- a/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go +++ b/vendor/golang.org/x/text/secure/bidirule/bidirule10.0.0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build go1.10 -// +build go1.10 package bidirule diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go b/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go index bb0a92001..8e1e94395 100644 --- a/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go +++ b/vendor/golang.org/x/text/secure/bidirule/bidirule9.0.0.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. //go:build !go1.10 -// +build !go1.10 package bidirule diff --git a/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.go index 42fa8d72c..d2bd71181 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables10.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.10 && !go1.13 -// +build go1.10,!go1.13 package bidi diff --git a/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.go index 56a0e1ea2..f76bdca27 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables11.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.13 && !go1.14 -// +build go1.13,!go1.14 package bidi diff --git a/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go index baacf32b4..3aa2c3bdf 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables12.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.14 && !go1.16 -// +build go1.14,!go1.16 package bidi diff --git a/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go index ffadb7beb..a71375790 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.16 && !go1.21 -// +build go1.16,!go1.21 package bidi diff --git a/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.go index 92cce5802..f15746f7d 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables15.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.21 -// +build go1.21 package bidi diff --git a/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.go b/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.go index f517fdb20..c164d3791 100644 --- a/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.go +++ b/vendor/golang.org/x/text/unicode/bidi/tables9.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build !go1.10 -// +build !go1.10 package bidi diff --git a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go index f5a078827..1af161c75 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.10 && !go1.13 -// +build go1.10,!go1.13 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go index cb7239c43..eb73ecc37 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables11.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.13 && !go1.14 -// +build go1.13,!go1.14 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go index 11b273300..276cb8d8c 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables12.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.14 && !go1.16 -// +build go1.14,!go1.16 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go index f65785e8a..0cceffd73 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables13.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.16 && !go1.21 -// +build go1.16,!go1.21 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables15.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables15.0.0.go index e1858b879..b0819e42d 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables15.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables15.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build go1.21 -// +build go1.21 package norm diff --git a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go index 0175eae50..bf65457d9 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go @@ -1,7 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. //go:build !go1.10 -// +build !go1.10 package norm diff --git a/vendor/modules.txt b/vendor/modules.txt index 7ac34b8ba..1e597560f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -498,8 +498,8 @@ go.uber.org/zap/zapcore # go4.org v0.0.0-20200104003542-c7e774b10ea0 ## explicit go4.org/errorutil -# golang.org/x/crypto v0.14.0 -## explicit; go 1.17 +# golang.org/x/crypto v0.17.0 +## explicit; go 1.18 golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/pbkdf2 @@ -533,17 +533,17 @@ golang.org/x/oauth2/internal # golang.org/x/sync v0.4.0 ## explicit; go 1.17 golang.org/x/sync/errgroup -# golang.org/x/sys v0.13.0 -## explicit; go 1.17 +# golang.org/x/sys v0.15.0 +## explicit; go 1.18 golang.org/x/sys/execabs golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.13.0 -## explicit; go 1.17 +# golang.org/x/term v0.15.0 +## explicit; go 1.18 golang.org/x/term -# golang.org/x/text v0.13.0 -## explicit; go 1.17 +# golang.org/x/text v0.14.0 +## explicit; go 1.18 golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex From 7c73437c75bc55198c548c9d97a6f0acd6086442 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 09:55:49 +0200 Subject: [PATCH 26/61] Change layout of the pkg/host to simplify testing The commit includes following changes: * move interfaces and public types(types that used in interfaces) to a separate package * move implementation of the interfaces to internal pkgs to avoid unwanted imports by users * move StoreManager to a separate package These changes are required to be able to generate mocks for Interfaces in the host package which can be used to tests other interfaces in the host package. Signed-off-by: Yury Kulazhenkov --- pkg/helper/host.go | 9 +- pkg/helper/mock/mock_helper.go | 41 ++--- pkg/host/interface.go | 55 ------ pkg/host/internal/common.go | 19 +++ pkg/host/{ => internal/kernel}/kernel.go | 90 ++-------- pkg/host/{ => internal/kernel}/kernel_test.go | 7 +- pkg/host/{ => internal/kernel}/suite_test.go | 6 +- pkg/host/{ => internal/network}/network.go | 28 +-- pkg/host/{ => internal/service}/service.go | 89 +++------- pkg/host/{ => internal/sriov}/sriov.go | 53 ++---- pkg/host/{ => internal/udev}/udev.go | 17 +- pkg/host/manager.go | 46 +++++ pkg/host/mock/mock_store.go | 108 ------------ pkg/host/store/mock/mock_store.go | 108 ++++++++++++ pkg/host/{ => store}/store.go | 27 ++- pkg/host/types/interfaces.go | 160 ++++++++++++++++++ pkg/host/types/types.go | 43 +++++ pkg/plugins/k8s/k8s_plugin.go | 38 ++--- 18 files changed, 494 insertions(+), 450 deletions(-) delete mode 100644 pkg/host/interface.go create mode 100644 pkg/host/internal/common.go rename pkg/host/{ => internal/kernel}/kernel.go (85%) rename pkg/host/{ => internal/kernel}/kernel_test.go (98%) rename pkg/host/{ => internal/kernel}/suite_test.go (79%) rename pkg/host/{ => internal/network}/network.go (82%) rename pkg/host/{ => internal/service}/service.go (66%) rename pkg/host/{ => internal/sriov}/sriov.go (88%) rename pkg/host/{ => internal/udev}/udev.go (89%) create mode 100644 pkg/host/manager.go delete mode 100644 pkg/host/mock/mock_store.go create mode 100644 pkg/host/store/mock/mock_store.go rename pkg/host/{ => store}/store.go (85%) create mode 100644 pkg/host/types/interfaces.go create mode 100644 pkg/host/types/types.go diff --git a/pkg/helper/host.go b/pkg/helper/host.go index df3325762..5829d161a 100644 --- a/pkg/helper/host.go +++ b/pkg/helper/host.go @@ -4,6 +4,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" ) @@ -12,21 +13,21 @@ import ( type HostHelpersInterface interface { utils.CmdInterface host.HostManagerInterface - host.StoreManagerInterface + store.ManagerInterface mlx.MellanoxInterface } type hostHelpers struct { utils.CmdInterface host.HostManagerInterface - host.StoreManagerInterface + store.ManagerInterface mlx.MellanoxInterface } // Use for unit tests func NewHostHelpers(utilsHelper utils.CmdInterface, hostManager host.HostManagerInterface, - storeManager host.StoreManagerInterface, + storeManager store.ManagerInterface, mlxHelper mlx.MellanoxInterface) HostHelpersInterface { return &hostHelpers{utilsHelper, hostManager, storeManager, mlxHelper} } @@ -35,7 +36,7 @@ func NewDefaultHostHelpers() (HostHelpersInterface, error) { utilsHelper := utils.New() mlxHelper := mlx.New(utilsHelper) hostManager := host.NewHostManager(utilsHelper) - storeManager, err := host.NewStoreManager() + storeManager, err := store.NewManager() if err != nil { log.Log.Error(err, "failed to create store manager") return nil, err diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index 75015a925..c00180cd3 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -11,7 +11,8 @@ import ( gomock "github.com/golang/mock/gomock" ghw "github.com/jaypipes/ghw" v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - host "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + store "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" + types "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" mlxutils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" netlink "github.com/vishvananda/netlink" ) @@ -82,17 +83,17 @@ func (mr *MockHostHelpersInterfaceMockRecorder) BindDpdkDriver(arg0, arg1 interf } // BindDriverByBusAndDevice mocks base method. -func (m *MockHostHelpersInterface) BindDriverByBusAndDevice(arg0, arg1, arg2 string) error { +func (m *MockHostHelpersInterface) BindDriverByBusAndDevice(bus, device, driver string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BindDriverByBusAndDevice", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "BindDriverByBusAndDevice", bus, device, driver) ret0, _ := ret[0].(error) return ret0 } // BindDriverByBusAndDevice indicates an expected call of BindDriverByBusAndDevice. -func (mr *MockHostHelpersInterfaceMockRecorder) BindDriverByBusAndDevice(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) BindDriverByBusAndDevice(bus, device, driver interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDriverByBusAndDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDriverByBusAndDevice), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDriverByBusAndDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDriverByBusAndDevice), bus, device, driver) } // Chroot mocks base method. @@ -125,7 +126,7 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ClearPCIAddressFolder() *gomock. } // CompareServices mocks base method. -func (m *MockHostHelpersInterface) CompareServices(serviceA, serviceB *host.Service) (bool, error) { +func (m *MockHostHelpersInterface) CompareServices(serviceA, serviceB *types.Service) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CompareServices", serviceA, serviceB) ret0, _ := ret[0].(bool) @@ -168,7 +169,7 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovDeviceVirtual(iface i } // ConfigSriovInterfaces mocks base method. -func (m *MockHostHelpersInterface) ConfigSriovInterfaces(arg0 host.StoreManagerInterface, arg1 []v1.Interface, arg2 []v1.InterfaceExt, arg3 map[string]bool) error { +func (m *MockHostHelpersInterface) ConfigSriovInterfaces(arg0 store.ManagerInterface, arg1 []v1.Interface, arg2 []v1.InterfaceExt, arg3 map[string]bool) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ConfigSriovInterfaces", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) @@ -182,7 +183,7 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovInterfaces(arg0, arg1 } // DiscoverSriovDevices mocks base method. -func (m *MockHostHelpersInterface) DiscoverSriovDevices(arg0 host.StoreManagerInterface) ([]v1.InterfaceExt, error) { +func (m *MockHostHelpersInterface) DiscoverSriovDevices(arg0 store.ManagerInterface) ([]v1.InterfaceExt, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DiscoverSriovDevices", arg0) ret0, _ := ret[0].([]v1.InterfaceExt) @@ -227,7 +228,7 @@ func (mr *MockHostHelpersInterfaceMockRecorder) EnableRDMAOnRHELMachine() *gomoc } // EnableService mocks base method. -func (m *MockHostHelpersInterface) EnableService(service *host.Service) error { +func (m *MockHostHelpersInterface) EnableService(service *types.Service) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "EnableService", service) ret0, _ := ret[0].(error) @@ -687,10 +688,10 @@ func (mr *MockHostHelpersInterfaceMockRecorder) RdmaIsLoaded() *gomock.Call { } // ReadScriptManifestFile mocks base method. -func (m *MockHostHelpersInterface) ReadScriptManifestFile(path string) (*host.ScriptManifestFile, error) { +func (m *MockHostHelpersInterface) ReadScriptManifestFile(path string) (*types.ScriptManifestFile, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadScriptManifestFile", path) - ret0, _ := ret[0].(*host.ScriptManifestFile) + ret0, _ := ret[0].(*types.ScriptManifestFile) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -702,10 +703,10 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReadScriptManifestFile(path inte } // ReadService mocks base method. -func (m *MockHostHelpersInterface) ReadService(arg0 string) (*host.Service, error) { +func (m *MockHostHelpersInterface) ReadService(arg0 string) (*types.Service, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadService", arg0) - ret0, _ := ret[0].(*host.Service) + ret0, _ := ret[0].(*types.Service) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -717,10 +718,10 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReadService(arg0 interface{}) *g } // ReadServiceInjectionManifestFile mocks base method. -func (m *MockHostHelpersInterface) ReadServiceInjectionManifestFile(path string) (*host.Service, error) { +func (m *MockHostHelpersInterface) ReadServiceInjectionManifestFile(path string) (*types.Service, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadServiceInjectionManifestFile", path) - ret0, _ := ret[0].(*host.Service) + ret0, _ := ret[0].(*types.Service) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -732,10 +733,10 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReadServiceInjectionManifestFile } // ReadServiceManifestFile mocks base method. -func (m *MockHostHelpersInterface) ReadServiceManifestFile(path string) (*host.Service, error) { +func (m *MockHostHelpersInterface) ReadServiceManifestFile(path string) (*types.Service, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadServiceManifestFile", path) - ret0, _ := ret[0].(*host.Service) + ret0, _ := ret[0].(*types.Service) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -775,14 +776,14 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReloadDriver(arg0 interface{}) * } // RemoveFromService mocks base method. -func (m *MockHostHelpersInterface) RemoveFromService(service *host.Service, options ...*unit.UnitOption) (*host.Service, error) { +func (m *MockHostHelpersInterface) RemoveFromService(service *types.Service, options ...*unit.UnitOption) (*types.Service, error) { m.ctrl.T.Helper() varargs := []interface{}{service} for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "RemoveFromService", varargs...) - ret0, _ := ret[0].(*host.Service) + ret0, _ := ret[0].(*types.Service) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -1037,7 +1038,7 @@ func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverIfNeeded(arg0, arg1 } // UpdateSystemService mocks base method. -func (m *MockHostHelpersInterface) UpdateSystemService(serviceObj *host.Service) error { +func (m *MockHostHelpersInterface) UpdateSystemService(serviceObj *types.Service) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UpdateSystemService", serviceObj) ret0, _ := ret[0].(error) diff --git a/pkg/host/interface.go b/pkg/host/interface.go deleted file mode 100644 index edccfd5c8..000000000 --- a/pkg/host/interface.go +++ /dev/null @@ -1,55 +0,0 @@ -package host - -import ( - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" -) - -const ( - hostPathFromDaemon = consts.Host - redhatReleaseFile = "/etc/redhat-release" - rhelRDMAConditionFile = "/usr/libexec/rdma-init-kernel" - rhelRDMAServiceName = "rdma" - rhelPackageManager = "yum" - - ubuntuRDMAConditionFile = "/usr/sbin/rdma-ndd" - ubuntuRDMAServiceName = "rdma-ndd" - ubuntuPackageManager = "apt-get" - - genericOSReleaseFile = "/etc/os-release" -) - -// Contains all the host manipulation functions -type HostManagerInterface interface { - KernelInterface - NetworkInterface - ServiceInterface - UdevInterface - SriovInterface -} - -type hostManager struct { - utils.CmdInterface - KernelInterface - NetworkInterface - ServiceInterface - UdevInterface - SriovInterface -} - -func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { - k := newKernelInterface(utilsInterface) - n := newNetworkInterface(utilsInterface) - sv := newServiceInterface(utilsInterface) - u := newUdevInterface(utilsInterface) - sr := newSriovInterface(utilsInterface, k, n, u) - - return &hostManager{ - utilsInterface, - k, - n, - sv, - u, - sr, - } -} diff --git a/pkg/host/internal/common.go b/pkg/host/internal/common.go new file mode 100644 index 000000000..b32d2cd93 --- /dev/null +++ b/pkg/host/internal/common.go @@ -0,0 +1,19 @@ +package internal + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" +) + +const ( + HostPathFromDaemon = consts.Host + RedhatReleaseFile = "/etc/redhat-release" + RhelRDMAConditionFile = "/usr/libexec/rdma-init-kernel" + RhelRDMAServiceName = "rdma" + RhelPackageManager = "yum" + + UbuntuRDMAConditionFile = "/usr/sbin/rdma-ndd" + UbuntuRDMAServiceName = "rdma-ndd" + UbuntuPackageManager = "apt-get" + + GenericOSReleaseFile = "/etc/os-release" +) diff --git a/pkg/host/kernel.go b/pkg/host/internal/kernel/kernel.go similarity index 85% rename from pkg/host/kernel.go rename to pkg/host/internal/kernel/kernel.go index 171807d95..3b3ab5fe6 100644 --- a/pkg/host/kernel.go +++ b/pkg/host/internal/kernel/kernel.go @@ -1,4 +1,4 @@ -package host +package kernel import ( "errors" @@ -11,77 +11,17 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) -type KernelInterface interface { - // TryEnableTun load the tun kernel module - TryEnableTun() - // TryEnableVhostNet load the vhost-net kernel module - TryEnableVhostNet() - // TryEnableRdma tries to enable RDMA on the machine base on the operating system - // if the package doesn't exist it will also will try to install it - // supported operating systems are RHEL RHCOS and ubuntu - TryEnableRdma() (bool, error) - // TriggerUdevEvent triggers a udev event - TriggerUdevEvent() error - // GetCurrentKernelArgs reads the /proc/cmdline to check the current kernel arguments - GetCurrentKernelArgs() (string, error) - // IsKernelArgsSet check is the requested kernel arguments are set - IsKernelArgsSet(string, string) bool - // Unbind unbinds a virtual function from is current driver - Unbind(string) error - // BindDpdkDriver binds the virtual function to a DPDK driver - BindDpdkDriver(string, string) error - // BindDefaultDriver binds the virtual function to is default driver - BindDefaultDriver(string) error - // BindDriverByBusAndDevice binds device to the provided driver - // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" - // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA - // driver - the name of the driver, e.g. vfio-pci or vhost_vdpa. - BindDriverByBusAndDevice(bus, device, driver string) error - // HasDriver returns try if the virtual function is bind to a driver - HasDriver(string) (bool, string) - // RebindVfToDefaultDriver rebinds the virtual function to is default driver - RebindVfToDefaultDriver(string) error - // UnbindDriverIfNeeded unbinds the virtual function from a driver if needed - UnbindDriverIfNeeded(string, bool) error - // UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver - // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" - // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA - UnbindDriverByBusAndDevice(bus, device string) error - // LoadKernelModule loads a kernel module to the host - LoadKernelModule(name string, args ...string) error - // IsKernelModuleLoaded returns try if the requested kernel module is loaded - IsKernelModuleLoaded(string) (bool, error) - // ReloadDriver reloads a requested driver - ReloadDriver(string) error - // IsKernelLockdownMode returns true if the kernel is in lockdown mode - IsKernelLockdownMode() bool - // IsRHELSystem returns try if the system is a RHEL base - IsRHELSystem() (bool, error) - // IsUbuntuSystem returns try if the system is an ubuntu base - IsUbuntuSystem() (bool, error) - // IsCoreOS returns true if the system is a CoreOS or RHCOS base - IsCoreOS() (bool, error) - // RdmaIsLoaded returns try if RDMA kernel modules are loaded - RdmaIsLoaded() (bool, error) - // EnableRDMA enable RDMA on the system - EnableRDMA(string, string, string) (bool, error) - // InstallRDMA install RDMA packages on the system - InstallRDMA(string) error - // EnableRDMAOnRHELMachine enable RDMA on a RHEL base system - EnableRDMAOnRHELMachine() (bool, error) - // GetOSPrettyName returns OS name - GetOSPrettyName() (string, error) -} - type kernel struct { utilsHelper utils.CmdInterface } -func newKernelInterface(utilsHelper utils.CmdInterface) KernelInterface { +func New(utilsHelper utils.CmdInterface) types.KernelInterface { return &kernel{utilsHelper: utilsHelper} } @@ -384,7 +324,7 @@ func (k *kernel) EnableRDMAOnRHELMachine() (bool, error) { // RHEL log.Log.Info("EnableRDMAOnRHELMachine(): enabling RDMA on RHEL machine") - isRDMAEnable, err := k.EnableRDMA(rhelRDMAConditionFile, rhelRDMAServiceName, rhelPackageManager) + isRDMAEnable, err := k.EnableRDMA(internal.RhelRDMAConditionFile, internal.RhelRDMAServiceName, internal.RhelPackageManager) if err != nil { log.Log.Error(err, "EnableRDMAOnRHELMachine(): failed to enable RDMA on RHEL machine") return false, err @@ -413,7 +353,7 @@ func (k *kernel) EnableRDMAOnRHELMachine() (bool, error) { func (k *kernel) EnableRDMAOnUbuntuMachine() (bool, error) { log.Log.Info("EnableRDMAOnUbuntuMachine(): enabling RDMA on RHEL machine") - isRDMAEnable, err := k.EnableRDMA(ubuntuRDMAConditionFile, ubuntuRDMAServiceName, ubuntuPackageManager) + isRDMAEnable, err := k.EnableRDMA(internal.UbuntuRDMAConditionFile, internal.UbuntuRDMAServiceName, internal.UbuntuPackageManager) if err != nil { log.Log.Error(err, "EnableRDMAOnUbuntuMachine(): failed to enable RDMA on Ubuntu machine") return false, err @@ -442,9 +382,9 @@ func (k *kernel) EnableRDMAOnUbuntuMachine() (bool, error) { func (k *kernel) IsRHELSystem() (bool, error) { log.Log.Info("IsRHELSystem(): checking for RHEL machine") - path := redhatReleaseFile + path := internal.RedhatReleaseFile if !vars.UsingSystemdMode { - path = filepath.Join(hostPathFromDaemon, path) + path = filepath.Join(internal.HostPathFromDaemon, path) } if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { @@ -461,9 +401,9 @@ func (k *kernel) IsRHELSystem() (bool, error) { func (k *kernel) IsCoreOS() (bool, error) { log.Log.Info("IsCoreOS(): checking for CoreOS machine") - path := redhatReleaseFile + path := internal.RedhatReleaseFile if !vars.UsingSystemdMode { - path = filepath.Join(hostPathFromDaemon, path) + path = filepath.Join(internal.HostPathFromDaemon, path) } data, err := os.ReadFile(path) @@ -481,9 +421,9 @@ func (k *kernel) IsCoreOS() (bool, error) { func (k *kernel) IsUbuntuSystem() (bool, error) { log.Log.Info("IsUbuntuSystem(): checking for Ubuntu machine") - path := genericOSReleaseFile + path := internal.GenericOSReleaseFile if !vars.UsingSystemdMode { - path = filepath.Join(hostPathFromDaemon, path) + path = filepath.Join(internal.HostPathFromDaemon, path) } if _, err := os.Stat(path); err != nil { @@ -530,7 +470,7 @@ func (k *kernel) RdmaIsLoaded() (bool, error) { func (k *kernel) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { path := conditionFilePath if !vars.UsingSystemdMode { - path = filepath.Join(hostPathFromDaemon, path) + path = filepath.Join(internal.HostPathFromDaemon, path) } log.Log.Info("EnableRDMA(): checking for service file", "path", path) @@ -604,9 +544,9 @@ func (k *kernel) ReloadDriver(driverName string) error { } func (k *kernel) GetOSPrettyName() (string, error) { - path := genericOSReleaseFile + path := internal.GenericOSReleaseFile if !vars.UsingSystemdMode { - path = filepath.Join(hostPathFromDaemon, path) + path = filepath.Join(internal.HostPathFromDaemon, path) } log.Log.Info("GetOSPrettyName(): getting os name from os-release file") diff --git a/pkg/host/kernel_test.go b/pkg/host/internal/kernel/kernel_test.go similarity index 98% rename from pkg/host/kernel_test.go rename to pkg/host/internal/kernel/kernel_test.go index 687cda454..de6f22cec 100644 --- a/pkg/host/kernel_test.go +++ b/pkg/host/internal/kernel/kernel_test.go @@ -1,4 +1,4 @@ -package host +package kernel import ( "os" @@ -8,6 +8,7 @@ import ( . "github.com/onsi/gomega" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" ) @@ -21,7 +22,7 @@ func assertFileContentsEquals(path, expectedContent string) { var _ = Describe("Kernel", func() { Context("Drivers", func() { var ( - k KernelInterface + k types.KernelInterface ) configureFS := func(f *fakefilesystem.FS) { var ( @@ -33,7 +34,7 @@ var _ = Describe("Kernel", func() { DeferCleanup(cleanFakeFs) } BeforeEach(func() { - k = newKernelInterface(nil) + k = New(nil) }) Context("Unbind, UnbindDriverByBusAndDevice", func() { It("unknown device", func() { diff --git a/pkg/host/suite_test.go b/pkg/host/internal/kernel/suite_test.go similarity index 79% rename from pkg/host/suite_test.go rename to pkg/host/internal/kernel/suite_test.go index 674437292..b36acb454 100644 --- a/pkg/host/suite_test.go +++ b/pkg/host/internal/kernel/suite_test.go @@ -1,4 +1,4 @@ -package host +package kernel import ( "testing" @@ -11,11 +11,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" ) -func TestHostManager(t *testing.T) { +func TestKernel(t *testing.T) { log.SetLogger(zap.New( zap.WriteTo(GinkgoWriter), zap.Level(zapcore.Level(-2)), zap.UseDevMode(true))) RegisterFailHandler(Fail) - RunSpecs(t, "Package Host Suite") + RunSpecs(t, "Package Kernel Suite") } diff --git a/pkg/host/network.go b/pkg/host/internal/network/network.go similarity index 82% rename from pkg/host/network.go rename to pkg/host/internal/network/network.go index dab12b354..4f97b2634 100644 --- a/pkg/host/network.go +++ b/pkg/host/internal/network/network.go @@ -1,4 +1,4 @@ -package host +package network import ( "fmt" @@ -14,38 +14,16 @@ import ( dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) -type NetworkInterface interface { - // TryToGetVirtualInterfaceName tries to find the virtio interface name base on pci address - // used for virtual environment where we pass SR-IOV virtual function into the system - // supported platform openstack - TryToGetVirtualInterfaceName(string) string - // TryGetInterfaceName tries to find the SR-IOV virtual interface name base on pci address - TryGetInterfaceName(string) string - // GetPhysSwitchID returns the physical switch ID for a specific pci address - GetPhysSwitchID(string) (string, error) - // GetPhysPortName returns the physical port name for a specific pci address - GetPhysPortName(string) (string, error) - // IsSwitchdev returns true of the pci address is on switchdev mode - IsSwitchdev(string) bool - // GetNetdevMTU returns the interface MTU for devices attached to kernel drivers - GetNetdevMTU(string) int - // SetNetdevMTU sets the MTU for a request interface - SetNetdevMTU(string, int) error - // GetNetDevMac returns the network interface mac address - GetNetDevMac(string) string - // GetNetDevLinkSpeed returns the network interface link speed - GetNetDevLinkSpeed(string) string -} - type network struct { utilsHelper utils.CmdInterface } -func newNetworkInterface(utilsHelper utils.CmdInterface) NetworkInterface { +func New(utilsHelper utils.CmdInterface) types.NetworkInterface { return &network{utilsHelper: utilsHelper} } diff --git a/pkg/host/service.go b/pkg/host/internal/service/service.go similarity index 66% rename from pkg/host/service.go rename to pkg/host/internal/service/service.go index 513542e66..4ecec5b5f 100644 --- a/pkg/host/service.go +++ b/pkg/host/internal/service/service.go @@ -1,4 +1,4 @@ -package host +package service import ( "fmt" @@ -13,58 +13,21 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" ) // TODO: handle this to support unit-tests const systemdDir = "/usr/lib/systemd/system/" -var ( - // Remove run condition form the service - ConditionOpt = &unit.UnitOption{ - Section: "Unit", - Name: "ConditionPathExists", - Value: "!/etc/ignition-machine-config-encapsulated.json", - } -) - -type ServiceInterface interface { - // IsServiceExist checks if the requested systemd service exist on the system - IsServiceExist(string) (bool, error) - // IsServiceEnabled checks if the requested systemd service is enabled on the system - IsServiceEnabled(string) (bool, error) - // ReadService reads a systemd servers and return it as a struct - ReadService(string) (*Service, error) - // EnableService enables a systemd server on the host - EnableService(service *Service) error - // ReadServiceManifestFile reads the systemd manifest for a specific service - ReadServiceManifestFile(path string) (*Service, error) - // RemoveFromService removes a systemd service from the host - RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) - // ReadScriptManifestFile reads the script manifest from a systemd service - ReadScriptManifestFile(path string) (*ScriptManifestFile, error) - // ReadServiceInjectionManifestFile reads the injection manifest file for the systemd service - ReadServiceInjectionManifestFile(path string) (*Service, error) - // CompareServices compare two servers and return true if they are equal - CompareServices(serviceA, serviceB *Service) (bool, error) - // UpdateSystemService updates a system service on the host - UpdateSystemService(serviceObj *Service) error -} - type service struct { utilsHelper utils.CmdInterface } -func newServiceInterface(utilsHelper utils.CmdInterface) ServiceInterface { +func New(utilsHelper utils.CmdInterface) types.ServiceInterface { return &service{utilsHelper: utilsHelper} } -type Service struct { - Name string - Path string - Content string -} - // ServiceInjectionManifestFile service injection manifest file structure type ServiceInjectionManifestFile struct { Name string @@ -73,20 +36,6 @@ type ServiceInjectionManifestFile struct { } } -// ServiceManifestFile service manifest file structure -type ServiceManifestFile struct { - Name string - Contents string -} - -// ScriptManifestFile script manifest file structure -type ScriptManifestFile struct { - Path string - Contents struct { - Inline string - } -} - // IsServiceExist check if service unit exist func (s *service) IsServiceExist(servicePath string) (bool, error) { _, err := os.Stat(path.Join(consts.Chroot, servicePath)) @@ -120,13 +69,13 @@ func (s *service) IsServiceEnabled(servicePath string) (bool, error) { } // ReadService read service from given path -func (s *service) ReadService(servicePath string) (*Service, error) { +func (s *service) ReadService(servicePath string) (*types.Service, error) { data, err := os.ReadFile(path.Join(consts.Chroot, servicePath)) if err != nil { return nil, err } - return &Service{ + return &types.Service{ Name: filepath.Base(servicePath), Path: servicePath, Content: string(data), @@ -134,7 +83,7 @@ func (s *service) ReadService(servicePath string) (*Service, error) { } // EnableService creates service file and enables it with systemctl enable -func (s *service) EnableService(service *Service) error { +func (s *service) EnableService(service *types.Service) error { // Write service file err := os.WriteFile(path.Join(consts.Chroot, service.Path), []byte(service.Content), 0644) if err != nil { @@ -154,7 +103,7 @@ func (s *service) EnableService(service *Service) error { } // CompareServices compare 2 service and return true if serviceA has all the fields of serviceB -func (s *service) CompareServices(serviceA, serviceB *Service) (bool, error) { +func (s *service) CompareServices(serviceA, serviceB *types.Service) (bool, error) { optsA, err := unit.Deserialize(strings.NewReader(serviceA.Content)) if err != nil { return false, err @@ -179,7 +128,7 @@ OUTER: } // RemoveFromService removes given fields from service -func (s *service) RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) { +func (s *service) RemoveFromService(service *types.Service, options ...*unit.UnitOption) (*types.Service, error) { opts, err := unit.Deserialize(strings.NewReader(service.Content)) if err != nil { return nil, err @@ -202,7 +151,7 @@ OUTER: return nil, err } - return &Service{ + return &types.Service{ Name: service.Name, Path: service.Path, Content: string(data), @@ -210,7 +159,7 @@ OUTER: } // ReadServiceInjectionManifestFile reads service injection file -func (s *service) ReadServiceInjectionManifestFile(path string) (*Service, error) { +func (s *service) ReadServiceInjectionManifestFile(path string) (*types.Service, error) { data, err := os.ReadFile(path) if err != nil { return nil, err @@ -221,7 +170,7 @@ func (s *service) ReadServiceInjectionManifestFile(path string) (*Service, error return nil, err } - return &Service{ + return &types.Service{ Name: serviceContent.Name, Path: systemdDir + serviceContent.Name, Content: serviceContent.Dropins[0].Contents, @@ -229,18 +178,18 @@ func (s *service) ReadServiceInjectionManifestFile(path string) (*Service, error } // ReadServiceManifestFile reads service file -func (s *service) ReadServiceManifestFile(path string) (*Service, error) { +func (s *service) ReadServiceManifestFile(path string) (*types.Service, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } - var serviceFile *ServiceManifestFile + var serviceFile *types.ServiceManifestFile if err := yaml.Unmarshal(data, &serviceFile); err != nil { return nil, err } - return &Service{ + return &types.Service{ Name: serviceFile.Name, Path: "/etc/systemd/system/" + serviceFile.Name, Content: serviceFile.Contents, @@ -248,13 +197,13 @@ func (s *service) ReadServiceManifestFile(path string) (*Service, error) { } // ReadScriptManifestFile reads script file -func (s *service) ReadScriptManifestFile(path string) (*ScriptManifestFile, error) { +func (s *service) ReadScriptManifestFile(path string) (*types.ScriptManifestFile, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } - var scriptFile *ScriptManifestFile + var scriptFile *types.ScriptManifestFile if err := yaml.Unmarshal(data, &scriptFile); err != nil { return nil, err } @@ -262,7 +211,7 @@ func (s *service) ReadScriptManifestFile(path string) (*ScriptManifestFile, erro return scriptFile, nil } -func (s *service) UpdateSystemService(serviceObj *Service) error { +func (s *service) UpdateSystemService(serviceObj *types.Service) error { systemService, err := s.ReadService(serviceObj.Path) if err != nil { return err @@ -284,7 +233,7 @@ func (s *service) UpdateSystemService(serviceObj *Service) error { } // appendToService appends given fields to service -func appendToService(service *Service, options ...*unit.UnitOption) (*Service, error) { +func appendToService(service *types.Service, options ...*unit.UnitOption) (*types.Service, error) { serviceOptions, err := unit.Deserialize(strings.NewReader(service.Content)) if err != nil { return nil, err @@ -305,7 +254,7 @@ OUTER: return nil, err } - return &Service{ + return &types.Service{ Name: service.Name, Path: service.Path, Content: string(data), diff --git a/pkg/host/sriov.go b/pkg/host/internal/sriov/sriov.go similarity index 88% rename from pkg/host/sriov.go rename to pkg/host/internal/sriov/sriov.go index 8a878854b..3baf6cbec 100644 --- a/pkg/host/sriov.go +++ b/pkg/host/internal/sriov/sriov.go @@ -1,4 +1,4 @@ -package host +package sriov import ( "errors" @@ -19,52 +19,24 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" mlx "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vendors/mellanox" ) -type SriovInterface interface { - // SetSriovNumVfs changes the number of virtual functions allocated for a specific - // physical function base on pci address - SetSriovNumVfs(string, int) error - // GetVfInfo returns the virtual function information is the operator struct from the host information - GetVfInfo(string, []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction - // SetVfGUID sets the GUID for a virtual function - SetVfGUID(string, netlink.Link) error - // VFIsReady returns the interface virtual function if the device is ready - VFIsReady(string) (netlink.Link, error) - // SetVfAdminMac sets the virtual function administrative mac address via the physical function - SetVfAdminMac(string, netlink.Link, netlink.Link) error - // GetNicSriovMode returns the interface mode - // supported modes SR-IOV legacy and switchdev - GetNicSriovMode(string) (string, error) - // GetLinkType return the link type - // supported types are ethernet and infiniband - GetLinkType(sriovnetworkv1.InterfaceExt) string - // ResetSriovDevice resets the number of virtual function for the specific physical function to zero - ResetSriovDevice(sriovnetworkv1.InterfaceExt) error - // DiscoverSriovDevices returns a list of all the available SR-IOV capable network interfaces on the system - DiscoverSriovDevices(StoreManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) - // ConfigSriovDevice configure the request SR-IOV device with the desired configuration - ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error - // ConfigSriovInterfaces configure multiple SR-IOV devices with the desired configuration - ConfigSriovInterfaces(StoreManagerInterface, []sriovnetworkv1.Interface, []sriovnetworkv1.InterfaceExt, map[string]bool) error - // ConfigSriovInterfaces configure virtual functions for virtual environments with the desired configuration - ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error -} - type sriov struct { utilsHelper utils.CmdInterface - kernelHelper KernelInterface - networkHelper NetworkInterface - udevHelper UdevInterface + kernelHelper types.KernelInterface + networkHelper types.NetworkInterface + udevHelper types.UdevInterface } -func newSriovInterface(utilsHelper utils.CmdInterface, - kernelHelper KernelInterface, - networkHelper NetworkInterface, - udevHelper UdevInterface) SriovInterface { +func New(utilsHelper utils.CmdInterface, + kernelHelper types.KernelInterface, + networkHelper types.NetworkInterface, + udevHelper types.UdevInterface) types.SriovInterface { return &sriov{utilsHelper: utilsHelper, kernelHelper: kernelHelper, networkHelper: networkHelper, udevHelper: udevHelper} } @@ -199,7 +171,7 @@ func (s *sriov) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error return nil } -func (s *sriov) DiscoverSriovDevices(storeManager StoreManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) { +func (s *sriov) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) { log.Log.V(2).Info("DiscoverSriovDevices") pfList := []sriovnetworkv1.InterfaceExt{} @@ -465,7 +437,8 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * return nil } -func (s *sriov) ConfigSriovInterfaces(storeManager StoreManagerInterface, interfaces []sriovnetworkv1.Interface, ifaceStatuses []sriovnetworkv1.InterfaceExt, pfsToConfig map[string]bool) error { +func (s *sriov) ConfigSriovInterfaces(storeManager store.ManagerInterface, + interfaces []sriovnetworkv1.Interface, ifaceStatuses []sriovnetworkv1.InterfaceExt, pfsToConfig map[string]bool) error { if s.kernelHelper.IsKernelLockdownMode() && mlx.HasMellanoxInterfacesInSpec(ifaceStatuses, interfaces) { log.Log.Error(nil, "cannot use mellanox devices when in kernel lockdown mode") return fmt.Errorf("cannot use mellanox devices when in kernel lockdown mode") diff --git a/pkg/host/udev.go b/pkg/host/internal/udev/udev.go similarity index 89% rename from pkg/host/udev.go rename to pkg/host/internal/udev/udev.go index 5f4daee58..dad88913e 100644 --- a/pkg/host/udev.go +++ b/pkg/host/internal/udev/udev.go @@ -1,4 +1,4 @@ -package host +package udev import ( "bytes" @@ -13,27 +13,16 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) -type UdevInterface interface { - // WriteSwitchdevConfFile writes the needed switchdev configuration files for HW offload support - WriteSwitchdevConfFile(*sriovnetworkv1.SriovNetworkNodeState, map[string]bool) (bool, error) - // PrepareNMUdevRule creates the needed udev rules to disable NetworkManager from - // our managed SR-IOV virtual functions - PrepareNMUdevRule([]string) error - // AddUdevRule adds a specific udev rule to the system - AddUdevRule(string) error - // RemoveUdevRule removes a udev rule from the system - RemoveUdevRule(string) error -} - type udev struct { utilsHelper utils.CmdInterface } -func newUdevInterface(utilsHelper utils.CmdInterface) UdevInterface { +func New(utilsHelper utils.CmdInterface) types.UdevInterface { return &udev{utilsHelper: utilsHelper} } diff --git a/pkg/host/manager.go b/pkg/host/manager.go new file mode 100644 index 000000000..3b0f790e9 --- /dev/null +++ b/pkg/host/manager.go @@ -0,0 +1,46 @@ +package host + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/kernel" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/network" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/service" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/sriov" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/udev" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" +) + +// Contains all the host manipulation functions +type HostManagerInterface interface { + types.KernelInterface + types.NetworkInterface + types.ServiceInterface + types.UdevInterface + types.SriovInterface +} + +type hostManager struct { + utils.CmdInterface + types.KernelInterface + types.NetworkInterface + types.ServiceInterface + types.UdevInterface + types.SriovInterface +} + +func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { + k := kernel.New(utilsInterface) + n := network.New(utilsInterface) + sv := service.New(utilsInterface) + u := udev.New(utilsInterface) + sr := sriov.New(utilsInterface, k, n, u) + + return &hostManager{ + utilsInterface, + k, + n, + sv, + u, + sr, + } +} diff --git a/pkg/host/mock/mock_store.go b/pkg/host/mock/mock_store.go deleted file mode 100644 index 54eae5850..000000000 --- a/pkg/host/mock/mock_store.go +++ /dev/null @@ -1,108 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: store.go - -// Package mock_host is a generated GoMock package. -package mock_host - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" -) - -// MockStoreManagerInterface is a mock of StoreManagerInterface interface. -type MockStoreManagerInterface struct { - ctrl *gomock.Controller - recorder *MockStoreManagerInterfaceMockRecorder -} - -// MockStoreManagerInterfaceMockRecorder is the mock recorder for MockStoreManagerInterface. -type MockStoreManagerInterfaceMockRecorder struct { - mock *MockStoreManagerInterface -} - -// NewMockStoreManagerInterface creates a new mock instance. -func NewMockStoreManagerInterface(ctrl *gomock.Controller) *MockStoreManagerInterface { - mock := &MockStoreManagerInterface{ctrl: ctrl} - mock.recorder = &MockStoreManagerInterfaceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockStoreManagerInterface) EXPECT() *MockStoreManagerInterfaceMockRecorder { - return m.recorder -} - -// ClearPCIAddressFolder mocks base method. -func (m *MockStoreManagerInterface) ClearPCIAddressFolder() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ClearPCIAddressFolder") - ret0, _ := ret[0].(error) - return ret0 -} - -// ClearPCIAddressFolder indicates an expected call of ClearPCIAddressFolder. -func (mr *MockStoreManagerInterfaceMockRecorder) ClearPCIAddressFolder() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearPCIAddressFolder", reflect.TypeOf((*MockStoreManagerInterface)(nil).ClearPCIAddressFolder)) -} - -// GetCheckPointNodeState mocks base method. -func (m *MockStoreManagerInterface) GetCheckPointNodeState() (*v1.SriovNetworkNodeState, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCheckPointNodeState") - ret0, _ := ret[0].(*v1.SriovNetworkNodeState) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCheckPointNodeState indicates an expected call of GetCheckPointNodeState. -func (mr *MockStoreManagerInterfaceMockRecorder) GetCheckPointNodeState() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCheckPointNodeState", reflect.TypeOf((*MockStoreManagerInterface)(nil).GetCheckPointNodeState)) -} - -// LoadPfsStatus mocks base method. -func (m *MockStoreManagerInterface) LoadPfsStatus(pciAddress string) (*v1.Interface, bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadPfsStatus", pciAddress) - ret0, _ := ret[0].(*v1.Interface) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// LoadPfsStatus indicates an expected call of LoadPfsStatus. -func (mr *MockStoreManagerInterfaceMockRecorder) LoadPfsStatus(pciAddress interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPfsStatus", reflect.TypeOf((*MockStoreManagerInterface)(nil).LoadPfsStatus), pciAddress) -} - -// SaveLastPfAppliedStatus mocks base method. -func (m *MockStoreManagerInterface) SaveLastPfAppliedStatus(PfInfo *v1.Interface) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SaveLastPfAppliedStatus", PfInfo) - ret0, _ := ret[0].(error) - return ret0 -} - -// SaveLastPfAppliedStatus indicates an expected call of SaveLastPfAppliedStatus. -func (mr *MockStoreManagerInterfaceMockRecorder) SaveLastPfAppliedStatus(PfInfo interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveLastPfAppliedStatus", reflect.TypeOf((*MockStoreManagerInterface)(nil).SaveLastPfAppliedStatus), PfInfo) -} - -// WriteCheckpointFile mocks base method. -func (m *MockStoreManagerInterface) WriteCheckpointFile(arg0 *v1.SriovNetworkNodeState) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WriteCheckpointFile", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// WriteCheckpointFile indicates an expected call of WriteCheckpointFile. -func (mr *MockStoreManagerInterfaceMockRecorder) WriteCheckpointFile(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCheckpointFile", reflect.TypeOf((*MockStoreManagerInterface)(nil).WriteCheckpointFile), arg0) -} diff --git a/pkg/host/store/mock/mock_store.go b/pkg/host/store/mock/mock_store.go new file mode 100644 index 000000000..2e0071dfd --- /dev/null +++ b/pkg/host/store/mock/mock_store.go @@ -0,0 +1,108 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: store.go + +// Package mock_store is a generated GoMock package. +package mock_store + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" +) + +// MockManagerInterface is a mock of ManagerInterface interface. +type MockManagerInterface struct { + ctrl *gomock.Controller + recorder *MockManagerInterfaceMockRecorder +} + +// MockManagerInterfaceMockRecorder is the mock recorder for MockManagerInterface. +type MockManagerInterfaceMockRecorder struct { + mock *MockManagerInterface +} + +// NewMockManagerInterface creates a new mock instance. +func NewMockManagerInterface(ctrl *gomock.Controller) *MockManagerInterface { + mock := &MockManagerInterface{ctrl: ctrl} + mock.recorder = &MockManagerInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockManagerInterface) EXPECT() *MockManagerInterfaceMockRecorder { + return m.recorder +} + +// ClearPCIAddressFolder mocks base method. +func (m *MockManagerInterface) ClearPCIAddressFolder() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClearPCIAddressFolder") + ret0, _ := ret[0].(error) + return ret0 +} + +// ClearPCIAddressFolder indicates an expected call of ClearPCIAddressFolder. +func (mr *MockManagerInterfaceMockRecorder) ClearPCIAddressFolder() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearPCIAddressFolder", reflect.TypeOf((*MockManagerInterface)(nil).ClearPCIAddressFolder)) +} + +// GetCheckPointNodeState mocks base method. +func (m *MockManagerInterface) GetCheckPointNodeState() (*v1.SriovNetworkNodeState, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCheckPointNodeState") + ret0, _ := ret[0].(*v1.SriovNetworkNodeState) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCheckPointNodeState indicates an expected call of GetCheckPointNodeState. +func (mr *MockManagerInterfaceMockRecorder) GetCheckPointNodeState() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCheckPointNodeState", reflect.TypeOf((*MockManagerInterface)(nil).GetCheckPointNodeState)) +} + +// LoadPfsStatus mocks base method. +func (m *MockManagerInterface) LoadPfsStatus(pciAddress string) (*v1.Interface, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadPfsStatus", pciAddress) + ret0, _ := ret[0].(*v1.Interface) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// LoadPfsStatus indicates an expected call of LoadPfsStatus. +func (mr *MockManagerInterfaceMockRecorder) LoadPfsStatus(pciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadPfsStatus", reflect.TypeOf((*MockManagerInterface)(nil).LoadPfsStatus), pciAddress) +} + +// SaveLastPfAppliedStatus mocks base method. +func (m *MockManagerInterface) SaveLastPfAppliedStatus(PfInfo *v1.Interface) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SaveLastPfAppliedStatus", PfInfo) + ret0, _ := ret[0].(error) + return ret0 +} + +// SaveLastPfAppliedStatus indicates an expected call of SaveLastPfAppliedStatus. +func (mr *MockManagerInterfaceMockRecorder) SaveLastPfAppliedStatus(PfInfo interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveLastPfAppliedStatus", reflect.TypeOf((*MockManagerInterface)(nil).SaveLastPfAppliedStatus), PfInfo) +} + +// WriteCheckpointFile mocks base method. +func (m *MockManagerInterface) WriteCheckpointFile(arg0 *v1.SriovNetworkNodeState) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteCheckpointFile", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteCheckpointFile indicates an expected call of WriteCheckpointFile. +func (mr *MockManagerInterfaceMockRecorder) WriteCheckpointFile(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteCheckpointFile", reflect.TypeOf((*MockManagerInterface)(nil).WriteCheckpointFile), arg0) +} diff --git a/pkg/host/store.go b/pkg/host/store/store.go similarity index 85% rename from pkg/host/store.go rename to pkg/host/store/store.go index 1bced8c9d..77e4bbd32 100644 --- a/pkg/host/store.go +++ b/pkg/host/store/store.go @@ -1,4 +1,4 @@ -package host +package store import ( "encoding/json" @@ -16,8 +16,8 @@ import ( // Contains all the file storing on the host // -//go:generate ../../bin/mockgen -destination mock/mock_store.go -source store.go -type StoreManagerInterface interface { +//go:generate ../../../bin/mockgen -destination mock/mock_store.go -source store.go +type ManagerInterface interface { ClearPCIAddressFolder() error SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) @@ -26,17 +26,16 @@ type StoreManagerInterface interface { WriteCheckpointFile(*sriovnetworkv1.SriovNetworkNodeState) error } -type storeManager struct { -} +type manager struct{} -// NewStoreManager: create the initial folders needed to store the info about the PF -// and return a storeManager struct that implements the StoreManagerInterface interface -func NewStoreManager() (StoreManagerInterface, error) { +// NewManager: create the initial folders needed to store the info about the PF +// and return a manager struct that implements the ManagerInterface interface +func NewManager() (ManagerInterface, error) { if err := createOperatorConfigFolderIfNeeded(); err != nil { return nil, err } - return &storeManager{}, nil + return &manager{}, nil } // createOperatorConfigFolderIfNeeded: create the operator base folder on the host @@ -73,7 +72,7 @@ func createOperatorConfigFolderIfNeeded() error { } // ClearPCIAddressFolder: removes all the PFs storage information -func (s *storeManager) ClearPCIAddressFolder() error { +func (s *manager) ClearPCIAddressFolder() error { hostExtension := utils.GetHostExtension() PfAppliedConfigUse := filepath.Join(hostExtension, consts.PfAppliedConfig) _, err := os.Stat(PfAppliedConfigUse) @@ -99,7 +98,7 @@ func (s *storeManager) ClearPCIAddressFolder() error { // SaveLastPfAppliedStatus will save the PF object as a json into the /etc/sriov-operator/pci/ // this function must be called after running the chroot function -func (s *storeManager) SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error { +func (s *manager) SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) error { data, err := json.Marshal(PfInfo) if err != nil { log.Log.Error(err, "failed to marshal PF status", "status", *PfInfo) @@ -114,7 +113,7 @@ func (s *storeManager) SaveLastPfAppliedStatus(PfInfo *sriovnetworkv1.Interface) // LoadPfsStatus convert the /etc/sriov-operator/pci/ json to pfstatus // returns false if the file doesn't exist. -func (s *storeManager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) { +func (s *manager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interface, bool, error) { hostExtension := utils.GetHostExtension() pathFile := filepath.Join(hostExtension, consts.PfAppliedConfig, pciAddress) pfStatus := &sriovnetworkv1.Interface{} @@ -136,7 +135,7 @@ func (s *storeManager) LoadPfsStatus(pciAddress string) (*sriovnetworkv1.Interfa return pfStatus, true, nil } -func (s *storeManager) GetCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNodeState, error) { +func (s *manager) GetCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNodeState, error) { log.Log.Info("getCheckPointNodeState()") configdir := filepath.Join(vars.Destdir, consts.CheckpointFileName) file, err := os.OpenFile(configdir, os.O_RDONLY, 0644) @@ -154,7 +153,7 @@ func (s *storeManager) GetCheckPointNodeState() (*sriovnetworkv1.SriovNetworkNod return &sriovnetworkv1.InitialState, nil } -func (s *storeManager) WriteCheckpointFile(ns *sriovnetworkv1.SriovNetworkNodeState) error { +func (s *manager) WriteCheckpointFile(ns *sriovnetworkv1.SriovNetworkNodeState) error { configdir := filepath.Join(vars.Destdir, consts.CheckpointFileName) file, err := os.OpenFile(configdir, os.O_RDWR|os.O_CREATE, 0644) if err != nil { diff --git a/pkg/host/types/interfaces.go b/pkg/host/types/interfaces.go new file mode 100644 index 000000000..5a4b66ea8 --- /dev/null +++ b/pkg/host/types/interfaces.go @@ -0,0 +1,160 @@ +package types + +import ( + "github.com/coreos/go-systemd/v22/unit" + "github.com/jaypipes/ghw" + "github.com/vishvananda/netlink" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" +) + +type KernelInterface interface { + // TryEnableTun load the tun kernel module + TryEnableTun() + // TryEnableVhostNet load the vhost-net kernel module + TryEnableVhostNet() + // TryEnableRdma tries to enable RDMA on the machine base on the operating system + // if the package doesn't exist it will also will try to install it + // supported operating systems are RHEL RHCOS and ubuntu + TryEnableRdma() (bool, error) + // TriggerUdevEvent triggers a udev event + TriggerUdevEvent() error + // GetCurrentKernelArgs reads the /proc/cmdline to check the current kernel arguments + GetCurrentKernelArgs() (string, error) + // IsKernelArgsSet check is the requested kernel arguments are set + IsKernelArgsSet(string, string) bool + // Unbind unbinds a virtual function from is current driver + Unbind(string) error + // BindDpdkDriver binds the virtual function to a DPDK driver + BindDpdkDriver(string, string) error + // BindDefaultDriver binds the virtual function to is default driver + BindDefaultDriver(string) error + // BindDriverByBusAndDevice binds device to the provided driver + // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" + // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA + // driver - the name of the driver, e.g. vfio-pci or vhost_vdpa. + BindDriverByBusAndDevice(bus, device, driver string) error + // HasDriver returns try if the virtual function is bind to a driver + HasDriver(string) (bool, string) + // RebindVfToDefaultDriver rebinds the virtual function to is default driver + RebindVfToDefaultDriver(string) error + // UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver + // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" + // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA + UnbindDriverByBusAndDevice(bus, device string) error + // UnbindDriverIfNeeded unbinds the virtual function from a driver if needed + UnbindDriverIfNeeded(string, bool) error + // LoadKernelModule loads a kernel module to the host + LoadKernelModule(name string, args ...string) error + // IsKernelModuleLoaded returns try if the requested kernel module is loaded + IsKernelModuleLoaded(string) (bool, error) + // ReloadDriver reloads a requested driver + ReloadDriver(string) error + // IsKernelLockdownMode returns true if the kernel is in lockdown mode + IsKernelLockdownMode() bool + // IsRHELSystem returns try if the system is a RHEL base + IsRHELSystem() (bool, error) + // IsUbuntuSystem returns try if the system is an ubuntu base + IsUbuntuSystem() (bool, error) + // IsCoreOS returns true if the system is a CoreOS or RHCOS base + IsCoreOS() (bool, error) + // RdmaIsLoaded returns try if RDMA kernel modules are loaded + RdmaIsLoaded() (bool, error) + // EnableRDMA enable RDMA on the system + EnableRDMA(string, string, string) (bool, error) + // InstallRDMA install RDMA packages on the system + InstallRDMA(string) error + // EnableRDMAOnRHELMachine enable RDMA on a RHEL base system + EnableRDMAOnRHELMachine() (bool, error) + // GetOSPrettyName returns OS name + GetOSPrettyName() (string, error) +} + +type NetworkInterface interface { + // TryToGetVirtualInterfaceName tries to find the virtio interface name base on pci address + // used for virtual environment where we pass SR-IOV virtual function into the system + // supported platform openstack + TryToGetVirtualInterfaceName(string) string + // TryGetInterfaceName tries to find the SR-IOV virtual interface name base on pci address + TryGetInterfaceName(string) string + // GetPhysSwitchID returns the physical switch ID for a specific pci address + GetPhysSwitchID(string) (string, error) + // GetPhysPortName returns the physical port name for a specific pci address + GetPhysPortName(string) (string, error) + // IsSwitchdev returns true of the pci address is on switchdev mode + IsSwitchdev(string) bool + // GetNetdevMTU returns the interface MTU for devices attached to kernel drivers + GetNetdevMTU(string) int + // SetNetdevMTU sets the MTU for a request interface + SetNetdevMTU(string, int) error + // GetNetDevMac returns the network interface mac address + GetNetDevMac(string) string + // GetNetDevLinkSpeed returns the network interface link speed + GetNetDevLinkSpeed(string) string +} + +type ServiceInterface interface { + // IsServiceExist checks if the requested systemd service exist on the system + IsServiceExist(string) (bool, error) + // IsServiceEnabled checks if the requested systemd service is enabled on the system + IsServiceEnabled(string) (bool, error) + // ReadService reads a systemd servers and return it as a struct + ReadService(string) (*Service, error) + // EnableService enables a systemd server on the host + EnableService(service *Service) error + // ReadServiceManifestFile reads the systemd manifest for a specific service + ReadServiceManifestFile(path string) (*Service, error) + // RemoveFromService removes a systemd service from the host + RemoveFromService(service *Service, options ...*unit.UnitOption) (*Service, error) + // ReadScriptManifestFile reads the script manifest from a systemd service + ReadScriptManifestFile(path string) (*ScriptManifestFile, error) + // ReadServiceInjectionManifestFile reads the injection manifest file for the systemd service + ReadServiceInjectionManifestFile(path string) (*Service, error) + // CompareServices compare two servers and return true if they are equal + CompareServices(serviceA, serviceB *Service) (bool, error) + // UpdateSystemService updates a system service on the host + UpdateSystemService(serviceObj *Service) error +} + +type SriovInterface interface { + // SetSriovNumVfs changes the number of virtual functions allocated for a specific + // physical function base on pci address + SetSriovNumVfs(string, int) error + // GetVfInfo returns the virtual function information is the operator struct from the host information + GetVfInfo(string, []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction + // SetVfGUID sets the GUID for a virtual function + SetVfGUID(string, netlink.Link) error + // VFIsReady returns the interface virtual function if the device is ready + VFIsReady(string) (netlink.Link, error) + // SetVfAdminMac sets the virtual function administrative mac address via the physical function + SetVfAdminMac(string, netlink.Link, netlink.Link) error + // GetNicSriovMode returns the interface mode + // supported modes SR-IOV legacy and switchdev + GetNicSriovMode(string) (string, error) + // GetLinkType return the link type + // supported types are ethernet and infiniband + GetLinkType(sriovnetworkv1.InterfaceExt) string + // ResetSriovDevice resets the number of virtual function for the specific physical function to zero + ResetSriovDevice(sriovnetworkv1.InterfaceExt) error + // DiscoverSriovDevices returns a list of all the available SR-IOV capable network interfaces on the system + DiscoverSriovDevices(store.ManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) + // ConfigSriovDevice configure the request SR-IOV device with the desired configuration + ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error + // ConfigSriovInterfaces configure multiple SR-IOV devices with the desired configuration + ConfigSriovInterfaces(store.ManagerInterface, []sriovnetworkv1.Interface, []sriovnetworkv1.InterfaceExt, map[string]bool) error + // ConfigSriovInterfaces configure virtual functions for virtual environments with the desired configuration + ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error +} + +type UdevInterface interface { + // WriteSwitchdevConfFile writes the needed switchdev configuration files for HW offload support + WriteSwitchdevConfFile(*sriovnetworkv1.SriovNetworkNodeState, map[string]bool) (bool, error) + // PrepareNMUdevRule creates the needed udev rules to disable NetworkManager from + // our managed SR-IOV virtual functions + PrepareNMUdevRule([]string) error + // AddUdevRule adds a specific udev rule to the system + AddUdevRule(string) error + // RemoveUdevRule removes a udev rule from the system + RemoveUdevRule(string) error +} diff --git a/pkg/host/types/types.go b/pkg/host/types/types.go new file mode 100644 index 000000000..935a34bfd --- /dev/null +++ b/pkg/host/types/types.go @@ -0,0 +1,43 @@ +package types + +import ( + "github.com/coreos/go-systemd/v22/unit" +) + +// Service contains info about systemd service +type Service struct { + Name string + Path string + Content string +} + +// ServiceInjectionManifestFile service injection manifest file structure +type ServiceInjectionManifestFile struct { + Name string + Dropins []struct { + Contents string + } +} + +// ServiceManifestFile service manifest file structure +type ServiceManifestFile struct { + Name string + Contents string +} + +// ScriptManifestFile script manifest file structure +type ScriptManifestFile struct { + Path string + Contents struct { + Inline string + } +} + +var ( + // Remove run condition form the service + ConditionOpt = &unit.UnitOption{ + Section: "Unit", + Name: "ConditionPathExists", + Value: "!/etc/ignition-machine-config-encapsulated.json", + } +) diff --git a/pkg/plugins/k8s/k8s_plugin.go b/pkg/plugins/k8s/k8s_plugin.go index 1bf70eab1..02b4e6336 100644 --- a/pkg/plugins/k8s/k8s_plugin.go +++ b/pkg/plugins/k8s/k8s_plugin.go @@ -11,7 +11,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host" + hostTypes "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" plugins "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) @@ -21,14 +21,14 @@ var PluginName = "k8s_plugin" type K8sPlugin struct { PluginName string SpecVersion string - switchdevBeforeNMRunScript *host.ScriptManifestFile - switchdevAfterNMRunScript *host.ScriptManifestFile - switchdevUdevScript *host.ScriptManifestFile - switchdevBeforeNMService *host.Service - switchdevAfterNMService *host.Service - openVSwitchService *host.Service - networkManagerService *host.Service - sriovService *host.Service + switchdevBeforeNMRunScript *hostTypes.ScriptManifestFile + switchdevAfterNMRunScript *hostTypes.ScriptManifestFile + switchdevUdevScript *hostTypes.ScriptManifestFile + switchdevBeforeNMService *hostTypes.Service + switchdevAfterNMService *hostTypes.Service + openVSwitchService *hostTypes.Service + networkManagerService *hostTypes.Service + sriovService *hostTypes.Service updateTarget *k8sUpdateTarget hostHelper helper.HostHelpersInterface } @@ -40,7 +40,7 @@ type k8sUpdateTarget struct { switchdevAfterNMRunScript bool switchdevUdevScript bool sriovScript bool - systemServices []*host.Service + systemServices []*hostTypes.Service } func (u *k8sUpdateTarget) needUpdate() bool { @@ -58,7 +58,7 @@ func (u *k8sUpdateTarget) reset() { u.switchdevAfterNMRunScript = false u.switchdevUdevScript = false u.sriovScript = false - u.systemServices = []*host.Service{} + u.systemServices = []*hostTypes.Service{} } func (u *k8sUpdateTarget) String() string { @@ -193,11 +193,11 @@ func (p *K8sPlugin) readSwitchdevManifest() error { return err } - switchdevBeforeNMService, err = p.hostHelper.RemoveFromService(switchdevBeforeNMService, host.ConditionOpt) + switchdevBeforeNMService, err = p.hostHelper.RemoveFromService(switchdevBeforeNMService, hostTypes.ConditionOpt) if err != nil { return err } - switchdevAfterNMService, err = p.hostHelper.RemoveFromService(switchdevAfterNMService, host.ConditionOpt) + switchdevAfterNMService, err = p.hostHelper.RemoveFromService(switchdevAfterNMService, hostTypes.ConditionOpt) if err != nil { return err } @@ -331,11 +331,11 @@ func (p *K8sPlugin) sriovServiceStateUpdate() error { return nil } -func (p *K8sPlugin) getSwitchDevSystemServices() []*host.Service { - return []*host.Service{p.networkManagerService, p.openVSwitchService} +func (p *K8sPlugin) getSwitchDevSystemServices() []*hostTypes.Service { + return []*hostTypes.Service{p.networkManagerService, p.openVSwitchService} } -func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *host.ScriptManifestFile) (needUpdate bool, err error) { +func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *hostTypes.ScriptManifestFile) (needUpdate bool, err error) { data, err := os.ReadFile(path.Join(consts.Host, scriptObj.Path)) if err != nil { if !os.IsNotExist(err) { @@ -348,7 +348,7 @@ func (p *K8sPlugin) isSwitchdevScriptNeedUpdate(scriptObj *host.ScriptManifestFi return false, nil } -func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *host.Service) (needUpdate bool, err error) { +func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *hostTypes.Service) (needUpdate bool, err error) { swdService, err := p.hostHelper.ReadService(serviceObj.Path) if err != nil { if !os.IsNotExist(err) { @@ -365,7 +365,7 @@ func (p *K8sPlugin) isSwitchdevServiceNeedUpdate(serviceObj *host.Service) (need } } -func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *host.Service) bool { +func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *hostTypes.Service) bool { log.Log.Info("isSystemServiceNeedUpdate()") systemService, err := p.hostHelper.ReadService(serviceObj.Path) if err != nil { @@ -386,7 +386,7 @@ func (p *K8sPlugin) isSystemServiceNeedUpdate(serviceObj *host.Service) bool { } func (p *K8sPlugin) systemServicesStateUpdate() error { - var services []*host.Service + var services []*hostTypes.Service for _, systemService := range p.getSwitchDevSystemServices() { exist, err := p.hostHelper.IsServiceExist(systemService.Path) if err != nil { From 51c2e695361036be3eb79e324ff08ee7bd8fdb23 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Wed, 17 Jan 2024 11:53:30 +0200 Subject: [PATCH 27/61] Use named args in interface definitions in host pkg Signed-off-by: Yury Kulazhenkov --- pkg/host/types/interfaces.go | 75 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/pkg/host/types/interfaces.go b/pkg/host/types/interfaces.go index 5a4b66ea8..d1613cd44 100644 --- a/pkg/host/types/interfaces.go +++ b/pkg/host/types/interfaces.go @@ -23,34 +23,34 @@ type KernelInterface interface { // GetCurrentKernelArgs reads the /proc/cmdline to check the current kernel arguments GetCurrentKernelArgs() (string, error) // IsKernelArgsSet check is the requested kernel arguments are set - IsKernelArgsSet(string, string) bool + IsKernelArgsSet(cmdLine, karg string) bool // Unbind unbinds a virtual function from is current driver - Unbind(string) error + Unbind(pciAddr string) error // BindDpdkDriver binds the virtual function to a DPDK driver - BindDpdkDriver(string, string) error + BindDpdkDriver(pciAddr, driver string) error // BindDefaultDriver binds the virtual function to is default driver - BindDefaultDriver(string) error + BindDefaultDriver(pciAddr string) error // BindDriverByBusAndDevice binds device to the provided driver // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA // driver - the name of the driver, e.g. vfio-pci or vhost_vdpa. BindDriverByBusAndDevice(bus, device, driver string) error // HasDriver returns try if the virtual function is bind to a driver - HasDriver(string) (bool, string) + HasDriver(pciAddr string) (bool, string) // RebindVfToDefaultDriver rebinds the virtual function to is default driver - RebindVfToDefaultDriver(string) error + RebindVfToDefaultDriver(pciAddr string) error // UnbindDriverByBusAndDevice unbind device identified by bus and device ID from the driver // bus - the bus path in the sysfs, e.g. "pci" or "vdpa" // device - the name of the device on the bus, e.g. 0000:85:1e.5 for PCI or vpda1 for VDPA UnbindDriverByBusAndDevice(bus, device string) error // UnbindDriverIfNeeded unbinds the virtual function from a driver if needed - UnbindDriverIfNeeded(string, bool) error + UnbindDriverIfNeeded(pciAddr string, isRdma bool) error // LoadKernelModule loads a kernel module to the host LoadKernelModule(name string, args ...string) error // IsKernelModuleLoaded returns try if the requested kernel module is loaded - IsKernelModuleLoaded(string) (bool, error) + IsKernelModuleLoaded(name string) (bool, error) // ReloadDriver reloads a requested driver - ReloadDriver(string) error + ReloadDriver(driver string) error // IsKernelLockdownMode returns true if the kernel is in lockdown mode IsKernelLockdownMode() bool // IsRHELSystem returns try if the system is a RHEL base @@ -62,9 +62,9 @@ type KernelInterface interface { // RdmaIsLoaded returns try if RDMA kernel modules are loaded RdmaIsLoaded() (bool, error) // EnableRDMA enable RDMA on the system - EnableRDMA(string, string, string) (bool, error) + EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) // InstallRDMA install RDMA packages on the system - InstallRDMA(string) error + InstallRDMA(packageManager string) error // EnableRDMAOnRHELMachine enable RDMA on a RHEL base system EnableRDMAOnRHELMachine() (bool, error) // GetOSPrettyName returns OS name @@ -75,32 +75,32 @@ type NetworkInterface interface { // TryToGetVirtualInterfaceName tries to find the virtio interface name base on pci address // used for virtual environment where we pass SR-IOV virtual function into the system // supported platform openstack - TryToGetVirtualInterfaceName(string) string + TryToGetVirtualInterfaceName(pciAddr string) string // TryGetInterfaceName tries to find the SR-IOV virtual interface name base on pci address - TryGetInterfaceName(string) string + TryGetInterfaceName(pciAddr string) string // GetPhysSwitchID returns the physical switch ID for a specific pci address - GetPhysSwitchID(string) (string, error) + GetPhysSwitchID(name string) (string, error) // GetPhysPortName returns the physical port name for a specific pci address - GetPhysPortName(string) (string, error) + GetPhysPortName(name string) (string, error) // IsSwitchdev returns true of the pci address is on switchdev mode - IsSwitchdev(string) bool + IsSwitchdev(name string) bool // GetNetdevMTU returns the interface MTU for devices attached to kernel drivers - GetNetdevMTU(string) int + GetNetdevMTU(pciAddr string) int // SetNetdevMTU sets the MTU for a request interface - SetNetdevMTU(string, int) error + SetNetdevMTU(pciAddr string, mtu int) error // GetNetDevMac returns the network interface mac address - GetNetDevMac(string) string + GetNetDevMac(name string) string // GetNetDevLinkSpeed returns the network interface link speed - GetNetDevLinkSpeed(string) string + GetNetDevLinkSpeed(name string) string } type ServiceInterface interface { // IsServiceExist checks if the requested systemd service exist on the system - IsServiceExist(string) (bool, error) + IsServiceExist(servicePath string) (bool, error) // IsServiceEnabled checks if the requested systemd service is enabled on the system - IsServiceEnabled(string) (bool, error) + IsServiceEnabled(servicePath string) (bool, error) // ReadService reads a systemd servers and return it as a struct - ReadService(string) (*Service, error) + ReadService(servicePath string) (*Service, error) // EnableService enables a systemd server on the host EnableService(service *Service) error // ReadServiceManifestFile reads the systemd manifest for a specific service @@ -120,41 +120,42 @@ type ServiceInterface interface { type SriovInterface interface { // SetSriovNumVfs changes the number of virtual functions allocated for a specific // physical function base on pci address - SetSriovNumVfs(string, int) error + SetSriovNumVfs(pciAddr string, numVfs int) error // GetVfInfo returns the virtual function information is the operator struct from the host information - GetVfInfo(string, []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction + GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction // SetVfGUID sets the GUID for a virtual function - SetVfGUID(string, netlink.Link) error + SetVfGUID(vfAddr string, pfLink netlink.Link) error // VFIsReady returns the interface virtual function if the device is ready - VFIsReady(string) (netlink.Link, error) + VFIsReady(pciAddr string) (netlink.Link, error) // SetVfAdminMac sets the virtual function administrative mac address via the physical function - SetVfAdminMac(string, netlink.Link, netlink.Link) error + SetVfAdminMac(vfAddr string, pfLink netlink.Link, vfLink netlink.Link) error // GetNicSriovMode returns the interface mode // supported modes SR-IOV legacy and switchdev - GetNicSriovMode(string) (string, error) + GetNicSriovMode(pciAddr string) (string, error) // GetLinkType return the link type // supported types are ethernet and infiniband - GetLinkType(sriovnetworkv1.InterfaceExt) string + GetLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string // ResetSriovDevice resets the number of virtual function for the specific physical function to zero - ResetSriovDevice(sriovnetworkv1.InterfaceExt) error + ResetSriovDevice(ifaceStatus sriovnetworkv1.InterfaceExt) error // DiscoverSriovDevices returns a list of all the available SR-IOV capable network interfaces on the system - DiscoverSriovDevices(store.ManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) + DiscoverSriovDevices(storeManager store.ManagerInterface) ([]sriovnetworkv1.InterfaceExt, error) // ConfigSriovDevice configure the request SR-IOV device with the desired configuration ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus *sriovnetworkv1.InterfaceExt) error // ConfigSriovInterfaces configure multiple SR-IOV devices with the desired configuration - ConfigSriovInterfaces(store.ManagerInterface, []sriovnetworkv1.Interface, []sriovnetworkv1.InterfaceExt, map[string]bool) error + ConfigSriovInterfaces(storeManager store.ManagerInterface, interfaces []sriovnetworkv1.Interface, + ifaceStatuses []sriovnetworkv1.InterfaceExt, pfsToConfig map[string]bool) error // ConfigSriovInterfaces configure virtual functions for virtual environments with the desired configuration ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error } type UdevInterface interface { // WriteSwitchdevConfFile writes the needed switchdev configuration files for HW offload support - WriteSwitchdevConfFile(*sriovnetworkv1.SriovNetworkNodeState, map[string]bool) (bool, error) + WriteSwitchdevConfFile(newState *sriovnetworkv1.SriovNetworkNodeState, pfsToSkip map[string]bool) (bool, error) // PrepareNMUdevRule creates the needed udev rules to disable NetworkManager from // our managed SR-IOV virtual functions - PrepareNMUdevRule([]string) error + PrepareNMUdevRule(supportedVfIds []string) error // AddUdevRule adds a specific udev rule to the system - AddUdevRule(string) error + AddUdevRule(pfPciAddress string) error // RemoveUdevRule removes a udev rule from the system - RemoveUdevRule(string) error + RemoveUdevRule(pfPciAddress string) error } From bdb6d90fa3f6182deee201234584d2e7b82885cb Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 09:59:41 +0200 Subject: [PATCH 28/61] Generate mock for host.HostManagerInterface interface Signed-off-by: Yury Kulazhenkov --- pkg/helper/mock/mock_helper.go | 296 +++++------ pkg/host/manager.go | 2 + pkg/host/mock/mock_host.go | 925 +++++++++++++++++++++++++++++++++ 3 files changed, 1075 insertions(+), 148 deletions(-) create mode 100644 pkg/host/mock/mock_host.go diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index c00180cd3..b96b0d4de 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -41,45 +41,45 @@ func (m *MockHostHelpersInterface) EXPECT() *MockHostHelpersInterfaceMockRecorde } // AddUdevRule mocks base method. -func (m *MockHostHelpersInterface) AddUdevRule(arg0 string) error { +func (m *MockHostHelpersInterface) AddUdevRule(pfPciAddress string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddUdevRule", arg0) + ret := m.ctrl.Call(m, "AddUdevRule", pfPciAddress) ret0, _ := ret[0].(error) return ret0 } // AddUdevRule indicates an expected call of AddUdevRule. -func (mr *MockHostHelpersInterfaceMockRecorder) AddUdevRule(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) AddUdevRule(pfPciAddress interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).AddUdevRule), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).AddUdevRule), pfPciAddress) } // BindDefaultDriver mocks base method. -func (m *MockHostHelpersInterface) BindDefaultDriver(arg0 string) error { +func (m *MockHostHelpersInterface) BindDefaultDriver(pciAddr string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BindDefaultDriver", arg0) + ret := m.ctrl.Call(m, "BindDefaultDriver", pciAddr) ret0, _ := ret[0].(error) return ret0 } // BindDefaultDriver indicates an expected call of BindDefaultDriver. -func (mr *MockHostHelpersInterfaceMockRecorder) BindDefaultDriver(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) BindDefaultDriver(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDefaultDriver), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDefaultDriver), pciAddr) } // BindDpdkDriver mocks base method. -func (m *MockHostHelpersInterface) BindDpdkDriver(arg0, arg1 string) error { +func (m *MockHostHelpersInterface) BindDpdkDriver(pciAddr, driver string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BindDpdkDriver", arg0, arg1) + ret := m.ctrl.Call(m, "BindDpdkDriver", pciAddr, driver) ret0, _ := ret[0].(error) return ret0 } // BindDpdkDriver indicates an expected call of BindDpdkDriver. -func (mr *MockHostHelpersInterfaceMockRecorder) BindDpdkDriver(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) BindDpdkDriver(pciAddr, driver interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDpdkDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDpdkDriver), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDpdkDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).BindDpdkDriver), pciAddr, driver) } // BindDriverByBusAndDevice mocks base method. @@ -169,47 +169,47 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovDeviceVirtual(iface i } // ConfigSriovInterfaces mocks base method. -func (m *MockHostHelpersInterface) ConfigSriovInterfaces(arg0 store.ManagerInterface, arg1 []v1.Interface, arg2 []v1.InterfaceExt, arg3 map[string]bool) error { +func (m *MockHostHelpersInterface) ConfigSriovInterfaces(storeManager store.ManagerInterface, interfaces []v1.Interface, ifaceStatuses []v1.InterfaceExt, pfsToConfig map[string]bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ConfigSriovInterfaces", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "ConfigSriovInterfaces", storeManager, interfaces, ifaceStatuses, pfsToConfig) ret0, _ := ret[0].(error) return ret0 } // ConfigSriovInterfaces indicates an expected call of ConfigSriovInterfaces. -func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovInterfaces(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovInterfaces(storeManager, interfaces, ifaceStatuses, pfsToConfig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovInterfaces), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovInterfaces), storeManager, interfaces, ifaceStatuses, pfsToConfig) } // DiscoverSriovDevices mocks base method. -func (m *MockHostHelpersInterface) DiscoverSriovDevices(arg0 store.ManagerInterface) ([]v1.InterfaceExt, error) { +func (m *MockHostHelpersInterface) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]v1.InterfaceExt, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DiscoverSriovDevices", arg0) + ret := m.ctrl.Call(m, "DiscoverSriovDevices", storeManager) ret0, _ := ret[0].([]v1.InterfaceExt) ret1, _ := ret[1].(error) return ret0, ret1 } // DiscoverSriovDevices indicates an expected call of DiscoverSriovDevices. -func (mr *MockHostHelpersInterfaceMockRecorder) DiscoverSriovDevices(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) DiscoverSriovDevices(storeManager interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostHelpersInterface)(nil).DiscoverSriovDevices), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostHelpersInterface)(nil).DiscoverSriovDevices), storeManager) } // EnableRDMA mocks base method. -func (m *MockHostHelpersInterface) EnableRDMA(arg0, arg1, arg2 string) (bool, error) { +func (m *MockHostHelpersInterface) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EnableRDMA", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "EnableRDMA", conditionFilePath, serviceName, packageManager) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // EnableRDMA indicates an expected call of EnableRDMA. -func (mr *MockHostHelpersInterfaceMockRecorder) EnableRDMA(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) EnableRDMA(conditionFilePath, serviceName, packageManager interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).EnableRDMA), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).EnableRDMA), conditionFilePath, serviceName, packageManager) } // EnableRDMAOnRHELMachine mocks base method. @@ -272,17 +272,17 @@ func (mr *MockHostHelpersInterfaceMockRecorder) GetCurrentKernelArgs() *gomock.C } // GetLinkType mocks base method. -func (m *MockHostHelpersInterface) GetLinkType(arg0 v1.InterfaceExt) string { +func (m *MockHostHelpersInterface) GetLinkType(ifaceStatus v1.InterfaceExt) string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLinkType", arg0) + ret := m.ctrl.Call(m, "GetLinkType", ifaceStatus) ret0, _ := ret[0].(string) return ret0 } // GetLinkType indicates an expected call of GetLinkType. -func (mr *MockHostHelpersInterfaceMockRecorder) GetLinkType(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetLinkType(ifaceStatus interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLinkType", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetLinkType), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLinkType", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetLinkType), ifaceStatus) } // GetMellanoxBlueFieldMode mocks base method. @@ -317,60 +317,60 @@ func (mr *MockHostHelpersInterfaceMockRecorder) GetMlxNicFwData(pciAddress inter } // GetNetDevLinkSpeed mocks base method. -func (m *MockHostHelpersInterface) GetNetDevLinkSpeed(arg0 string) string { +func (m *MockHostHelpersInterface) GetNetDevLinkSpeed(name string) string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetDevLinkSpeed", arg0) + ret := m.ctrl.Call(m, "GetNetDevLinkSpeed", name) ret0, _ := ret[0].(string) return ret0 } // GetNetDevLinkSpeed indicates an expected call of GetNetDevLinkSpeed. -func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevLinkSpeed(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevLinkSpeed(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevLinkSpeed", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevLinkSpeed), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevLinkSpeed", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevLinkSpeed), name) } // GetNetDevMac mocks base method. -func (m *MockHostHelpersInterface) GetNetDevMac(arg0 string) string { +func (m *MockHostHelpersInterface) GetNetDevMac(name string) string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetDevMac", arg0) + ret := m.ctrl.Call(m, "GetNetDevMac", name) ret0, _ := ret[0].(string) return ret0 } // GetNetDevMac indicates an expected call of GetNetDevMac. -func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevMac(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetDevMac(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevMac), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetDevMac), name) } // GetNetdevMTU mocks base method. -func (m *MockHostHelpersInterface) GetNetdevMTU(arg0 string) int { +func (m *MockHostHelpersInterface) GetNetdevMTU(pciAddr string) int { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNetdevMTU", arg0) + ret := m.ctrl.Call(m, "GetNetdevMTU", pciAddr) ret0, _ := ret[0].(int) return ret0 } // GetNetdevMTU indicates an expected call of GetNetdevMTU. -func (mr *MockHostHelpersInterfaceMockRecorder) GetNetdevMTU(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetNetdevMTU(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetdevMTU), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNetdevMTU), pciAddr) } // GetNicSriovMode mocks base method. -func (m *MockHostHelpersInterface) GetNicSriovMode(arg0 string) (string, error) { +func (m *MockHostHelpersInterface) GetNicSriovMode(pciAddr string) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetNicSriovMode", arg0) + ret := m.ctrl.Call(m, "GetNicSriovMode", pciAddr) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetNicSriovMode indicates an expected call of GetNicSriovMode. -func (mr *MockHostHelpersInterfaceMockRecorder) GetNicSriovMode(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetNicSriovMode(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNicSriovMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNicSriovMode), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNicSriovMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetNicSriovMode), pciAddr) } // GetOSPrettyName mocks base method. @@ -389,76 +389,76 @@ func (mr *MockHostHelpersInterfaceMockRecorder) GetOSPrettyName() *gomock.Call { } // GetPhysPortName mocks base method. -func (m *MockHostHelpersInterface) GetPhysPortName(arg0 string) (string, error) { +func (m *MockHostHelpersInterface) GetPhysPortName(name string) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPhysPortName", arg0) + ret := m.ctrl.Call(m, "GetPhysPortName", name) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetPhysPortName indicates an expected call of GetPhysPortName. -func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysPortName(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysPortName(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysPortName", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysPortName), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysPortName", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysPortName), name) } // GetPhysSwitchID mocks base method. -func (m *MockHostHelpersInterface) GetPhysSwitchID(arg0 string) (string, error) { +func (m *MockHostHelpersInterface) GetPhysSwitchID(name string) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPhysSwitchID", arg0) + ret := m.ctrl.Call(m, "GetPhysSwitchID", name) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetPhysSwitchID indicates an expected call of GetPhysSwitchID. -func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysSwitchID(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetPhysSwitchID(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysSwitchID", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysSwitchID), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysSwitchID", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetPhysSwitchID), name) } // GetVfInfo mocks base method. -func (m *MockHostHelpersInterface) GetVfInfo(arg0 string, arg1 []*ghw.PCIDevice) v1.VirtualFunction { +func (m *MockHostHelpersInterface) GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) v1.VirtualFunction { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetVfInfo", arg0, arg1) + ret := m.ctrl.Call(m, "GetVfInfo", pciAddr, devices) ret0, _ := ret[0].(v1.VirtualFunction) return ret0 } // GetVfInfo indicates an expected call of GetVfInfo. -func (mr *MockHostHelpersInterfaceMockRecorder) GetVfInfo(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) GetVfInfo(pciAddr, devices interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVfInfo", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetVfInfo), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVfInfo", reflect.TypeOf((*MockHostHelpersInterface)(nil).GetVfInfo), pciAddr, devices) } // HasDriver mocks base method. -func (m *MockHostHelpersInterface) HasDriver(arg0 string) (bool, string) { +func (m *MockHostHelpersInterface) HasDriver(pciAddr string) (bool, string) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasDriver", arg0) + ret := m.ctrl.Call(m, "HasDriver", pciAddr) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(string) return ret0, ret1 } // HasDriver indicates an expected call of HasDriver. -func (mr *MockHostHelpersInterfaceMockRecorder) HasDriver(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) HasDriver(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).HasDriver), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).HasDriver), pciAddr) } // InstallRDMA mocks base method. -func (m *MockHostHelpersInterface) InstallRDMA(arg0 string) error { +func (m *MockHostHelpersInterface) InstallRDMA(packageManager string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InstallRDMA", arg0) + ret := m.ctrl.Call(m, "InstallRDMA", packageManager) ret0, _ := ret[0].(error) return ret0 } // InstallRDMA indicates an expected call of InstallRDMA. -func (mr *MockHostHelpersInterfaceMockRecorder) InstallRDMA(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) InstallRDMA(packageManager interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).InstallRDMA), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallRDMA", reflect.TypeOf((*MockHostHelpersInterface)(nil).InstallRDMA), packageManager) } // IsCoreOS mocks base method. @@ -477,17 +477,17 @@ func (mr *MockHostHelpersInterfaceMockRecorder) IsCoreOS() *gomock.Call { } // IsKernelArgsSet mocks base method. -func (m *MockHostHelpersInterface) IsKernelArgsSet(arg0, arg1 string) bool { +func (m *MockHostHelpersInterface) IsKernelArgsSet(cmdLine, karg string) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsKernelArgsSet", arg0, arg1) + ret := m.ctrl.Call(m, "IsKernelArgsSet", cmdLine, karg) ret0, _ := ret[0].(bool) return ret0 } // IsKernelArgsSet indicates an expected call of IsKernelArgsSet. -func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelArgsSet(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelArgsSet(cmdLine, karg interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelArgsSet", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelArgsSet), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelArgsSet", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelArgsSet), cmdLine, karg) } // IsKernelLockdownMode mocks base method. @@ -505,18 +505,18 @@ func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelLockdownMode() *gomock.C } // IsKernelModuleLoaded mocks base method. -func (m *MockHostHelpersInterface) IsKernelModuleLoaded(arg0 string) (bool, error) { +func (m *MockHostHelpersInterface) IsKernelModuleLoaded(name string) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsKernelModuleLoaded", arg0) + ret := m.ctrl.Call(m, "IsKernelModuleLoaded", name) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // IsKernelModuleLoaded indicates an expected call of IsKernelModuleLoaded. -func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelModuleLoaded(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) IsKernelModuleLoaded(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelModuleLoaded", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelModuleLoaded), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelModuleLoaded", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsKernelModuleLoaded), name) } // IsRHELSystem mocks base method. @@ -535,47 +535,47 @@ func (mr *MockHostHelpersInterfaceMockRecorder) IsRHELSystem() *gomock.Call { } // IsServiceEnabled mocks base method. -func (m *MockHostHelpersInterface) IsServiceEnabled(arg0 string) (bool, error) { +func (m *MockHostHelpersInterface) IsServiceEnabled(servicePath string) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsServiceEnabled", arg0) + ret := m.ctrl.Call(m, "IsServiceEnabled", servicePath) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // IsServiceEnabled indicates an expected call of IsServiceEnabled. -func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceEnabled(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceEnabled(servicePath interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceEnabled", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceEnabled), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceEnabled", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceEnabled), servicePath) } // IsServiceExist mocks base method. -func (m *MockHostHelpersInterface) IsServiceExist(arg0 string) (bool, error) { +func (m *MockHostHelpersInterface) IsServiceExist(servicePath string) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsServiceExist", arg0) + ret := m.ctrl.Call(m, "IsServiceExist", servicePath) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // IsServiceExist indicates an expected call of IsServiceExist. -func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceExist(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) IsServiceExist(servicePath interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceExist", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceExist), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceExist", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsServiceExist), servicePath) } // IsSwitchdev mocks base method. -func (m *MockHostHelpersInterface) IsSwitchdev(arg0 string) bool { +func (m *MockHostHelpersInterface) IsSwitchdev(name string) bool { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsSwitchdev", arg0) + ret := m.ctrl.Call(m, "IsSwitchdev", name) ret0, _ := ret[0].(bool) return ret0 } // IsSwitchdev indicates an expected call of IsSwitchdev. -func (mr *MockHostHelpersInterfaceMockRecorder) IsSwitchdev(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) IsSwitchdev(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSwitchdev", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsSwitchdev), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSwitchdev", reflect.TypeOf((*MockHostHelpersInterface)(nil).IsSwitchdev), name) } // IsUbuntuSystem mocks base method. @@ -659,17 +659,17 @@ func (mr *MockHostHelpersInterfaceMockRecorder) MstConfigReadData(arg0 interface } // PrepareNMUdevRule mocks base method. -func (m *MockHostHelpersInterface) PrepareNMUdevRule(arg0 []string) error { +func (m *MockHostHelpersInterface) PrepareNMUdevRule(supportedVfIds []string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PrepareNMUdevRule", arg0) + ret := m.ctrl.Call(m, "PrepareNMUdevRule", supportedVfIds) ret0, _ := ret[0].(error) return ret0 } // PrepareNMUdevRule indicates an expected call of PrepareNMUdevRule. -func (mr *MockHostHelpersInterfaceMockRecorder) PrepareNMUdevRule(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) PrepareNMUdevRule(supportedVfIds interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareNMUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).PrepareNMUdevRule), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareNMUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).PrepareNMUdevRule), supportedVfIds) } // RdmaIsLoaded mocks base method. @@ -703,18 +703,18 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReadScriptManifestFile(path inte } // ReadService mocks base method. -func (m *MockHostHelpersInterface) ReadService(arg0 string) (*types.Service, error) { +func (m *MockHostHelpersInterface) ReadService(servicePath string) (*types.Service, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReadService", arg0) + ret := m.ctrl.Call(m, "ReadService", servicePath) ret0, _ := ret[0].(*types.Service) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadService indicates an expected call of ReadService. -func (mr *MockHostHelpersInterfaceMockRecorder) ReadService(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) ReadService(servicePath interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadService", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadService), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadService", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReadService), servicePath) } // ReadServiceInjectionManifestFile mocks base method. @@ -748,31 +748,31 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ReadServiceManifestFile(path int } // RebindVfToDefaultDriver mocks base method. -func (m *MockHostHelpersInterface) RebindVfToDefaultDriver(arg0 string) error { +func (m *MockHostHelpersInterface) RebindVfToDefaultDriver(pciAddr string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RebindVfToDefaultDriver", arg0) + ret := m.ctrl.Call(m, "RebindVfToDefaultDriver", pciAddr) ret0, _ := ret[0].(error) return ret0 } // RebindVfToDefaultDriver indicates an expected call of RebindVfToDefaultDriver. -func (mr *MockHostHelpersInterfaceMockRecorder) RebindVfToDefaultDriver(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) RebindVfToDefaultDriver(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebindVfToDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).RebindVfToDefaultDriver), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebindVfToDefaultDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).RebindVfToDefaultDriver), pciAddr) } // ReloadDriver mocks base method. -func (m *MockHostHelpersInterface) ReloadDriver(arg0 string) error { +func (m *MockHostHelpersInterface) ReloadDriver(driver string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReloadDriver", arg0) + ret := m.ctrl.Call(m, "ReloadDriver", driver) ret0, _ := ret[0].(error) return ret0 } // ReloadDriver indicates an expected call of ReloadDriver. -func (mr *MockHostHelpersInterfaceMockRecorder) ReloadDriver(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) ReloadDriver(driver interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReloadDriver), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadDriver", reflect.TypeOf((*MockHostHelpersInterface)(nil).ReloadDriver), driver) } // RemoveFromService mocks base method. @@ -796,31 +796,31 @@ func (mr *MockHostHelpersInterfaceMockRecorder) RemoveFromService(service interf } // RemoveUdevRule mocks base method. -func (m *MockHostHelpersInterface) RemoveUdevRule(arg0 string) error { +func (m *MockHostHelpersInterface) RemoveUdevRule(pfPciAddress string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RemoveUdevRule", arg0) + ret := m.ctrl.Call(m, "RemoveUdevRule", pfPciAddress) ret0, _ := ret[0].(error) return ret0 } // RemoveUdevRule indicates an expected call of RemoveUdevRule. -func (mr *MockHostHelpersInterfaceMockRecorder) RemoveUdevRule(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) RemoveUdevRule(pfPciAddress interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveUdevRule), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveUdevRule), pfPciAddress) } // ResetSriovDevice mocks base method. -func (m *MockHostHelpersInterface) ResetSriovDevice(arg0 v1.InterfaceExt) error { +func (m *MockHostHelpersInterface) ResetSriovDevice(ifaceStatus v1.InterfaceExt) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ResetSriovDevice", arg0) + ret := m.ctrl.Call(m, "ResetSriovDevice", ifaceStatus) ret0, _ := ret[0].(error) return ret0 } // ResetSriovDevice indicates an expected call of ResetSriovDevice. -func (mr *MockHostHelpersInterfaceMockRecorder) ResetSriovDevice(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) ResetSriovDevice(ifaceStatus interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetSriovDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).ResetSriovDevice), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetSriovDevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).ResetSriovDevice), ifaceStatus) } // RunCommand mocks base method. @@ -859,59 +859,59 @@ func (mr *MockHostHelpersInterfaceMockRecorder) SaveLastPfAppliedStatus(PfInfo i } // SetNetdevMTU mocks base method. -func (m *MockHostHelpersInterface) SetNetdevMTU(arg0 string, arg1 int) error { +func (m *MockHostHelpersInterface) SetNetdevMTU(pciAddr string, mtu int) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetNetdevMTU", arg0, arg1) + ret := m.ctrl.Call(m, "SetNetdevMTU", pciAddr, mtu) ret0, _ := ret[0].(error) return ret0 } // SetNetdevMTU indicates an expected call of SetNetdevMTU. -func (mr *MockHostHelpersInterfaceMockRecorder) SetNetdevMTU(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) SetNetdevMTU(pciAddr, mtu interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetNetdevMTU), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetNetdevMTU), pciAddr, mtu) } // SetSriovNumVfs mocks base method. -func (m *MockHostHelpersInterface) SetSriovNumVfs(arg0 string, arg1 int) error { +func (m *MockHostHelpersInterface) SetSriovNumVfs(pciAddr string, numVfs int) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetSriovNumVfs", arg0, arg1) + ret := m.ctrl.Call(m, "SetSriovNumVfs", pciAddr, numVfs) ret0, _ := ret[0].(error) return ret0 } // SetSriovNumVfs indicates an expected call of SetSriovNumVfs. -func (mr *MockHostHelpersInterfaceMockRecorder) SetSriovNumVfs(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) SetSriovNumVfs(pciAddr, numVfs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSriovNumVfs", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetSriovNumVfs), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSriovNumVfs", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetSriovNumVfs), pciAddr, numVfs) } // SetVfAdminMac mocks base method. -func (m *MockHostHelpersInterface) SetVfAdminMac(arg0 string, arg1, arg2 netlink.Link) error { +func (m *MockHostHelpersInterface) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetVfAdminMac", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "SetVfAdminMac", vfAddr, pfLink, vfLink) ret0, _ := ret[0].(error) return ret0 } // SetVfAdminMac indicates an expected call of SetVfAdminMac. -func (mr *MockHostHelpersInterfaceMockRecorder) SetVfAdminMac(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) SetVfAdminMac(vfAddr, pfLink, vfLink interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfAdminMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfAdminMac), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfAdminMac", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfAdminMac), vfAddr, pfLink, vfLink) } // SetVfGUID mocks base method. -func (m *MockHostHelpersInterface) SetVfGUID(arg0 string, arg1 netlink.Link) error { +func (m *MockHostHelpersInterface) SetVfGUID(vfAddr string, pfLink netlink.Link) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetVfGUID", arg0, arg1) + ret := m.ctrl.Call(m, "SetVfGUID", vfAddr, pfLink) ret0, _ := ret[0].(error) return ret0 } // SetVfGUID indicates an expected call of SetVfGUID. -func (mr *MockHostHelpersInterfaceMockRecorder) SetVfGUID(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) SetVfGUID(vfAddr, pfLink interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfGUID", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfGUID), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfGUID", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetVfGUID), vfAddr, pfLink) } // TriggerUdevEvent mocks base method. @@ -968,45 +968,45 @@ func (mr *MockHostHelpersInterfaceMockRecorder) TryEnableVhostNet() *gomock.Call } // TryGetInterfaceName mocks base method. -func (m *MockHostHelpersInterface) TryGetInterfaceName(arg0 string) string { +func (m *MockHostHelpersInterface) TryGetInterfaceName(pciAddr string) string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TryGetInterfaceName", arg0) + ret := m.ctrl.Call(m, "TryGetInterfaceName", pciAddr) ret0, _ := ret[0].(string) return ret0 } // TryGetInterfaceName indicates an expected call of TryGetInterfaceName. -func (mr *MockHostHelpersInterfaceMockRecorder) TryGetInterfaceName(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) TryGetInterfaceName(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryGetInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryGetInterfaceName), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryGetInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryGetInterfaceName), pciAddr) } // TryToGetVirtualInterfaceName mocks base method. -func (m *MockHostHelpersInterface) TryToGetVirtualInterfaceName(arg0 string) string { +func (m *MockHostHelpersInterface) TryToGetVirtualInterfaceName(pciAddr string) string { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TryToGetVirtualInterfaceName", arg0) + ret := m.ctrl.Call(m, "TryToGetVirtualInterfaceName", pciAddr) ret0, _ := ret[0].(string) return ret0 } // TryToGetVirtualInterfaceName indicates an expected call of TryToGetVirtualInterfaceName. -func (mr *MockHostHelpersInterfaceMockRecorder) TryToGetVirtualInterfaceName(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) TryToGetVirtualInterfaceName(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryToGetVirtualInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryToGetVirtualInterfaceName), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryToGetVirtualInterfaceName", reflect.TypeOf((*MockHostHelpersInterface)(nil).TryToGetVirtualInterfaceName), pciAddr) } // Unbind mocks base method. -func (m *MockHostHelpersInterface) Unbind(arg0 string) error { +func (m *MockHostHelpersInterface) Unbind(pciAddr string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Unbind", arg0) + ret := m.ctrl.Call(m, "Unbind", pciAddr) ret0, _ := ret[0].(error) return ret0 } // Unbind indicates an expected call of Unbind. -func (mr *MockHostHelpersInterfaceMockRecorder) Unbind(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) Unbind(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockHostHelpersInterface)(nil).Unbind), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockHostHelpersInterface)(nil).Unbind), pciAddr) } // UnbindDriverByBusAndDevice mocks base method. @@ -1024,17 +1024,17 @@ func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverByBusAndDevice(bus, } // UnbindDriverIfNeeded mocks base method. -func (m *MockHostHelpersInterface) UnbindDriverIfNeeded(arg0 string, arg1 bool) error { +func (m *MockHostHelpersInterface) UnbindDriverIfNeeded(pciAddr string, isRdma bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UnbindDriverIfNeeded", arg0, arg1) + ret := m.ctrl.Call(m, "UnbindDriverIfNeeded", pciAddr, isRdma) ret0, _ := ret[0].(error) return ret0 } // UnbindDriverIfNeeded indicates an expected call of UnbindDriverIfNeeded. -func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverIfNeeded(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) UnbindDriverIfNeeded(pciAddr, isRdma interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverIfNeeded", reflect.TypeOf((*MockHostHelpersInterface)(nil).UnbindDriverIfNeeded), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverIfNeeded", reflect.TypeOf((*MockHostHelpersInterface)(nil).UnbindDriverIfNeeded), pciAddr, isRdma) } // UpdateSystemService mocks base method. @@ -1052,18 +1052,18 @@ func (mr *MockHostHelpersInterfaceMockRecorder) UpdateSystemService(serviceObj i } // VFIsReady mocks base method. -func (m *MockHostHelpersInterface) VFIsReady(arg0 string) (netlink.Link, error) { +func (m *MockHostHelpersInterface) VFIsReady(pciAddr string) (netlink.Link, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VFIsReady", arg0) + ret := m.ctrl.Call(m, "VFIsReady", pciAddr) ret0, _ := ret[0].(netlink.Link) ret1, _ := ret[1].(error) return ret0, ret1 } // VFIsReady indicates an expected call of VFIsReady. -func (mr *MockHostHelpersInterfaceMockRecorder) VFIsReady(arg0 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) VFIsReady(pciAddr interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VFIsReady", reflect.TypeOf((*MockHostHelpersInterface)(nil).VFIsReady), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VFIsReady", reflect.TypeOf((*MockHostHelpersInterface)(nil).VFIsReady), pciAddr) } // WriteCheckpointFile mocks base method. @@ -1081,16 +1081,16 @@ func (mr *MockHostHelpersInterfaceMockRecorder) WriteCheckpointFile(arg0 interfa } // WriteSwitchdevConfFile mocks base method. -func (m *MockHostHelpersInterface) WriteSwitchdevConfFile(arg0 *v1.SriovNetworkNodeState, arg1 map[string]bool) (bool, error) { +func (m *MockHostHelpersInterface) WriteSwitchdevConfFile(newState *v1.SriovNetworkNodeState, pfsToSkip map[string]bool) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WriteSwitchdevConfFile", arg0, arg1) + ret := m.ctrl.Call(m, "WriteSwitchdevConfFile", newState, pfsToSkip) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // WriteSwitchdevConfFile indicates an expected call of WriteSwitchdevConfFile. -func (mr *MockHostHelpersInterfaceMockRecorder) WriteSwitchdevConfFile(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockHostHelpersInterfaceMockRecorder) WriteSwitchdevConfFile(newState, pfsToSkip interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSwitchdevConfFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).WriteSwitchdevConfFile), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSwitchdevConfFile", reflect.TypeOf((*MockHostHelpersInterface)(nil).WriteSwitchdevConfFile), newState, pfsToSkip) } diff --git a/pkg/host/manager.go b/pkg/host/manager.go index 3b0f790e9..3983fa9b6 100644 --- a/pkg/host/manager.go +++ b/pkg/host/manager.go @@ -11,6 +11,8 @@ import ( ) // Contains all the host manipulation functions +// +//go:generate ../../bin/mockgen -destination mock/mock_host.go -source manager.go type HostManagerInterface interface { types.KernelInterface types.NetworkInterface diff --git a/pkg/host/mock/mock_host.go b/pkg/host/mock/mock_host.go new file mode 100644 index 000000000..7c52fd28b --- /dev/null +++ b/pkg/host/mock/mock_host.go @@ -0,0 +1,925 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: manager.go + +// Package mock_host is a generated GoMock package. +package mock_host + +import ( + reflect "reflect" + + unit "github.com/coreos/go-systemd/v22/unit" + gomock "github.com/golang/mock/gomock" + ghw "github.com/jaypipes/ghw" + v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + store "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" + types "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" + netlink "github.com/vishvananda/netlink" +) + +// MockHostManagerInterface is a mock of HostManagerInterface interface. +type MockHostManagerInterface struct { + ctrl *gomock.Controller + recorder *MockHostManagerInterfaceMockRecorder +} + +// MockHostManagerInterfaceMockRecorder is the mock recorder for MockHostManagerInterface. +type MockHostManagerInterfaceMockRecorder struct { + mock *MockHostManagerInterface +} + +// NewMockHostManagerInterface creates a new mock instance. +func NewMockHostManagerInterface(ctrl *gomock.Controller) *MockHostManagerInterface { + mock := &MockHostManagerInterface{ctrl: ctrl} + mock.recorder = &MockHostManagerInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHostManagerInterface) EXPECT() *MockHostManagerInterfaceMockRecorder { + return m.recorder +} + +// AddUdevRule mocks base method. +func (m *MockHostManagerInterface) AddUdevRule(pfPciAddress string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddUdevRule", pfPciAddress) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddUdevRule indicates an expected call of AddUdevRule. +func (mr *MockHostManagerInterfaceMockRecorder) AddUdevRule(pfPciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).AddUdevRule), pfPciAddress) +} + +// BindDefaultDriver mocks base method. +func (m *MockHostManagerInterface) BindDefaultDriver(pciAddr string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDefaultDriver", pciAddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDefaultDriver indicates an expected call of BindDefaultDriver. +func (mr *MockHostManagerInterfaceMockRecorder) BindDefaultDriver(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDefaultDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).BindDefaultDriver), pciAddr) +} + +// BindDpdkDriver mocks base method. +func (m *MockHostManagerInterface) BindDpdkDriver(pciAddr, driver string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDpdkDriver", pciAddr, driver) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDpdkDriver indicates an expected call of BindDpdkDriver. +func (mr *MockHostManagerInterfaceMockRecorder) BindDpdkDriver(pciAddr, driver interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDpdkDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).BindDpdkDriver), pciAddr, driver) +} + +// BindDriverByBusAndDevice mocks base method. +func (m *MockHostManagerInterface) BindDriverByBusAndDevice(bus, device, driver string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BindDriverByBusAndDevice", bus, device, driver) + ret0, _ := ret[0].(error) + return ret0 +} + +// BindDriverByBusAndDevice indicates an expected call of BindDriverByBusAndDevice. +func (mr *MockHostManagerInterfaceMockRecorder) BindDriverByBusAndDevice(bus, device, driver interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindDriverByBusAndDevice", reflect.TypeOf((*MockHostManagerInterface)(nil).BindDriverByBusAndDevice), bus, device, driver) +} + +// CompareServices mocks base method. +func (m *MockHostManagerInterface) CompareServices(serviceA, serviceB *types.Service) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CompareServices", serviceA, serviceB) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CompareServices indicates an expected call of CompareServices. +func (mr *MockHostManagerInterfaceMockRecorder) CompareServices(serviceA, serviceB interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompareServices", reflect.TypeOf((*MockHostManagerInterface)(nil).CompareServices), serviceA, serviceB) +} + +// ConfigSriovDevice mocks base method. +func (m *MockHostManagerInterface) ConfigSriovDevice(iface *v1.Interface, ifaceStatus *v1.InterfaceExt) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovDevice", iface, ifaceStatus) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovDevice indicates an expected call of ConfigSriovDevice. +func (mr *MockHostManagerInterfaceMockRecorder) ConfigSriovDevice(iface, ifaceStatus interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovDevice", reflect.TypeOf((*MockHostManagerInterface)(nil).ConfigSriovDevice), iface, ifaceStatus) +} + +// ConfigSriovDeviceVirtual mocks base method. +func (m *MockHostManagerInterface) ConfigSriovDeviceVirtual(iface *v1.Interface) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovDeviceVirtual", iface) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovDeviceVirtual indicates an expected call of ConfigSriovDeviceVirtual. +func (mr *MockHostManagerInterfaceMockRecorder) ConfigSriovDeviceVirtual(iface interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovDeviceVirtual", reflect.TypeOf((*MockHostManagerInterface)(nil).ConfigSriovDeviceVirtual), iface) +} + +// ConfigSriovInterfaces mocks base method. +func (m *MockHostManagerInterface) ConfigSriovInterfaces(storeManager store.ManagerInterface, interfaces []v1.Interface, ifaceStatuses []v1.InterfaceExt, pfsToConfig map[string]bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigSriovInterfaces", storeManager, interfaces, ifaceStatuses, pfsToConfig) + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigSriovInterfaces indicates an expected call of ConfigSriovInterfaces. +func (mr *MockHostManagerInterfaceMockRecorder) ConfigSriovInterfaces(storeManager, interfaces, ifaceStatuses, pfsToConfig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostManagerInterface)(nil).ConfigSriovInterfaces), storeManager, interfaces, ifaceStatuses, pfsToConfig) +} + +// DiscoverSriovDevices mocks base method. +func (m *MockHostManagerInterface) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]v1.InterfaceExt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverSriovDevices", storeManager) + ret0, _ := ret[0].([]v1.InterfaceExt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DiscoverSriovDevices indicates an expected call of DiscoverSriovDevices. +func (mr *MockHostManagerInterfaceMockRecorder) DiscoverSriovDevices(storeManager interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostManagerInterface)(nil).DiscoverSriovDevices), storeManager) +} + +// EnableRDMA mocks base method. +func (m *MockHostManagerInterface) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableRDMA", conditionFilePath, serviceName, packageManager) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EnableRDMA indicates an expected call of EnableRDMA. +func (mr *MockHostManagerInterfaceMockRecorder) EnableRDMA(conditionFilePath, serviceName, packageManager interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMA", reflect.TypeOf((*MockHostManagerInterface)(nil).EnableRDMA), conditionFilePath, serviceName, packageManager) +} + +// EnableRDMAOnRHELMachine mocks base method. +func (m *MockHostManagerInterface) EnableRDMAOnRHELMachine() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableRDMAOnRHELMachine") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EnableRDMAOnRHELMachine indicates an expected call of EnableRDMAOnRHELMachine. +func (mr *MockHostManagerInterfaceMockRecorder) EnableRDMAOnRHELMachine() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableRDMAOnRHELMachine", reflect.TypeOf((*MockHostManagerInterface)(nil).EnableRDMAOnRHELMachine)) +} + +// EnableService mocks base method. +func (m *MockHostManagerInterface) EnableService(service *types.Service) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableService", service) + ret0, _ := ret[0].(error) + return ret0 +} + +// EnableService indicates an expected call of EnableService. +func (mr *MockHostManagerInterfaceMockRecorder) EnableService(service interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableService", reflect.TypeOf((*MockHostManagerInterface)(nil).EnableService), service) +} + +// GetCurrentKernelArgs mocks base method. +func (m *MockHostManagerInterface) GetCurrentKernelArgs() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentKernelArgs") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentKernelArgs indicates an expected call of GetCurrentKernelArgs. +func (mr *MockHostManagerInterfaceMockRecorder) GetCurrentKernelArgs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentKernelArgs", reflect.TypeOf((*MockHostManagerInterface)(nil).GetCurrentKernelArgs)) +} + +// GetLinkType mocks base method. +func (m *MockHostManagerInterface) GetLinkType(ifaceStatus v1.InterfaceExt) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLinkType", ifaceStatus) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetLinkType indicates an expected call of GetLinkType. +func (mr *MockHostManagerInterfaceMockRecorder) GetLinkType(ifaceStatus interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLinkType", reflect.TypeOf((*MockHostManagerInterface)(nil).GetLinkType), ifaceStatus) +} + +// GetNetDevLinkSpeed mocks base method. +func (m *MockHostManagerInterface) GetNetDevLinkSpeed(name string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetDevLinkSpeed", name) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetNetDevLinkSpeed indicates an expected call of GetNetDevLinkSpeed. +func (mr *MockHostManagerInterfaceMockRecorder) GetNetDevLinkSpeed(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevLinkSpeed", reflect.TypeOf((*MockHostManagerInterface)(nil).GetNetDevLinkSpeed), name) +} + +// GetNetDevMac mocks base method. +func (m *MockHostManagerInterface) GetNetDevMac(name string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetDevMac", name) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetNetDevMac indicates an expected call of GetNetDevMac. +func (mr *MockHostManagerInterfaceMockRecorder) GetNetDevMac(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetDevMac", reflect.TypeOf((*MockHostManagerInterface)(nil).GetNetDevMac), name) +} + +// GetNetdevMTU mocks base method. +func (m *MockHostManagerInterface) GetNetdevMTU(pciAddr string) int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetdevMTU", pciAddr) + ret0, _ := ret[0].(int) + return ret0 +} + +// GetNetdevMTU indicates an expected call of GetNetdevMTU. +func (mr *MockHostManagerInterfaceMockRecorder) GetNetdevMTU(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetdevMTU", reflect.TypeOf((*MockHostManagerInterface)(nil).GetNetdevMTU), pciAddr) +} + +// GetNicSriovMode mocks base method. +func (m *MockHostManagerInterface) GetNicSriovMode(pciAddr string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNicSriovMode", pciAddr) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetNicSriovMode indicates an expected call of GetNicSriovMode. +func (mr *MockHostManagerInterfaceMockRecorder) GetNicSriovMode(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNicSriovMode", reflect.TypeOf((*MockHostManagerInterface)(nil).GetNicSriovMode), pciAddr) +} + +// GetOSPrettyName mocks base method. +func (m *MockHostManagerInterface) GetOSPrettyName() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOSPrettyName") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetOSPrettyName indicates an expected call of GetOSPrettyName. +func (mr *MockHostManagerInterfaceMockRecorder) GetOSPrettyName() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOSPrettyName", reflect.TypeOf((*MockHostManagerInterface)(nil).GetOSPrettyName)) +} + +// GetPhysPortName mocks base method. +func (m *MockHostManagerInterface) GetPhysPortName(name string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPhysPortName", name) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPhysPortName indicates an expected call of GetPhysPortName. +func (mr *MockHostManagerInterfaceMockRecorder) GetPhysPortName(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysPortName", reflect.TypeOf((*MockHostManagerInterface)(nil).GetPhysPortName), name) +} + +// GetPhysSwitchID mocks base method. +func (m *MockHostManagerInterface) GetPhysSwitchID(name string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPhysSwitchID", name) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPhysSwitchID indicates an expected call of GetPhysSwitchID. +func (mr *MockHostManagerInterfaceMockRecorder) GetPhysSwitchID(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhysSwitchID", reflect.TypeOf((*MockHostManagerInterface)(nil).GetPhysSwitchID), name) +} + +// GetVfInfo mocks base method. +func (m *MockHostManagerInterface) GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) v1.VirtualFunction { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVfInfo", pciAddr, devices) + ret0, _ := ret[0].(v1.VirtualFunction) + return ret0 +} + +// GetVfInfo indicates an expected call of GetVfInfo. +func (mr *MockHostManagerInterfaceMockRecorder) GetVfInfo(pciAddr, devices interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVfInfo", reflect.TypeOf((*MockHostManagerInterface)(nil).GetVfInfo), pciAddr, devices) +} + +// HasDriver mocks base method. +func (m *MockHostManagerInterface) HasDriver(pciAddr string) (bool, string) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasDriver", pciAddr) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + return ret0, ret1 +} + +// HasDriver indicates an expected call of HasDriver. +func (mr *MockHostManagerInterfaceMockRecorder) HasDriver(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).HasDriver), pciAddr) +} + +// InstallRDMA mocks base method. +func (m *MockHostManagerInterface) InstallRDMA(packageManager string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InstallRDMA", packageManager) + ret0, _ := ret[0].(error) + return ret0 +} + +// InstallRDMA indicates an expected call of InstallRDMA. +func (mr *MockHostManagerInterfaceMockRecorder) InstallRDMA(packageManager interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstallRDMA", reflect.TypeOf((*MockHostManagerInterface)(nil).InstallRDMA), packageManager) +} + +// IsCoreOS mocks base method. +func (m *MockHostManagerInterface) IsCoreOS() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsCoreOS") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsCoreOS indicates an expected call of IsCoreOS. +func (mr *MockHostManagerInterfaceMockRecorder) IsCoreOS() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsCoreOS", reflect.TypeOf((*MockHostManagerInterface)(nil).IsCoreOS)) +} + +// IsKernelArgsSet mocks base method. +func (m *MockHostManagerInterface) IsKernelArgsSet(cmdLine, karg string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelArgsSet", cmdLine, karg) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsKernelArgsSet indicates an expected call of IsKernelArgsSet. +func (mr *MockHostManagerInterfaceMockRecorder) IsKernelArgsSet(cmdLine, karg interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelArgsSet", reflect.TypeOf((*MockHostManagerInterface)(nil).IsKernelArgsSet), cmdLine, karg) +} + +// IsKernelLockdownMode mocks base method. +func (m *MockHostManagerInterface) IsKernelLockdownMode() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelLockdownMode") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsKernelLockdownMode indicates an expected call of IsKernelLockdownMode. +func (mr *MockHostManagerInterfaceMockRecorder) IsKernelLockdownMode() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelLockdownMode", reflect.TypeOf((*MockHostManagerInterface)(nil).IsKernelLockdownMode)) +} + +// IsKernelModuleLoaded mocks base method. +func (m *MockHostManagerInterface) IsKernelModuleLoaded(name string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsKernelModuleLoaded", name) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsKernelModuleLoaded indicates an expected call of IsKernelModuleLoaded. +func (mr *MockHostManagerInterfaceMockRecorder) IsKernelModuleLoaded(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsKernelModuleLoaded", reflect.TypeOf((*MockHostManagerInterface)(nil).IsKernelModuleLoaded), name) +} + +// IsRHELSystem mocks base method. +func (m *MockHostManagerInterface) IsRHELSystem() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsRHELSystem") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsRHELSystem indicates an expected call of IsRHELSystem. +func (mr *MockHostManagerInterfaceMockRecorder) IsRHELSystem() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsRHELSystem", reflect.TypeOf((*MockHostManagerInterface)(nil).IsRHELSystem)) +} + +// IsServiceEnabled mocks base method. +func (m *MockHostManagerInterface) IsServiceEnabled(servicePath string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsServiceEnabled", servicePath) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsServiceEnabled indicates an expected call of IsServiceEnabled. +func (mr *MockHostManagerInterfaceMockRecorder) IsServiceEnabled(servicePath interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceEnabled", reflect.TypeOf((*MockHostManagerInterface)(nil).IsServiceEnabled), servicePath) +} + +// IsServiceExist mocks base method. +func (m *MockHostManagerInterface) IsServiceExist(servicePath string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsServiceExist", servicePath) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsServiceExist indicates an expected call of IsServiceExist. +func (mr *MockHostManagerInterfaceMockRecorder) IsServiceExist(servicePath interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsServiceExist", reflect.TypeOf((*MockHostManagerInterface)(nil).IsServiceExist), servicePath) +} + +// IsSwitchdev mocks base method. +func (m *MockHostManagerInterface) IsSwitchdev(name string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSwitchdev", name) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSwitchdev indicates an expected call of IsSwitchdev. +func (mr *MockHostManagerInterfaceMockRecorder) IsSwitchdev(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSwitchdev", reflect.TypeOf((*MockHostManagerInterface)(nil).IsSwitchdev), name) +} + +// IsUbuntuSystem mocks base method. +func (m *MockHostManagerInterface) IsUbuntuSystem() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsUbuntuSystem") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsUbuntuSystem indicates an expected call of IsUbuntuSystem. +func (mr *MockHostManagerInterfaceMockRecorder) IsUbuntuSystem() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUbuntuSystem", reflect.TypeOf((*MockHostManagerInterface)(nil).IsUbuntuSystem)) +} + +// LoadKernelModule mocks base method. +func (m *MockHostManagerInterface) LoadKernelModule(name string, args ...string) error { + m.ctrl.T.Helper() + varargs := []interface{}{name} + for _, a := range args { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "LoadKernelModule", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// LoadKernelModule indicates an expected call of LoadKernelModule. +func (mr *MockHostManagerInterfaceMockRecorder) LoadKernelModule(name interface{}, args ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{name}, args...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadKernelModule", reflect.TypeOf((*MockHostManagerInterface)(nil).LoadKernelModule), varargs...) +} + +// PrepareNMUdevRule mocks base method. +func (m *MockHostManagerInterface) PrepareNMUdevRule(supportedVfIds []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PrepareNMUdevRule", supportedVfIds) + ret0, _ := ret[0].(error) + return ret0 +} + +// PrepareNMUdevRule indicates an expected call of PrepareNMUdevRule. +func (mr *MockHostManagerInterfaceMockRecorder) PrepareNMUdevRule(supportedVfIds interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareNMUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).PrepareNMUdevRule), supportedVfIds) +} + +// RdmaIsLoaded mocks base method. +func (m *MockHostManagerInterface) RdmaIsLoaded() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RdmaIsLoaded") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RdmaIsLoaded indicates an expected call of RdmaIsLoaded. +func (mr *MockHostManagerInterfaceMockRecorder) RdmaIsLoaded() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RdmaIsLoaded", reflect.TypeOf((*MockHostManagerInterface)(nil).RdmaIsLoaded)) +} + +// ReadScriptManifestFile mocks base method. +func (m *MockHostManagerInterface) ReadScriptManifestFile(path string) (*types.ScriptManifestFile, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadScriptManifestFile", path) + ret0, _ := ret[0].(*types.ScriptManifestFile) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadScriptManifestFile indicates an expected call of ReadScriptManifestFile. +func (mr *MockHostManagerInterfaceMockRecorder) ReadScriptManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadScriptManifestFile", reflect.TypeOf((*MockHostManagerInterface)(nil).ReadScriptManifestFile), path) +} + +// ReadService mocks base method. +func (m *MockHostManagerInterface) ReadService(servicePath string) (*types.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadService", servicePath) + ret0, _ := ret[0].(*types.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadService indicates an expected call of ReadService. +func (mr *MockHostManagerInterfaceMockRecorder) ReadService(servicePath interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadService", reflect.TypeOf((*MockHostManagerInterface)(nil).ReadService), servicePath) +} + +// ReadServiceInjectionManifestFile mocks base method. +func (m *MockHostManagerInterface) ReadServiceInjectionManifestFile(path string) (*types.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadServiceInjectionManifestFile", path) + ret0, _ := ret[0].(*types.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadServiceInjectionManifestFile indicates an expected call of ReadServiceInjectionManifestFile. +func (mr *MockHostManagerInterfaceMockRecorder) ReadServiceInjectionManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadServiceInjectionManifestFile", reflect.TypeOf((*MockHostManagerInterface)(nil).ReadServiceInjectionManifestFile), path) +} + +// ReadServiceManifestFile mocks base method. +func (m *MockHostManagerInterface) ReadServiceManifestFile(path string) (*types.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadServiceManifestFile", path) + ret0, _ := ret[0].(*types.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadServiceManifestFile indicates an expected call of ReadServiceManifestFile. +func (mr *MockHostManagerInterfaceMockRecorder) ReadServiceManifestFile(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadServiceManifestFile", reflect.TypeOf((*MockHostManagerInterface)(nil).ReadServiceManifestFile), path) +} + +// RebindVfToDefaultDriver mocks base method. +func (m *MockHostManagerInterface) RebindVfToDefaultDriver(pciAddr string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RebindVfToDefaultDriver", pciAddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// RebindVfToDefaultDriver indicates an expected call of RebindVfToDefaultDriver. +func (mr *MockHostManagerInterfaceMockRecorder) RebindVfToDefaultDriver(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RebindVfToDefaultDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).RebindVfToDefaultDriver), pciAddr) +} + +// ReloadDriver mocks base method. +func (m *MockHostManagerInterface) ReloadDriver(driver string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReloadDriver", driver) + ret0, _ := ret[0].(error) + return ret0 +} + +// ReloadDriver indicates an expected call of ReloadDriver. +func (mr *MockHostManagerInterfaceMockRecorder) ReloadDriver(driver interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReloadDriver", reflect.TypeOf((*MockHostManagerInterface)(nil).ReloadDriver), driver) +} + +// RemoveFromService mocks base method. +func (m *MockHostManagerInterface) RemoveFromService(service *types.Service, options ...*unit.UnitOption) (*types.Service, error) { + m.ctrl.T.Helper() + varargs := []interface{}{service} + for _, a := range options { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveFromService", varargs...) + ret0, _ := ret[0].(*types.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveFromService indicates an expected call of RemoveFromService. +func (mr *MockHostManagerInterfaceMockRecorder) RemoveFromService(service interface{}, options ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{service}, options...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveFromService", reflect.TypeOf((*MockHostManagerInterface)(nil).RemoveFromService), varargs...) +} + +// RemoveUdevRule mocks base method. +func (m *MockHostManagerInterface) RemoveUdevRule(pfPciAddress string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveUdevRule", pfPciAddress) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveUdevRule indicates an expected call of RemoveUdevRule. +func (mr *MockHostManagerInterfaceMockRecorder) RemoveUdevRule(pfPciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).RemoveUdevRule), pfPciAddress) +} + +// ResetSriovDevice mocks base method. +func (m *MockHostManagerInterface) ResetSriovDevice(ifaceStatus v1.InterfaceExt) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResetSriovDevice", ifaceStatus) + ret0, _ := ret[0].(error) + return ret0 +} + +// ResetSriovDevice indicates an expected call of ResetSriovDevice. +func (mr *MockHostManagerInterfaceMockRecorder) ResetSriovDevice(ifaceStatus interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetSriovDevice", reflect.TypeOf((*MockHostManagerInterface)(nil).ResetSriovDevice), ifaceStatus) +} + +// SetNetdevMTU mocks base method. +func (m *MockHostManagerInterface) SetNetdevMTU(pciAddr string, mtu int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetNetdevMTU", pciAddr, mtu) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetNetdevMTU indicates an expected call of SetNetdevMTU. +func (mr *MockHostManagerInterfaceMockRecorder) SetNetdevMTU(pciAddr, mtu interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostManagerInterface)(nil).SetNetdevMTU), pciAddr, mtu) +} + +// SetSriovNumVfs mocks base method. +func (m *MockHostManagerInterface) SetSriovNumVfs(pciAddr string, numVfs int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetSriovNumVfs", pciAddr, numVfs) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetSriovNumVfs indicates an expected call of SetSriovNumVfs. +func (mr *MockHostManagerInterfaceMockRecorder) SetSriovNumVfs(pciAddr, numVfs interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSriovNumVfs", reflect.TypeOf((*MockHostManagerInterface)(nil).SetSriovNumVfs), pciAddr, numVfs) +} + +// SetVfAdminMac mocks base method. +func (m *MockHostManagerInterface) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetVfAdminMac", vfAddr, pfLink, vfLink) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetVfAdminMac indicates an expected call of SetVfAdminMac. +func (mr *MockHostManagerInterfaceMockRecorder) SetVfAdminMac(vfAddr, pfLink, vfLink interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfAdminMac", reflect.TypeOf((*MockHostManagerInterface)(nil).SetVfAdminMac), vfAddr, pfLink, vfLink) +} + +// SetVfGUID mocks base method. +func (m *MockHostManagerInterface) SetVfGUID(vfAddr string, pfLink netlink.Link) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetVfGUID", vfAddr, pfLink) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetVfGUID indicates an expected call of SetVfGUID. +func (mr *MockHostManagerInterfaceMockRecorder) SetVfGUID(vfAddr, pfLink interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVfGUID", reflect.TypeOf((*MockHostManagerInterface)(nil).SetVfGUID), vfAddr, pfLink) +} + +// TriggerUdevEvent mocks base method. +func (m *MockHostManagerInterface) TriggerUdevEvent() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TriggerUdevEvent") + ret0, _ := ret[0].(error) + return ret0 +} + +// TriggerUdevEvent indicates an expected call of TriggerUdevEvent. +func (mr *MockHostManagerInterfaceMockRecorder) TriggerUdevEvent() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TriggerUdevEvent", reflect.TypeOf((*MockHostManagerInterface)(nil).TriggerUdevEvent)) +} + +// TryEnableRdma mocks base method. +func (m *MockHostManagerInterface) TryEnableRdma() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryEnableRdma") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TryEnableRdma indicates an expected call of TryEnableRdma. +func (mr *MockHostManagerInterfaceMockRecorder) TryEnableRdma() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableRdma", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableRdma)) +} + +// TryEnableTun mocks base method. +func (m *MockHostManagerInterface) TryEnableTun() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TryEnableTun") +} + +// TryEnableTun indicates an expected call of TryEnableTun. +func (mr *MockHostManagerInterfaceMockRecorder) TryEnableTun() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableTun", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableTun)) +} + +// TryEnableVhostNet mocks base method. +func (m *MockHostManagerInterface) TryEnableVhostNet() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "TryEnableVhostNet") +} + +// TryEnableVhostNet indicates an expected call of TryEnableVhostNet. +func (mr *MockHostManagerInterfaceMockRecorder) TryEnableVhostNet() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryEnableVhostNet", reflect.TypeOf((*MockHostManagerInterface)(nil).TryEnableVhostNet)) +} + +// TryGetInterfaceName mocks base method. +func (m *MockHostManagerInterface) TryGetInterfaceName(pciAddr string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryGetInterfaceName", pciAddr) + ret0, _ := ret[0].(string) + return ret0 +} + +// TryGetInterfaceName indicates an expected call of TryGetInterfaceName. +func (mr *MockHostManagerInterfaceMockRecorder) TryGetInterfaceName(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryGetInterfaceName", reflect.TypeOf((*MockHostManagerInterface)(nil).TryGetInterfaceName), pciAddr) +} + +// TryToGetVirtualInterfaceName mocks base method. +func (m *MockHostManagerInterface) TryToGetVirtualInterfaceName(pciAddr string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TryToGetVirtualInterfaceName", pciAddr) + ret0, _ := ret[0].(string) + return ret0 +} + +// TryToGetVirtualInterfaceName indicates an expected call of TryToGetVirtualInterfaceName. +func (mr *MockHostManagerInterfaceMockRecorder) TryToGetVirtualInterfaceName(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryToGetVirtualInterfaceName", reflect.TypeOf((*MockHostManagerInterface)(nil).TryToGetVirtualInterfaceName), pciAddr) +} + +// Unbind mocks base method. +func (m *MockHostManagerInterface) Unbind(pciAddr string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Unbind", pciAddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// Unbind indicates an expected call of Unbind. +func (mr *MockHostManagerInterfaceMockRecorder) Unbind(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unbind", reflect.TypeOf((*MockHostManagerInterface)(nil).Unbind), pciAddr) +} + +// UnbindDriverByBusAndDevice mocks base method. +func (m *MockHostManagerInterface) UnbindDriverByBusAndDevice(bus, device string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbindDriverByBusAndDevice", bus, device) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnbindDriverByBusAndDevice indicates an expected call of UnbindDriverByBusAndDevice. +func (mr *MockHostManagerInterfaceMockRecorder) UnbindDriverByBusAndDevice(bus, device interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverByBusAndDevice", reflect.TypeOf((*MockHostManagerInterface)(nil).UnbindDriverByBusAndDevice), bus, device) +} + +// UnbindDriverIfNeeded mocks base method. +func (m *MockHostManagerInterface) UnbindDriverIfNeeded(pciAddr string, isRdma bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UnbindDriverIfNeeded", pciAddr, isRdma) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnbindDriverIfNeeded indicates an expected call of UnbindDriverIfNeeded. +func (mr *MockHostManagerInterfaceMockRecorder) UnbindDriverIfNeeded(pciAddr, isRdma interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnbindDriverIfNeeded", reflect.TypeOf((*MockHostManagerInterface)(nil).UnbindDriverIfNeeded), pciAddr, isRdma) +} + +// UpdateSystemService mocks base method. +func (m *MockHostManagerInterface) UpdateSystemService(serviceObj *types.Service) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateSystemService", serviceObj) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateSystemService indicates an expected call of UpdateSystemService. +func (mr *MockHostManagerInterfaceMockRecorder) UpdateSystemService(serviceObj interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSystemService", reflect.TypeOf((*MockHostManagerInterface)(nil).UpdateSystemService), serviceObj) +} + +// VFIsReady mocks base method. +func (m *MockHostManagerInterface) VFIsReady(pciAddr string) (netlink.Link, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "VFIsReady", pciAddr) + ret0, _ := ret[0].(netlink.Link) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// VFIsReady indicates an expected call of VFIsReady. +func (mr *MockHostManagerInterfaceMockRecorder) VFIsReady(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VFIsReady", reflect.TypeOf((*MockHostManagerInterface)(nil).VFIsReady), pciAddr) +} + +// WriteSwitchdevConfFile mocks base method. +func (m *MockHostManagerInterface) WriteSwitchdevConfFile(newState *v1.SriovNetworkNodeState, pfsToSkip map[string]bool) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteSwitchdevConfFile", newState, pfsToSkip) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WriteSwitchdevConfFile indicates an expected call of WriteSwitchdevConfFile. +func (mr *MockHostManagerInterfaceMockRecorder) WriteSwitchdevConfFile(newState, pfsToSkip interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSwitchdevConfFile", reflect.TypeOf((*MockHostManagerInterface)(nil).WriteSwitchdevConfFile), newState, pfsToSkip) +} From a63e2ef7cde56187c751989bff03243b262ccc58 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Mon, 22 Jan 2024 11:40:24 +0200 Subject: [PATCH 29/61] CI: remove images after we push to cluster removing the images after we push as part of the CI, we need this to avoid exploding the CI nodes Signed-off-by: Sebastian Sch --- hack/run-e2e-conformance-virtual-cluster.sh | 3 +++ hack/run-e2e-conformance-virtual-ocp.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/hack/run-e2e-conformance-virtual-cluster.sh b/hack/run-e2e-conformance-virtual-cluster.sh index 8c276fb4e..90670f2df 100755 --- a/hack/run-e2e-conformance-virtual-cluster.sh +++ b/hack/run-e2e-conformance-virtual-cluster.sh @@ -271,8 +271,11 @@ echo "## build webhook image" podman build -t "${SRIOV_NETWORK_WEBHOOK_IMAGE}" -f "${root}/Dockerfile.webhook" "${root}" podman push --tls-verify=false "${SRIOV_NETWORK_OPERATOR_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_OPERATOR_IMAGE} podman push --tls-verify=false "${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE} podman push --tls-verify=false "${SRIOV_NETWORK_WEBHOOK_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_WEBHOOK_IMAGE} # remove the crio bridge and let flannel to recreate kcli ssh $cluster_name-ctlplane-0 << EOF diff --git a/hack/run-e2e-conformance-virtual-ocp.sh b/hack/run-e2e-conformance-virtual-ocp.sh index 0cd188c19..66a1cc910 100755 --- a/hack/run-e2e-conformance-virtual-ocp.sh +++ b/hack/run-e2e-conformance-virtual-ocp.sh @@ -215,8 +215,11 @@ pass=$( jq .\"$internal_registry\".password registry-login.conf ) podman login -u serviceaccount -p ${pass:1:-1} $registry --tls-verify=false podman push --tls-verify=false "${SRIOV_NETWORK_OPERATOR_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_OPERATOR_IMAGE} podman push --tls-verify=false "${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE} podman push --tls-verify=false "${SRIOV_NETWORK_WEBHOOK_IMAGE}" +podman rmi -fi ${SRIOV_NETWORK_WEBHOOK_IMAGE} podman logout $registry From c59dc72df0add027d76b0a23c3de36e4a667e393 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Fri, 19 Jan 2024 14:09:03 +0200 Subject: [PATCH 30/61] Create a separate pkg for test helper functions Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/kernel/kernel_test.go | 64 +++++++++---------------- test/util/helpers/helpers.go | 34 +++++++++++++ 2 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 test/util/helpers/helpers.go diff --git a/pkg/host/internal/kernel/kernel_test.go b/pkg/host/internal/kernel/kernel_test.go index de6f22cec..b8eef8b07 100644 --- a/pkg/host/internal/kernel/kernel_test.go +++ b/pkg/host/internal/kernel/kernel_test.go @@ -1,38 +1,20 @@ package kernel import ( - "os" - "path/filepath" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/helpers" ) -func assertFileContentsEquals(path, expectedContent string) { - d, err := os.ReadFile(filepath.Join(vars.FilesystemRoot, path)) - ExpectWithOffset(1, err).NotTo(HaveOccurred()) - ExpectWithOffset(1, string(d)).To(Equal(expectedContent)) -} - var _ = Describe("Kernel", func() { Context("Drivers", func() { var ( k types.KernelInterface ) - configureFS := func(f *fakefilesystem.FS) { - var ( - cleanFakeFs func() - err error - ) - vars.FilesystemRoot, cleanFakeFs, err = f.Use() - Expect(err).ToNot(HaveOccurred()) - DeferCleanup(cleanFakeFs) - } BeforeEach(func() { k = New(nil) }) @@ -41,11 +23,11 @@ var _ = Describe("Kernel", func() { Expect(k.UnbindDriverByBusAndDevice(consts.BusPci, "unknown-dev")).NotTo(HaveOccurred()) }) It("known device, no driver", func() { - configureFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) Expect(k.Unbind("0000:d8:00.0")).NotTo(HaveOccurred()) }) It("has driver, succeed", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/test-driver"}, @@ -56,10 +38,10 @@ var _ = Describe("Kernel", func() { }) Expect(k.Unbind("0000:d8:00.0")).NotTo(HaveOccurred()) // check that echo to unbind path was done - assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") }) It("has driver, failed to unbind", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0"}, Symlinks: map[string]string{ @@ -75,13 +57,13 @@ var _ = Describe("Kernel", func() { Expect(driver).To(BeEmpty()) }) It("known device, no driver", func() { - configureFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}}) has, driver := k.HasDriver("0000:d8:00.0") Expect(has).To(BeFalse()) Expect(driver).To(BeEmpty()) }) It("has driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/test-driver"}, @@ -98,7 +80,7 @@ var _ = Describe("Kernel", func() { Expect(k.BindDefaultDriver("unknown-dev")).To(HaveOccurred()) }) It("no driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0"}, Files: map[string][]byte{ @@ -106,10 +88,10 @@ var _ = Describe("Kernel", func() { }) Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) // should probe driver for dev - assertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") }) It("already bind to default driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0"}, Symlinks: map[string]string{ @@ -118,7 +100,7 @@ var _ = Describe("Kernel", func() { Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) }) It("bind to dpdk driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/vfio-pci"}, @@ -130,9 +112,9 @@ var _ = Describe("Kernel", func() { }) Expect(k.BindDefaultDriver("0000:d8:00.0")).NotTo(HaveOccurred()) // should unbind from dpdk driver - assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/unbind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/unbind", "0000:d8:00.0") // should probe driver for dev - assertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers_probe", "0000:d8:00.0") }) }) Context("BindDpdkDriver", func() { @@ -140,7 +122,7 @@ var _ = Describe("Kernel", func() { Expect(k.BindDpdkDriver("unknown-dev", "vfio-pci")).To(HaveOccurred()) }) It("no driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/vfio-pci"}, @@ -149,10 +131,10 @@ var _ = Describe("Kernel", func() { }) Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) // should reset driver override - assertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/driver_override", "\x00") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/driver_override", "\x00") }) It("already bind to required driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0"}, Symlinks: map[string]string{ @@ -161,7 +143,7 @@ var _ = Describe("Kernel", func() { Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) }) It("bind to wrong driver", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/test-driver", @@ -175,12 +157,12 @@ var _ = Describe("Kernel", func() { }) Expect(k.BindDpdkDriver("0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) // should unbind from driver1 - assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") // should bind to driver2 - assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") }) It("fail to bind", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/test-driver"}, @@ -195,7 +177,7 @@ var _ = Describe("Kernel", func() { }) Context("BindDriverByBusAndDevice", func() { It("device doesn't support driver_override", func() { - configureFS(&fakefilesystem.FS{ + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ Dirs: []string{ "/sys/bus/pci/devices/0000:d8:00.0", "/sys/bus/pci/drivers/test-driver", @@ -208,9 +190,9 @@ var _ = Describe("Kernel", func() { }) Expect(k.BindDriverByBusAndDevice(consts.BusPci, "0000:d8:00.0", "vfio-pci")).NotTo(HaveOccurred()) // should unbind from driver1 - assertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/test-driver/unbind", "0000:d8:00.0") // should bind to driver2 - assertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/drivers/vfio-pci/bind", "0000:d8:00.0") }) }) }) diff --git a/test/util/helpers/helpers.go b/test/util/helpers/helpers.go new file mode 100644 index 000000000..35f1bf22f --- /dev/null +++ b/test/util/helpers/helpers.go @@ -0,0 +1,34 @@ +package helpers + +import ( + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" +) + +// GinkgoConfigureFakeFS configure fake filesystem by setting vars.FilesystemRoot +// and register Ginkgo DeferCleanup handler to clean the fs when test completed +func GinkgoConfigureFakeFS(f *fakefilesystem.FS) { + var ( + cleanFakeFs func() + err error + ) + vars.FilesystemRoot, cleanFakeFs, err = f.Use() + Expect(err).ToNot(HaveOccurred()) + DeferCleanup(cleanFakeFs) +} + +// GinkgoAssertFileContentsEquals check that content of the file +// match the expected value. +// prepends vars.FilesystemRoot to the file path to be compatible with +// GinkgoConfigureFakeFS function +func GinkgoAssertFileContentsEquals(path, expectedContent string) { + d, err := os.ReadFile(filepath.Join(vars.FilesystemRoot, path)) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + ExpectWithOffset(1, string(d)).To(Equal(expectedContent)) +} From 4b46a859f630a8f1d58117c5e1e3821ba09f7c66 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Thu, 11 Jan 2024 12:49:24 +0200 Subject: [PATCH 31/61] Add wrapper for govdpa lib Signed-off-by: Yury Kulazhenkov --- go.mod | 2 +- pkg/host/internal/lib/govdpa/govdpa.go | 40 ++++ .../internal/lib/govdpa/mock/mock_govdpa.go | 187 ++++++++++++++++++ 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 pkg/host/internal/lib/govdpa/govdpa.go create mode 100644 pkg/host/internal/lib/govdpa/mock/mock_govdpa.go diff --git a/go.mod b/go.mod index c1aaf85ba..2ca75b2d9 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-retryablehttp v0.7.0 github.com/jaypipes/ghw v0.9.0 + github.com/k8snetworkplumbingwg/govdpa v0.1.4 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 github.com/k8snetworkplumbingwg/sriov-network-device-plugin v0.0.0-20221127172732-a5a7395122e3 github.com/onsi/ginkgo/v2 v2.11.0 @@ -91,7 +92,6 @@ require ( github.com/jaypipes/pcidb v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/k8snetworkplumbingwg/govdpa v0.1.4 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.17 // indirect diff --git a/pkg/host/internal/lib/govdpa/govdpa.go b/pkg/host/internal/lib/govdpa/govdpa.go new file mode 100644 index 000000000..e85f89db1 --- /dev/null +++ b/pkg/host/internal/lib/govdpa/govdpa.go @@ -0,0 +1,40 @@ +package govdpa + +import ( + "github.com/k8snetworkplumbingwg/govdpa/pkg/kvdpa" +) + +func New() GoVdpaLib { + return &libWrapper{} +} + +type VdpaDevice interface { + kvdpa.VdpaDevice +} + +//go:generate ../../../../../bin/mockgen -destination mock/mock_govdpa.go -source govdpa.go +type GoVdpaLib interface { + // GetVdpaDevice returns the vdpa device information by a vdpa device name + GetVdpaDevice(vdpaDeviceName string) (VdpaDevice, error) + // AddVdpaDevice adds a new vdpa device to the given management device + AddVdpaDevice(mgmtDeviceName string, vdpaDeviceName string) error + // DeleteVdpaDevice deletes a vdpa device + DeleteVdpaDevice(vdpaDeviceName string) error +} + +type libWrapper struct{} + +// GetVdpaDevice returns the vdpa device information by a vdpa device name +func (w *libWrapper) GetVdpaDevice(name string) (VdpaDevice, error) { + return kvdpa.GetVdpaDevice(name) +} + +// AddVdpaDevice adds a new vdpa device to the given management device +func (w *libWrapper) AddVdpaDevice(mgmtDeviceName string, vdpaDeviceName string) error { + return kvdpa.AddVdpaDevice(mgmtDeviceName, vdpaDeviceName) +} + +// DeleteVdpaDevice deletes a vdpa device +func (w *libWrapper) DeleteVdpaDevice(name string) error { + return kvdpa.DeleteVdpaDevice(name) +} diff --git a/pkg/host/internal/lib/govdpa/mock/mock_govdpa.go b/pkg/host/internal/lib/govdpa/mock/mock_govdpa.go new file mode 100644 index 000000000..cdeeac743 --- /dev/null +++ b/pkg/host/internal/lib/govdpa/mock/mock_govdpa.go @@ -0,0 +1,187 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: govdpa.go + +// Package mock_govdpa is a generated GoMock package. +package mock_govdpa + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + kvdpa "github.com/k8snetworkplumbingwg/govdpa/pkg/kvdpa" + govdpa "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa" +) + +// MockVdpaDevice is a mock of VdpaDevice interface. +type MockVdpaDevice struct { + ctrl *gomock.Controller + recorder *MockVdpaDeviceMockRecorder +} + +// MockVdpaDeviceMockRecorder is the mock recorder for MockVdpaDevice. +type MockVdpaDeviceMockRecorder struct { + mock *MockVdpaDevice +} + +// NewMockVdpaDevice creates a new mock instance. +func NewMockVdpaDevice(ctrl *gomock.Controller) *MockVdpaDevice { + mock := &MockVdpaDevice{ctrl: ctrl} + mock.recorder = &MockVdpaDeviceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockVdpaDevice) EXPECT() *MockVdpaDeviceMockRecorder { + return m.recorder +} + +// Driver mocks base method. +func (m *MockVdpaDevice) Driver() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Driver") + ret0, _ := ret[0].(string) + return ret0 +} + +// Driver indicates an expected call of Driver. +func (mr *MockVdpaDeviceMockRecorder) Driver() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Driver", reflect.TypeOf((*MockVdpaDevice)(nil).Driver)) +} + +// MgmtDev mocks base method. +func (m *MockVdpaDevice) MgmtDev() kvdpa.MgmtDev { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MgmtDev") + ret0, _ := ret[0].(kvdpa.MgmtDev) + return ret0 +} + +// MgmtDev indicates an expected call of MgmtDev. +func (mr *MockVdpaDeviceMockRecorder) MgmtDev() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MgmtDev", reflect.TypeOf((*MockVdpaDevice)(nil).MgmtDev)) +} + +// Name mocks base method. +func (m *MockVdpaDevice) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockVdpaDeviceMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockVdpaDevice)(nil).Name)) +} + +// ParentDevicePath mocks base method. +func (m *MockVdpaDevice) ParentDevicePath() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParentDevicePath") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParentDevicePath indicates an expected call of ParentDevicePath. +func (mr *MockVdpaDeviceMockRecorder) ParentDevicePath() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParentDevicePath", reflect.TypeOf((*MockVdpaDevice)(nil).ParentDevicePath)) +} + +// VhostVdpa mocks base method. +func (m *MockVdpaDevice) VhostVdpa() kvdpa.VhostVdpa { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "VhostVdpa") + ret0, _ := ret[0].(kvdpa.VhostVdpa) + return ret0 +} + +// VhostVdpa indicates an expected call of VhostVdpa. +func (mr *MockVdpaDeviceMockRecorder) VhostVdpa() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VhostVdpa", reflect.TypeOf((*MockVdpaDevice)(nil).VhostVdpa)) +} + +// VirtioNet mocks base method. +func (m *MockVdpaDevice) VirtioNet() kvdpa.VirtioNet { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "VirtioNet") + ret0, _ := ret[0].(kvdpa.VirtioNet) + return ret0 +} + +// VirtioNet indicates an expected call of VirtioNet. +func (mr *MockVdpaDeviceMockRecorder) VirtioNet() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VirtioNet", reflect.TypeOf((*MockVdpaDevice)(nil).VirtioNet)) +} + +// MockGoVdpaLib is a mock of GoVdpaLib interface. +type MockGoVdpaLib struct { + ctrl *gomock.Controller + recorder *MockGoVdpaLibMockRecorder +} + +// MockGoVdpaLibMockRecorder is the mock recorder for MockGoVdpaLib. +type MockGoVdpaLibMockRecorder struct { + mock *MockGoVdpaLib +} + +// NewMockGoVdpaLib creates a new mock instance. +func NewMockGoVdpaLib(ctrl *gomock.Controller) *MockGoVdpaLib { + mock := &MockGoVdpaLib{ctrl: ctrl} + mock.recorder = &MockGoVdpaLibMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockGoVdpaLib) EXPECT() *MockGoVdpaLibMockRecorder { + return m.recorder +} + +// AddVdpaDevice mocks base method. +func (m *MockGoVdpaLib) AddVdpaDevice(mgmtDeviceName, vdpaDeviceName string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddVdpaDevice", mgmtDeviceName, vdpaDeviceName) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddVdpaDevice indicates an expected call of AddVdpaDevice. +func (mr *MockGoVdpaLibMockRecorder) AddVdpaDevice(mgmtDeviceName, vdpaDeviceName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddVdpaDevice", reflect.TypeOf((*MockGoVdpaLib)(nil).AddVdpaDevice), mgmtDeviceName, vdpaDeviceName) +} + +// DeleteVdpaDevice mocks base method. +func (m *MockGoVdpaLib) DeleteVdpaDevice(vdpaDeviceName string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteVdpaDevice", vdpaDeviceName) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteVdpaDevice indicates an expected call of DeleteVdpaDevice. +func (mr *MockGoVdpaLibMockRecorder) DeleteVdpaDevice(vdpaDeviceName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteVdpaDevice", reflect.TypeOf((*MockGoVdpaLib)(nil).DeleteVdpaDevice), vdpaDeviceName) +} + +// GetVdpaDevice mocks base method. +func (m *MockGoVdpaLib) GetVdpaDevice(vdpaDeviceName string) (govdpa.VdpaDevice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVdpaDevice", vdpaDeviceName) + ret0, _ := ret[0].(govdpa.VdpaDevice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetVdpaDevice indicates an expected call of GetVdpaDevice. +func (mr *MockGoVdpaLibMockRecorder) GetVdpaDevice(vdpaDeviceName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVdpaDevice", reflect.TypeOf((*MockGoVdpaLib)(nil).GetVdpaDevice), vdpaDeviceName) +} From 31b5e516e458f49af19ed2a9db00f9165654772a Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 11:07:08 +0200 Subject: [PATCH 32/61] Add VdpaInterface to host package The interface provides implementation for the following functions: * CreateVDPADevice - creates VDPA device for VF with required type(vhost, virtio) * DeleteVDPADevice - removes VDPA device for provided VF * DiscoverVDPAType - return type of existing VDPA device for VF Signed-off-by: Yury Kulazhenkov --- pkg/helper/mock/mock_helper.go | 42 +++++++++ pkg/host/internal/vdpa/suite_test.go | 21 +++++ pkg/host/internal/vdpa/vdpa.go | 131 +++++++++++++++++++++++++++ pkg/host/internal/vdpa/vdpa_test.go | 115 +++++++++++++++++++++++ pkg/host/manager.go | 6 ++ pkg/host/mock/mock_host.go | 42 +++++++++ pkg/host/types/interfaces.go | 10 ++ 7 files changed, 367 insertions(+) create mode 100644 pkg/host/internal/vdpa/suite_test.go create mode 100644 pkg/host/internal/vdpa/vdpa.go create mode 100644 pkg/host/internal/vdpa/vdpa_test.go diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index b96b0d4de..db270364d 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -182,6 +182,34 @@ func (mr *MockHostHelpersInterfaceMockRecorder) ConfigSriovInterfaces(storeManag return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostHelpersInterface)(nil).ConfigSriovInterfaces), storeManager, interfaces, ifaceStatuses, pfsToConfig) } +// CreateVDPADevice mocks base method. +func (m *MockHostHelpersInterface) CreateVDPADevice(pciAddr, vdpaType string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateVDPADevice", pciAddr, vdpaType) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateVDPADevice indicates an expected call of CreateVDPADevice. +func (mr *MockHostHelpersInterfaceMockRecorder) CreateVDPADevice(pciAddr, vdpaType interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVDPADevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).CreateVDPADevice), pciAddr, vdpaType) +} + +// DeleteVDPADevice mocks base method. +func (m *MockHostHelpersInterface) DeleteVDPADevice(pciAddr string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteVDPADevice", pciAddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteVDPADevice indicates an expected call of DeleteVDPADevice. +func (mr *MockHostHelpersInterfaceMockRecorder) DeleteVDPADevice(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteVDPADevice", reflect.TypeOf((*MockHostHelpersInterface)(nil).DeleteVDPADevice), pciAddr) +} + // DiscoverSriovDevices mocks base method. func (m *MockHostHelpersInterface) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]v1.InterfaceExt, error) { m.ctrl.T.Helper() @@ -197,6 +225,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) DiscoverSriovDevices(storeManage return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostHelpersInterface)(nil).DiscoverSriovDevices), storeManager) } +// DiscoverVDPAType mocks base method. +func (m *MockHostHelpersInterface) DiscoverVDPAType(pciAddr string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverVDPAType", pciAddr) + ret0, _ := ret[0].(string) + return ret0 +} + +// DiscoverVDPAType indicates an expected call of DiscoverVDPAType. +func (mr *MockHostHelpersInterfaceMockRecorder) DiscoverVDPAType(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverVDPAType", reflect.TypeOf((*MockHostHelpersInterface)(nil).DiscoverVDPAType), pciAddr) +} + // EnableRDMA mocks base method. func (m *MockHostHelpersInterface) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { m.ctrl.T.Helper() diff --git a/pkg/host/internal/vdpa/suite_test.go b/pkg/host/internal/vdpa/suite_test.go new file mode 100644 index 000000000..5863f7f27 --- /dev/null +++ b/pkg/host/internal/vdpa/suite_test.go @@ -0,0 +1,21 @@ +package vdpa + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "go.uber.org/zap/zapcore" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func TestVdpa(t *testing.T) { + log.SetLogger(zap.New( + zap.WriteTo(GinkgoWriter), + zap.Level(zapcore.Level(-2)), + zap.UseDevMode(true))) + RegisterFailHandler(Fail) + RunSpecs(t, "Package VDPA Suite") +} diff --git a/pkg/host/internal/vdpa/vdpa.go b/pkg/host/internal/vdpa/vdpa.go new file mode 100644 index 000000000..010098f8b --- /dev/null +++ b/pkg/host/internal/vdpa/vdpa.go @@ -0,0 +1,131 @@ +package vdpa + +import ( + "errors" + "fmt" + "syscall" + + "github.com/k8snetworkplumbingwg/govdpa/pkg/kvdpa" + "sigs.k8s.io/controller-runtime/pkg/log" + + constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" +) + +type vdpa struct { + kernel types.KernelInterface + vdpaLib govdpa.GoVdpaLib +} + +func New(k types.KernelInterface, vdpaLib govdpa.GoVdpaLib) types.VdpaInterface { + return &vdpa{kernel: k, vdpaLib: vdpaLib} +} + +// CreateVDPADevice creates VDPA device for VF with required type, +// pciAddr - PCI address of the VF +// vdpaType - type of the VDPA device to create: virtio of vhost +func (v *vdpa) CreateVDPADevice(pciAddr, vdpaType string) error { + log.Log.V(2).Info("CreateVDPADevice(): create VDPA device for VF", + "device", pciAddr, "vdpaType", vdpaType) + expectedDriver := vdpaTypeToDriver(vdpaType) + if expectedDriver == "" { + return fmt.Errorf("unknown VDPA device type: %s", vdpaType) + } + expectedVDPAName := generateVDPADevName(pciAddr) + _, err := v.vdpaLib.GetVdpaDevice(expectedVDPAName) + if err != nil { + if !errors.Is(err, syscall.ENODEV) { + log.Log.Error(err, "CreateVDPADevice(): fail to check if VDPA device exist", + "device", pciAddr, "vdpaDev", expectedVDPAName) + return err + } + if err := v.vdpaLib.AddVdpaDevice("pci/"+pciAddr, expectedVDPAName); err != nil { + log.Log.Error(err, "CreateVDPADevice(): fail to create VDPA device", + "device", pciAddr, "vdpaDev", expectedVDPAName) + return err + } + } + err = v.kernel.BindDriverByBusAndDevice(constants.BusVdpa, expectedVDPAName, expectedDriver) + if err != nil { + log.Log.Error(err, "CreateVDPADevice(): fail to bind VDPA device to the driver", + "device", pciAddr, "vdpaDev", expectedVDPAName, "driver", expectedDriver) + return err + } + return nil +} + +// DeleteVDPADevice removes VDPA device for provided pci address +// pciAddr - PCI address of the VF +func (v *vdpa) DeleteVDPADevice(pciAddr string) error { + log.Log.V(2).Info("DeleteVDPADevice(): delete VDPA device for VF", + "device", pciAddr) + expectedVDPAName := generateVDPADevName(pciAddr) + if err := v.vdpaLib.DeleteVdpaDevice(expectedVDPAName); err != nil { + if errors.Is(err, syscall.ENODEV) { + log.Log.V(2).Info("DeleteVDPADevice(): VDPA device not found", + "device", pciAddr, "name", expectedVDPAName) + return nil + } + log.Log.Error(err, "DeleteVDPADevice(): fail to remove VDPA device", + "device", pciAddr, "name", expectedVDPAName) + return err + } + return nil +} + +// DiscoverVDPAType returns type of existing VDPA device for VF, +// returns empty string if VDPA device not found or unknown driver is in use +// pciAddr - PCI address of the VF +func (v *vdpa) DiscoverVDPAType(pciAddr string) string { + expectedVDPADevName := generateVDPADevName(pciAddr) + vdpaDev, err := v.vdpaLib.GetVdpaDevice(expectedVDPADevName) + if err != nil { + if errors.Is(err, syscall.ENODEV) { + log.Log.V(2).Info("discoverVDPAType(): VDPA device for VF not found", "device", pciAddr) + return "" + } + log.Log.Error(err, "getVfInfo(): unable to get VF VDPA devices", "device", pciAddr) + return "" + } + driverName := vdpaDev.Driver() + if driverName == "" { + log.Log.V(2).Info("discoverVDPAType(): VDPA device has no driver", "device", pciAddr) + return "" + } + vdpaType := vdpaDriverToType(driverName) + if vdpaType == "" { + log.Log.Error(nil, "getVfInfo(): WARNING: unknown VDPA device type for VF, ignore", + "device", pciAddr, "driver", driverName) + } + return vdpaType +} + +// generates predictable name for VDPA device, example: vpda:0000:03:00.1 +func generateVDPADevName(pciAddr string) string { + return "vdpa:" + pciAddr +} + +// vdpa type to driver name conversion +func vdpaTypeToDriver(vdpaType string) string { + switch vdpaType { + case constants.VdpaTypeVhost: + return kvdpa.VhostVdpaDriver + case constants.VdpaTypeVirtio: + return kvdpa.VirtioVdpaDriver + default: + return "" + } +} + +// vdpa driver name to type conversion +func vdpaDriverToType(driver string) string { + switch driver { + case kvdpa.VhostVdpaDriver: + return constants.VdpaTypeVhost + case kvdpa.VirtioVdpaDriver: + return constants.VdpaTypeVirtio + default: + return "" + } +} diff --git a/pkg/host/internal/vdpa/vdpa_test.go b/pkg/host/internal/vdpa/vdpa_test.go new file mode 100644 index 000000000..3c668aa44 --- /dev/null +++ b/pkg/host/internal/vdpa/vdpa_test.go @@ -0,0 +1,115 @@ +package vdpa + +import ( + "fmt" + "syscall" + + "github.com/golang/mock/gomock" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + govdpaMock "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa/mock" + hostMock "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/mock" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" +) + +var _ = Describe("VDPA", func() { + var ( + v types.VdpaInterface + libMock *govdpaMock.MockGoVdpaLib + vdpaDevMock *govdpaMock.MockVdpaDevice + kernelMock *hostMock.MockHostManagerInterface + + testCtrl *gomock.Controller + testErr = fmt.Errorf("test-error") + ) + BeforeEach(func() { + testCtrl = gomock.NewController(GinkgoT()) + libMock = govdpaMock.NewMockGoVdpaLib(testCtrl) + vdpaDevMock = govdpaMock.NewMockVdpaDevice(testCtrl) + kernelMock = hostMock.NewMockHostManagerInterface(testCtrl) + v = New(kernelMock, libMock) + }) + AfterEach(func() { + testCtrl.Finish() + }) + Context("CreateVDPADevice", func() { + callFunc := func() error { + return v.CreateVDPADevice("0000:d8:00.2", constants.VdpaTypeVhost) + } + It("Created", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(nil, syscall.ENODEV) + libMock.EXPECT().AddVdpaDevice("pci/"+"0000:d8:00.2", "vdpa:0000:d8:00.2").Return(nil) + kernelMock.EXPECT().BindDriverByBusAndDevice(consts.BusVdpa, "vdpa:0000:d8:00.2", "vhost_vdpa").Return(nil) + Expect(callFunc()).NotTo(HaveOccurred()) + }) + It("Already exist", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + kernelMock.EXPECT().BindDriverByBusAndDevice(consts.BusVdpa, "vdpa:0000:d8:00.2", "vhost_vdpa").Return(nil) + Expect(callFunc()).NotTo(HaveOccurred()) + }) + It("Fail to Get device", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(nil, testErr) + Expect(callFunc()).To(MatchError(testErr)) + }) + It("Fail to Create device", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(nil, syscall.ENODEV) + libMock.EXPECT().AddVdpaDevice("pci/"+"0000:d8:00.2", "vdpa:0000:d8:00.2").Return(testErr) + Expect(callFunc()).To(MatchError(testErr)) + }) + It("Fail to Bind device", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + kernelMock.EXPECT().BindDriverByBusAndDevice(consts.BusVdpa, "vdpa:0000:d8:00.2", "vhost_vdpa").Return(testErr) + Expect(callFunc()).To(MatchError(testErr)) + }) + }) + Context("DeleteVDPADevice", func() { + callFunc := func() error { + return v.DeleteVDPADevice("0000:d8:00.2") + } + It("Removed", func() { + libMock.EXPECT().DeleteVdpaDevice("vdpa:0000:d8:00.2").Return(nil) + Expect(callFunc()).NotTo(HaveOccurred()) + }) + It("Not found", func() { + libMock.EXPECT().DeleteVdpaDevice("vdpa:0000:d8:00.2").Return(syscall.ENODEV) + Expect(callFunc()).NotTo(HaveOccurred()) + }) + It("Fail to delete device", func() { + libMock.EXPECT().DeleteVdpaDevice("vdpa:0000:d8:00.2").Return(testErr) + Expect(callFunc()).To(MatchError(testErr)) + }) + }) + Context("DiscoverVDPAType", func() { + callFunc := func() string { + return v.DiscoverVDPAType("0000:d8:00.2") + } + It("No device", func() { + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(nil, syscall.ENODEV) + Expect(callFunc()).To(BeEmpty()) + }) + It("No driver", func() { + vdpaDevMock.EXPECT().Driver().Return("") + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + Expect(callFunc()).To(BeEmpty()) + }) + It("Unknown driver", func() { + vdpaDevMock.EXPECT().Driver().Return("something") + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + Expect(callFunc()).To(BeEmpty()) + }) + It("Vhost driver", func() { + vdpaDevMock.EXPECT().Driver().Return("vhost_vdpa") + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + Expect(callFunc()).To(Equal("vhost")) + }) + It("Virtio driver", func() { + vdpaDevMock.EXPECT().Driver().Return("virtio_vdpa") + libMock.EXPECT().GetVdpaDevice("vdpa:0000:d8:00.2").Return(vdpaDevMock, nil) + Expect(callFunc()).To(Equal("virtio")) + }) + }) +}) diff --git a/pkg/host/manager.go b/pkg/host/manager.go index 3983fa9b6..3593dbaee 100644 --- a/pkg/host/manager.go +++ b/pkg/host/manager.go @@ -2,10 +2,12 @@ package host import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/kernel" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/network" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/service" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/sriov" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/udev" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/vdpa" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" ) @@ -19,6 +21,7 @@ type HostManagerInterface interface { types.ServiceInterface types.UdevInterface types.SriovInterface + types.VdpaInterface } type hostManager struct { @@ -28,6 +31,7 @@ type hostManager struct { types.ServiceInterface types.UdevInterface types.SriovInterface + types.VdpaInterface } func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { @@ -36,6 +40,7 @@ func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { sv := service.New(utilsInterface) u := udev.New(utilsInterface) sr := sriov.New(utilsInterface, k, n, u) + v := vdpa.New(k, govdpa.New()) return &hostManager{ utilsInterface, @@ -44,5 +49,6 @@ func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { sv, u, sr, + v, } } diff --git a/pkg/host/mock/mock_host.go b/pkg/host/mock/mock_host.go index 7c52fd28b..29d2c87ec 100644 --- a/pkg/host/mock/mock_host.go +++ b/pkg/host/mock/mock_host.go @@ -152,6 +152,34 @@ func (mr *MockHostManagerInterfaceMockRecorder) ConfigSriovInterfaces(storeManag return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigSriovInterfaces", reflect.TypeOf((*MockHostManagerInterface)(nil).ConfigSriovInterfaces), storeManager, interfaces, ifaceStatuses, pfsToConfig) } +// CreateVDPADevice mocks base method. +func (m *MockHostManagerInterface) CreateVDPADevice(pciAddr, vdpaType string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateVDPADevice", pciAddr, vdpaType) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateVDPADevice indicates an expected call of CreateVDPADevice. +func (mr *MockHostManagerInterfaceMockRecorder) CreateVDPADevice(pciAddr, vdpaType interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVDPADevice", reflect.TypeOf((*MockHostManagerInterface)(nil).CreateVDPADevice), pciAddr, vdpaType) +} + +// DeleteVDPADevice mocks base method. +func (m *MockHostManagerInterface) DeleteVDPADevice(pciAddr string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteVDPADevice", pciAddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteVDPADevice indicates an expected call of DeleteVDPADevice. +func (mr *MockHostManagerInterfaceMockRecorder) DeleteVDPADevice(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteVDPADevice", reflect.TypeOf((*MockHostManagerInterface)(nil).DeleteVDPADevice), pciAddr) +} + // DiscoverSriovDevices mocks base method. func (m *MockHostManagerInterface) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]v1.InterfaceExt, error) { m.ctrl.T.Helper() @@ -167,6 +195,20 @@ func (mr *MockHostManagerInterfaceMockRecorder) DiscoverSriovDevices(storeManage return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverSriovDevices", reflect.TypeOf((*MockHostManagerInterface)(nil).DiscoverSriovDevices), storeManager) } +// DiscoverVDPAType mocks base method. +func (m *MockHostManagerInterface) DiscoverVDPAType(pciAddr string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DiscoverVDPAType", pciAddr) + ret0, _ := ret[0].(string) + return ret0 +} + +// DiscoverVDPAType indicates an expected call of DiscoverVDPAType. +func (mr *MockHostManagerInterfaceMockRecorder) DiscoverVDPAType(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DiscoverVDPAType", reflect.TypeOf((*MockHostManagerInterface)(nil).DiscoverVDPAType), pciAddr) +} + // EnableRDMA mocks base method. func (m *MockHostManagerInterface) EnableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) { m.ctrl.T.Helper() diff --git a/pkg/host/types/interfaces.go b/pkg/host/types/interfaces.go index d1613cd44..e13f8ee66 100644 --- a/pkg/host/types/interfaces.go +++ b/pkg/host/types/interfaces.go @@ -159,3 +159,13 @@ type UdevInterface interface { // RemoveUdevRule removes a udev rule from the system RemoveUdevRule(pfPciAddress string) error } + +type VdpaInterface interface { + // CreateVDPADevice creates VDPA device for VF with required type + CreateVDPADevice(pciAddr, vdpaType string) error + // DeleteVDPADevice removes VDPA device for provided pci address + DeleteVDPADevice(pciAddr string) error + // DiscoverVDPAType returns type of existing VDPA device for VF, + // returns empty string if VDPA device not found or unknown driver is in use + DiscoverVDPAType(pciAddr string) string +} From 37cb2db40fc03a81439e546fa6196be3b0d278e4 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 11:13:36 +0200 Subject: [PATCH 33/61] Add wrapper for netlink library to host pkg Signed-off-by: Yury Kulazhenkov --- .../internal/lib/netlink/mock/mock_netlink.go | 188 ++++++++++++++++++ pkg/host/internal/lib/netlink/netlink.go | 86 ++++++++ 2 files changed, 274 insertions(+) create mode 100644 pkg/host/internal/lib/netlink/mock/mock_netlink.go create mode 100644 pkg/host/internal/lib/netlink/netlink.go diff --git a/pkg/host/internal/lib/netlink/mock/mock_netlink.go b/pkg/host/internal/lib/netlink/mock/mock_netlink.go new file mode 100644 index 000000000..072ba8980 --- /dev/null +++ b/pkg/host/internal/lib/netlink/mock/mock_netlink.go @@ -0,0 +1,188 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: netlink.go + +// Package mock_netlink is a generated GoMock package. +package mock_netlink + +import ( + net "net" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + netlink "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink" + netlink0 "github.com/vishvananda/netlink" +) + +// MockLink is a mock of Link interface. +type MockLink struct { + ctrl *gomock.Controller + recorder *MockLinkMockRecorder +} + +// MockLinkMockRecorder is the mock recorder for MockLink. +type MockLinkMockRecorder struct { + mock *MockLink +} + +// NewMockLink creates a new mock instance. +func NewMockLink(ctrl *gomock.Controller) *MockLink { + mock := &MockLink{ctrl: ctrl} + mock.recorder = &MockLinkMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLink) EXPECT() *MockLinkMockRecorder { + return m.recorder +} + +// Attrs mocks base method. +func (m *MockLink) Attrs() *netlink0.LinkAttrs { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Attrs") + ret0, _ := ret[0].(*netlink0.LinkAttrs) + return ret0 +} + +// Attrs indicates an expected call of Attrs. +func (mr *MockLinkMockRecorder) Attrs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Attrs", reflect.TypeOf((*MockLink)(nil).Attrs)) +} + +// Type mocks base method. +func (m *MockLink) Type() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Type") + ret0, _ := ret[0].(string) + return ret0 +} + +// Type indicates an expected call of Type. +func (mr *MockLinkMockRecorder) Type() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Type", reflect.TypeOf((*MockLink)(nil).Type)) +} + +// MockNetlinkLib is a mock of NetlinkLib interface. +type MockNetlinkLib struct { + ctrl *gomock.Controller + recorder *MockNetlinkLibMockRecorder +} + +// MockNetlinkLibMockRecorder is the mock recorder for MockNetlinkLib. +type MockNetlinkLibMockRecorder struct { + mock *MockNetlinkLib +} + +// NewMockNetlinkLib creates a new mock instance. +func NewMockNetlinkLib(ctrl *gomock.Controller) *MockNetlinkLib { + mock := &MockNetlinkLib{ctrl: ctrl} + mock.recorder = &MockNetlinkLibMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockNetlinkLib) EXPECT() *MockNetlinkLibMockRecorder { + return m.recorder +} + +// DevLinkGetDeviceByName mocks base method. +func (m *MockNetlinkLib) DevLinkGetDeviceByName(bus, device string) (*netlink0.DevlinkDevice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DevLinkGetDeviceByName", bus, device) + ret0, _ := ret[0].(*netlink0.DevlinkDevice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DevLinkGetDeviceByName indicates an expected call of DevLinkGetDeviceByName. +func (mr *MockNetlinkLibMockRecorder) DevLinkGetDeviceByName(bus, device interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DevLinkGetDeviceByName", reflect.TypeOf((*MockNetlinkLib)(nil).DevLinkGetDeviceByName), bus, device) +} + +// DevLinkSetEswitchMode mocks base method. +func (m *MockNetlinkLib) DevLinkSetEswitchMode(dev *netlink0.DevlinkDevice, newMode string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DevLinkSetEswitchMode", dev, newMode) + ret0, _ := ret[0].(error) + return ret0 +} + +// DevLinkSetEswitchMode indicates an expected call of DevLinkSetEswitchMode. +func (mr *MockNetlinkLibMockRecorder) DevLinkSetEswitchMode(dev, newMode interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DevLinkSetEswitchMode", reflect.TypeOf((*MockNetlinkLib)(nil).DevLinkSetEswitchMode), dev, newMode) +} + +// LinkByName mocks base method. +func (m *MockNetlinkLib) LinkByName(name string) (netlink.Link, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LinkByName", name) + ret0, _ := ret[0].(netlink.Link) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// LinkByName indicates an expected call of LinkByName. +func (mr *MockNetlinkLibMockRecorder) LinkByName(name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkByName", reflect.TypeOf((*MockNetlinkLib)(nil).LinkByName), name) +} + +// LinkSetUp mocks base method. +func (m *MockNetlinkLib) LinkSetUp(link netlink.Link) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LinkSetUp", link) + ret0, _ := ret[0].(error) + return ret0 +} + +// LinkSetUp indicates an expected call of LinkSetUp. +func (mr *MockNetlinkLibMockRecorder) LinkSetUp(link interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetUp", reflect.TypeOf((*MockNetlinkLib)(nil).LinkSetUp), link) +} + +// LinkSetVfHardwareAddr mocks base method. +func (m *MockNetlinkLib) LinkSetVfHardwareAddr(link netlink.Link, vf int, hwaddr net.HardwareAddr) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LinkSetVfHardwareAddr", link, vf, hwaddr) + ret0, _ := ret[0].(error) + return ret0 +} + +// LinkSetVfHardwareAddr indicates an expected call of LinkSetVfHardwareAddr. +func (mr *MockNetlinkLibMockRecorder) LinkSetVfHardwareAddr(link, vf, hwaddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetVfHardwareAddr", reflect.TypeOf((*MockNetlinkLib)(nil).LinkSetVfHardwareAddr), link, vf, hwaddr) +} + +// LinkSetVfNodeGUID mocks base method. +func (m *MockNetlinkLib) LinkSetVfNodeGUID(link netlink.Link, vf int, nodeguid net.HardwareAddr) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LinkSetVfNodeGUID", link, vf, nodeguid) + ret0, _ := ret[0].(error) + return ret0 +} + +// LinkSetVfNodeGUID indicates an expected call of LinkSetVfNodeGUID. +func (mr *MockNetlinkLibMockRecorder) LinkSetVfNodeGUID(link, vf, nodeguid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetVfNodeGUID", reflect.TypeOf((*MockNetlinkLib)(nil).LinkSetVfNodeGUID), link, vf, nodeguid) +} + +// LinkSetVfPortGUID mocks base method. +func (m *MockNetlinkLib) LinkSetVfPortGUID(link netlink.Link, vf int, portguid net.HardwareAddr) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LinkSetVfPortGUID", link, vf, portguid) + ret0, _ := ret[0].(error) + return ret0 +} + +// LinkSetVfPortGUID indicates an expected call of LinkSetVfPortGUID. +func (mr *MockNetlinkLibMockRecorder) LinkSetVfPortGUID(link, vf, portguid interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetVfPortGUID", reflect.TypeOf((*MockNetlinkLib)(nil).LinkSetVfPortGUID), link, vf, portguid) +} diff --git a/pkg/host/internal/lib/netlink/netlink.go b/pkg/host/internal/lib/netlink/netlink.go new file mode 100644 index 000000000..4871abe95 --- /dev/null +++ b/pkg/host/internal/lib/netlink/netlink.go @@ -0,0 +1,86 @@ +package netlink + +import ( + "net" + + "github.com/vishvananda/netlink" +) + +func New() NetlinkLib { + return &libWrapper{} +} + +type Link interface { + netlink.Link +} + +//go:generate ../../../../../bin/mockgen -destination mock/mock_netlink.go -source netlink.go +type NetlinkLib interface { + // LinkSetVfNodeGUID sets the node GUID of a vf for the link. + // Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid` + LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error + // LinkSetVfPortGUID sets the port GUID of a vf for the link. + // Equivalent to: `ip link set dev $link vf $vf port_guid $portguid` + LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error + // LinkByName finds a link by name and returns a pointer to the object. + LinkByName(name string) (Link, error) + // LinkSetVfHardwareAddr sets the hardware address of a vf for the link. + // Equivalent to: `ip link set $link vf $vf mac $hwaddr` + LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error + // LinkSetUp enables the link device. + // Equivalent to: `ip link set $link up` + LinkSetUp(link Link) error + // DevlinkGetDeviceByName provides a pointer to devlink device and nil error, + // otherwise returns an error code. + DevLinkGetDeviceByName(bus string, device string) (*netlink.DevlinkDevice, error) + // DevLinkSetEswitchMode sets eswitch mode if able to set successfully or + // returns an error code. + // Equivalent to: `devlink dev eswitch set $dev mode switchdev` + // Equivalent to: `devlink dev eswitch set $dev mode legacy` + DevLinkSetEswitchMode(dev *netlink.DevlinkDevice, newMode string) error +} + +type libWrapper struct{} + +// LinkSetVfNodeGUID sets the node GUID of a vf for the link. +// Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid` +func (w *libWrapper) LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error { + return netlink.LinkSetVfNodeGUID(link, vf, nodeguid) +} + +// LinkSetVfPortGUID sets the port GUID of a vf for the link. +// Equivalent to: `ip link set dev $link vf $vf port_guid $portguid` +func (w *libWrapper) LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error { + return netlink.LinkSetVfPortGUID(link, vf, portguid) +} + +// LinkByName finds a link by name and returns a pointer to the object.// LinkByName finds a link by name and returns a pointer to the object. +func (w *libWrapper) LinkByName(name string) (Link, error) { + return netlink.LinkByName(name) +} + +// LinkSetVfHardwareAddr sets the hardware address of a vf for the link. +// Equivalent to: `ip link set $link vf $vf mac $hwaddr` +func (w *libWrapper) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error { + return netlink.LinkSetVfHardwareAddr(link, vf, hwaddr) +} + +// LinkSetUp enables the link device. +// Equivalent to: `ip link set $link up` +func (w *libWrapper) LinkSetUp(link Link) error { + return netlink.LinkSetUp(link) +} + +// DevlinkGetDeviceByName provides a pointer to devlink device and nil error, +// otherwise returns an error code. +func (w *libWrapper) DevLinkGetDeviceByName(bus string, device string) (*netlink.DevlinkDevice, error) { + return netlink.DevLinkGetDeviceByName(bus, device) +} + +// DevLinkSetEswitchMode sets eswitch mode if able to set successfully or +// returns an error code. +// Equivalent to: `devlink dev eswitch set $dev mode switchdev` +// Equivalent to: `devlink dev eswitch set $dev mode legacy` +func (w *libWrapper) DevLinkSetEswitchMode(dev *netlink.DevlinkDevice, newMode string) error { + return netlink.DevLinkSetEswitchMode(dev, newMode) +} From 21a2ad3fdb429d644026cb8debe5d66c2a271771 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 11:19:03 +0200 Subject: [PATCH 34/61] Use netlink lib wrapper in implementation of host.SriovInterface Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/sriov/sriov.go | 30 +++++++++++++++++++----------- pkg/host/manager.go | 3 ++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/pkg/host/internal/sriov/sriov.go b/pkg/host/internal/sriov/sriov.go index 3baf6cbec..24db7917a 100644 --- a/pkg/host/internal/sriov/sriov.go +++ b/pkg/host/internal/sriov/sriov.go @@ -19,6 +19,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + netlinkPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" @@ -31,13 +32,20 @@ type sriov struct { kernelHelper types.KernelInterface networkHelper types.NetworkInterface udevHelper types.UdevInterface + netlinkLib netlinkPkg.NetlinkLib } func New(utilsHelper utils.CmdInterface, kernelHelper types.KernelInterface, networkHelper types.NetworkInterface, - udevHelper types.UdevInterface) types.SriovInterface { - return &sriov{utilsHelper: utilsHelper, kernelHelper: kernelHelper, networkHelper: networkHelper, udevHelper: udevHelper} + udevHelper types.UdevInterface, + netlinkLib netlinkPkg.NetlinkLib) types.SriovInterface { + return &sriov{utilsHelper: utilsHelper, + kernelHelper: kernelHelper, + networkHelper: networkHelper, + udevHelper: udevHelper, + netlinkLib: netlinkLib, + } } func (s *sriov) SetSriovNumVfs(pciAddr string, numVfs int) error { @@ -124,10 +132,10 @@ func (s *sriov) SetVfGUID(vfAddr string, pfLink netlink.Link) error { return err } guid := utils.GenerateRandomGUID() - if err := netlink.LinkSetVfNodeGUID(pfLink, vfID, guid); err != nil { + if err := s.netlinkLib.LinkSetVfNodeGUID(pfLink, vfID, guid); err != nil { return err } - if err := netlink.LinkSetVfPortGUID(pfLink, vfID, guid); err != nil { + if err := s.netlinkLib.LinkSetVfPortGUID(pfLink, vfID, guid); err != nil { return err } if err = s.kernelHelper.Unbind(vfAddr); err != nil { @@ -143,7 +151,7 @@ func (s *sriov) VFIsReady(pciAddr string) (netlink.Link, error) { var vfLink netlink.Link err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { vfName := s.networkHelper.TryGetInterfaceName(pciAddr) - vfLink, err = netlink.LinkByName(vfName) + vfLink, err = s.netlinkLib.LinkByName(vfName) if err != nil { log.Log.Error(err, "VFIsReady(): unable to get VF link", "device", pciAddr) } @@ -164,7 +172,7 @@ func (s *sriov) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error return err } - if err := netlink.LinkSetVfHardwareAddr(pfLink, vfID, vfLink.Attrs().HardwareAddr); err != nil { + if err := s.netlinkLib.LinkSetVfHardwareAddr(pfLink, vfID, vfLink.Attrs().HardwareAddr); err != nil { return err } @@ -333,7 +341,7 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * if err != nil { log.Log.Error(err, "configSriovDevice(): unable to parse VFs for device", "device", iface.PciAddress) } - pfLink, err := netlink.LinkByName(iface.Name) + pfLink, err := s.netlinkLib.LinkByName(iface.Name) if err != nil { log.Log.Error(err, "configSriovDevice(): unable to get PF link for device", "device", iface) return err @@ -424,12 +432,12 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * } } // Set PF link up - pfLink, err := netlink.LinkByName(ifaceStatus.Name) + pfLink, err := s.netlinkLib.LinkByName(ifaceStatus.Name) if err != nil { return err } if pfLink.Attrs().OperState != netlink.OperUp { - err = netlink.LinkSetUp(pfLink) + err = s.netlinkLib.LinkSetUp(pfLink) if err != nil { return err } @@ -576,7 +584,7 @@ func (s *sriov) ConfigSriovDeviceVirtual(iface *sriovnetworkv1.Interface) error func (s *sriov) GetNicSriovMode(pciAddress string) (string, error) { log.Log.V(2).Info("GetNicSriovMode()", "device", pciAddress) - devLink, err := netlink.DevLinkGetDeviceByName("pci", pciAddress) + devLink, err := s.netlinkLib.DevLinkGetDeviceByName("pci", pciAddress) if err != nil { if errors.Is(err, syscall.ENODEV) { // the device doesn't support devlink @@ -591,7 +599,7 @@ func (s *sriov) GetNicSriovMode(pciAddress string) (string, error) { func (s *sriov) GetLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string { log.Log.V(2).Info("GetLinkType()", "device", ifaceStatus.PciAddress) if ifaceStatus.Name != "" { - link, err := netlink.LinkByName(ifaceStatus.Name) + link, err := s.netlinkLib.LinkByName(ifaceStatus.Name) if err != nil { log.Log.Error(err, "GetLinkType(): failed to get link", "device", ifaceStatus.Name) return "" diff --git a/pkg/host/manager.go b/pkg/host/manager.go index 3593dbaee..f883ffe06 100644 --- a/pkg/host/manager.go +++ b/pkg/host/manager.go @@ -3,6 +3,7 @@ package host import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/kernel" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/network" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/service" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/sriov" @@ -39,7 +40,7 @@ func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { n := network.New(utilsInterface) sv := service.New(utilsInterface) u := udev.New(utilsInterface) - sr := sriov.New(utilsInterface, k, n, u) + sr := sriov.New(utilsInterface, k, n, u, netlink.New()) v := vdpa.New(k, govdpa.New()) return &hostManager{ From 0c79197deac5594ddc0a7db5a938478c5ca3df17 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 11:25:47 +0200 Subject: [PATCH 35/61] Optimize SetSriovNumVfs for use-case when we need to ser numVfs to 0 Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/sriov/sriov.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/host/internal/sriov/sriov.go b/pkg/host/internal/sriov/sriov.go index 24db7917a..8b4189ed0 100644 --- a/pkg/host/internal/sriov/sriov.go +++ b/pkg/host/internal/sriov/sriov.go @@ -57,6 +57,9 @@ func (s *sriov) SetSriovNumVfs(pciAddr string, numVfs int) error { log.Log.Error(err, "SetSriovNumVfs(): fail to reset NumVfs file", "path", numVfsFilePath) return err } + if numVfs == 0 { + return nil + } err = os.WriteFile(numVfsFilePath, bs, os.ModeAppend) if err != nil { log.Log.Error(err, "SetSriovNumVfs(): fail to set NumVfs file", "path", numVfsFilePath) From 5410c123dabf394945a5fa586fdfa978c1d0a80c Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 11:31:00 +0200 Subject: [PATCH 36/61] Add sriov.SetNicSriovMode function The function set required eSwitch mode for the NIC. Signed-off-by: Yury Kulazhenkov --- pkg/helper/mock/mock_helper.go | 14 ++++++++++++++ pkg/host/internal/sriov/sriov.go | 10 ++++++++++ pkg/host/mock/mock_host.go | 14 ++++++++++++++ pkg/host/types/interfaces.go | 3 +++ 4 files changed, 41 insertions(+) diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index db270364d..b77f46720 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -914,6 +914,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) SetNetdevMTU(pciAddr, mtu interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetNetdevMTU), pciAddr, mtu) } +// SetNicSriovMode mocks base method. +func (m *MockHostHelpersInterface) SetNicSriovMode(pciAddr, mode string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetNicSriovMode", pciAddr, mode) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetNicSriovMode indicates an expected call of SetNicSriovMode. +func (mr *MockHostHelpersInterfaceMockRecorder) SetNicSriovMode(pciAddr, mode interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNicSriovMode", reflect.TypeOf((*MockHostHelpersInterface)(nil).SetNicSriovMode), pciAddr, mode) +} + // SetSriovNumVfs mocks base method. func (m *MockHostHelpersInterface) SetSriovNumVfs(pciAddr string, numVfs int) error { m.ctrl.T.Helper() diff --git a/pkg/host/internal/sriov/sriov.go b/pkg/host/internal/sriov/sriov.go index 8b4189ed0..9541c8bcd 100644 --- a/pkg/host/internal/sriov/sriov.go +++ b/pkg/host/internal/sriov/sriov.go @@ -599,6 +599,16 @@ func (s *sriov) GetNicSriovMode(pciAddress string) (string, error) { return devLink.Attrs.Eswitch.Mode, nil } +func (s *sriov) SetNicSriovMode(pciAddress string, mode string) error { + log.Log.V(2).Info("SetNicSriovMode()", "device", pciAddress, "mode", mode) + + dev, err := s.netlinkLib.DevLinkGetDeviceByName("pci", pciAddress) + if err != nil { + return err + } + return s.netlinkLib.DevLinkSetEswitchMode(dev, mode) +} + func (s *sriov) GetLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string { log.Log.V(2).Info("GetLinkType()", "device", ifaceStatus.PciAddress) if ifaceStatus.Name != "" { diff --git a/pkg/host/mock/mock_host.go b/pkg/host/mock/mock_host.go index 29d2c87ec..459ac594e 100644 --- a/pkg/host/mock/mock_host.go +++ b/pkg/host/mock/mock_host.go @@ -757,6 +757,20 @@ func (mr *MockHostManagerInterfaceMockRecorder) SetNetdevMTU(pciAddr, mtu interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNetdevMTU", reflect.TypeOf((*MockHostManagerInterface)(nil).SetNetdevMTU), pciAddr, mtu) } +// SetNicSriovMode mocks base method. +func (m *MockHostManagerInterface) SetNicSriovMode(pciAddr, mode string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetNicSriovMode", pciAddr, mode) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetNicSriovMode indicates an expected call of SetNicSriovMode. +func (mr *MockHostManagerInterfaceMockRecorder) SetNicSriovMode(pciAddr, mode interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNicSriovMode", reflect.TypeOf((*MockHostManagerInterface)(nil).SetNicSriovMode), pciAddr, mode) +} + // SetSriovNumVfs mocks base method. func (m *MockHostManagerInterface) SetSriovNumVfs(pciAddr string, numVfs int) error { m.ctrl.T.Helper() diff --git a/pkg/host/types/interfaces.go b/pkg/host/types/interfaces.go index e13f8ee66..1edea916e 100644 --- a/pkg/host/types/interfaces.go +++ b/pkg/host/types/interfaces.go @@ -132,6 +132,9 @@ type SriovInterface interface { // GetNicSriovMode returns the interface mode // supported modes SR-IOV legacy and switchdev GetNicSriovMode(pciAddr string) (string, error) + // SetNicSriovMode configure the interface mode + // supported modes SR-IOV legacy and switchdev + SetNicSriovMode(pciAddr, mode string) error // GetLinkType return the link type // supported types are ethernet and infiniband GetLinkType(ifaceStatus sriovnetworkv1.InterfaceExt) string From 2b49a6a0f2b33b99806e2ad61030a56d3f96b4ad Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 16 Jan 2024 13:11:34 +0200 Subject: [PATCH 37/61] Add tests for some functions in SriovInterface Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/sriov/sriov_test.go | 96 +++++++++++++++++++++++++++ pkg/host/internal/sriov/suite_test.go | 21 ++++++ 2 files changed, 117 insertions(+) create mode 100644 pkg/host/internal/sriov/sriov_test.go create mode 100644 pkg/host/internal/sriov/suite_test.go diff --git a/pkg/host/internal/sriov/sriov_test.go b/pkg/host/internal/sriov/sriov_test.go new file mode 100644 index 000000000..8a87a6de6 --- /dev/null +++ b/pkg/host/internal/sriov/sriov_test.go @@ -0,0 +1,96 @@ +package sriov + +import ( + "fmt" + "strconv" + "syscall" + + "github.com/golang/mock/gomock" + "github.com/vishvananda/netlink" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + netlinkMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink/mock" + hostMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/mock" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/helpers" +) + +var _ = Describe("SRIOV", func() { + var ( + s types.SriovInterface + libMock *netlinkMockPkg.MockNetlinkLib + hostMock *hostMockPkg.MockHostManagerInterface + + testCtrl *gomock.Controller + + testError = fmt.Errorf("test") + ) + BeforeEach(func() { + testCtrl = gomock.NewController(GinkgoT()) + libMock = netlinkMockPkg.NewMockNetlinkLib(testCtrl) + hostMock = hostMockPkg.NewMockHostManagerInterface(testCtrl) + s = New(nil, hostMock, hostMock, hostMock, libMock) + }) + + AfterEach(func() { + testCtrl.Finish() + }) + + Context("SetSriovNumVfs", func() { + It("set", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/sys/bus/pci/devices/0000:d8:00.0"}, + Files: map[string][]byte{"/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs": {}}, + }) + Expect(s.SetSriovNumVfs("0000:d8:00.0", 5)).NotTo(HaveOccurred()) + helpers.GinkgoAssertFileContentsEquals("/sys/bus/pci/devices/0000:d8:00.0/sriov_numvfs", strconv.Itoa(5)) + }) + It("fail - no such device", func() { + Expect(s.SetSriovNumVfs("0000:d8:00.0", 5)).To(HaveOccurred()) + }) + }) + + Context("GetNicSriovMode", func() { + It("devlink returns info", func() { + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return( + &netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "switchdev"}}}, + nil) + mode, err := s.GetNicSriovMode("0000:d8:00.0") + Expect(err).NotTo(HaveOccurred()) + Expect(mode).To(Equal("switchdev")) + }) + It("devlink returns error", func() { + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) + _, err := s.GetNicSriovMode("0000:d8:00.0") + Expect(err).To(MatchError(testError)) + }) + It("devlink not supported - fail to get name", func() { + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, syscall.ENODEV) + mode, err := s.GetNicSriovMode("0000:d8:00.0") + Expect(err).NotTo(HaveOccurred()) + Expect(mode).To(BeEmpty()) + }) + }) + + Context("SetNicSriovMode", func() { + It("set", func() { + testDev := &netlink.DevlinkDevice{} + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) + libMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(nil) + Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).NotTo(HaveOccurred()) + }) + It("fail to get dev", func() { + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) + Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError)) + }) + It("fail to set mode", func() { + testDev := &netlink.DevlinkDevice{} + libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) + libMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(testError) + Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError)) + }) + }) +}) diff --git a/pkg/host/internal/sriov/suite_test.go b/pkg/host/internal/sriov/suite_test.go new file mode 100644 index 000000000..8f76f0a85 --- /dev/null +++ b/pkg/host/internal/sriov/suite_test.go @@ -0,0 +1,21 @@ +package sriov + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "go.uber.org/zap/zapcore" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +func TestSriov(t *testing.T) { + log.SetLogger(zap.New( + zap.WriteTo(GinkgoWriter), + zap.Level(zapcore.Level(-2)), + zap.UseDevMode(true))) + RegisterFailHandler(Fail) + RunSpecs(t, "Package SRIOV Suite") +} From 6f2ccaa10347bf53cdd86e03153f943341ba4685 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Thu, 18 Jan 2024 17:42:39 +0200 Subject: [PATCH 38/61] Extend Udev interface to support switchdev rule This rule is required to generate predictable names for VF representors when NIC is in switchdev mode. Signed-off-by: Yury Kulazhenkov --- pkg/consts/constants.go | 13 ++- pkg/helper/mock/mock_helper.go | 28 +++++++ pkg/host/internal/udev/suite_test.go | 30 +++++++ pkg/host/internal/udev/udev.go | 58 +++++++++---- pkg/host/internal/udev/udev_test.go | 117 +++++++++++++++++++++++++++ pkg/host/mock/mock_host.go | 28 +++++++ pkg/host/types/interfaces.go | 8 +- 7 files changed, 265 insertions(+), 17 deletions(-) create mode 100644 pkg/host/internal/udev/suite_test.go create mode 100644 pkg/host/internal/udev/udev_test.go diff --git a/pkg/consts/constants.go b/pkg/consts/constants.go index e7255368d..d3ddd3f6d 100644 --- a/pkg/consts/constants.go +++ b/pkg/consts/constants.go @@ -92,7 +92,18 @@ const ( UdevRulesFolder = UdevFolder + "/rules.d" HostUdevRulesFolder = Host + UdevRulesFolder UdevDisableNM = "/bindata/scripts/udev-find-sriov-pf.sh" - NMUdevRule = "SUBSYSTEM==\"net\", ACTION==\"add|change|move\", ATTRS{device}==\"%s\", IMPORT{program}=\"/etc/udev/disable-nm-sriov.sh $env{INTERFACE} %s\"" + // nolint:goconst + NMUdevRule = `SUBSYSTEM=="net", ` + + `ACTION=="add|change|move", ` + + `ATTRS{device}=="%s", ` + + `IMPORT{program}="/etc/udev/disable-nm-sriov.sh $env{INTERFACE} %s"` + // nolint:goconst + SwitchdevUdevRule = `SUBSYSTEM=="net", ` + + `ACTION=="add|move", ` + + `ATTRS{phys_switch_id}=="%s", ` + + `ATTR{phys_port_name}=="pf%svf*", ` + + `IMPORT{program}="/etc/udev/switchdev-vf-link-name.sh $attr{phys_port_name}", ` + + `NAME="%s_$env{NUMBER}"` KernelArgPciRealloc = "pci=realloc" KernelArgIntelIommu = "intel_iommu=on" diff --git a/pkg/helper/mock/mock_helper.go b/pkg/helper/mock/mock_helper.go index b77f46720..a8e417e49 100644 --- a/pkg/helper/mock/mock_helper.go +++ b/pkg/helper/mock/mock_helper.go @@ -54,6 +54,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) AddUdevRule(pfPciAddress interfa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).AddUdevRule), pfPciAddress) } +// AddVfRepresentorUdevRule mocks base method. +func (m *MockHostHelpersInterface) AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddVfRepresentorUdevRule", pfPciAddress, pfName, pfSwitchID, pfSwitchPort) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddVfRepresentorUdevRule indicates an expected call of AddVfRepresentorUdevRule. +func (mr *MockHostHelpersInterfaceMockRecorder) AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddVfRepresentorUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).AddVfRepresentorUdevRule), pfPciAddress, pfName, pfSwitchID, pfSwitchPort) +} + // BindDefaultDriver mocks base method. func (m *MockHostHelpersInterface) BindDefaultDriver(pciAddr string) error { m.ctrl.T.Helper() @@ -851,6 +865,20 @@ func (mr *MockHostHelpersInterfaceMockRecorder) RemoveUdevRule(pfPciAddress inte return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveUdevRule), pfPciAddress) } +// RemoveVfRepresentorUdevRule mocks base method. +func (m *MockHostHelpersInterface) RemoveVfRepresentorUdevRule(pfPciAddress string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveVfRepresentorUdevRule", pfPciAddress) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveVfRepresentorUdevRule indicates an expected call of RemoveVfRepresentorUdevRule. +func (mr *MockHostHelpersInterfaceMockRecorder) RemoveVfRepresentorUdevRule(pfPciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveVfRepresentorUdevRule", reflect.TypeOf((*MockHostHelpersInterface)(nil).RemoveVfRepresentorUdevRule), pfPciAddress) +} + // ResetSriovDevice mocks base method. func (m *MockHostHelpersInterface) ResetSriovDevice(ifaceStatus v1.InterfaceExt) error { m.ctrl.T.Helper() diff --git a/pkg/host/internal/udev/suite_test.go b/pkg/host/internal/udev/suite_test.go new file mode 100644 index 000000000..34a8820cf --- /dev/null +++ b/pkg/host/internal/udev/suite_test.go @@ -0,0 +1,30 @@ +package udev + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "go.uber.org/zap/zapcore" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" +) + +func TestUdev(t *testing.T) { + log.SetLogger(zap.New( + zap.WriteTo(GinkgoWriter), + zap.Level(zapcore.Level(-2)), + zap.UseDevMode(true))) + RegisterFailHandler(Fail) + RunSpecs(t, "Package Udev Suite") +} + +var _ = BeforeSuite(func() { + vars.SupportedVfIds = []string{"0x1017", "0x1018"} + DeferCleanup(func() { + vars.SupportedVfIds = []string{} + }) +}) diff --git a/pkg/host/internal/udev/udev.go b/pkg/host/internal/udev/udev.go index dad88913e..2b4c4c6b3 100644 --- a/pkg/host/internal/udev/udev.go +++ b/pkg/host/internal/udev/udev.go @@ -146,34 +146,64 @@ func (u *udev) WriteSwitchdevConfFile(newState *sriovnetworkv1.SriovNetworkNodeS return true, nil } +// AddUdevRule adds a udev rule that disables network-manager for VFs on the concrete PF func (u *udev) AddUdevRule(pfPciAddress string) error { log.Log.V(2).Info("AddUdevRule()", "device", pfPciAddress) - pathFile := filepath.Join(vars.FilesystemRoot, consts.UdevRulesFolder) udevRuleContent := fmt.Sprintf(consts.NMUdevRule, strings.Join(vars.SupportedVfIds, "|"), pfPciAddress) + return u.addUdevRule(pfPciAddress, "10-nm-disable", udevRuleContent) +} + +// RemoveUdevRule removes a udev rule that disables network-manager for VFs on the concrete PF +func (u *udev) RemoveUdevRule(pfPciAddress string) error { + log.Log.V(2).Info("RemoveUdevRule()", "device", pfPciAddress) + return u.removeUdevRule(pfPciAddress, "10-nm-disable") +} + +// AddVfRepresentorUdevRule adds udev rule that renames VF representors on the concrete PF +func (u *udev) AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort string) error { + log.Log.V(2).Info("AddVfRepresentorUdevRule()", + "device", pfPciAddress, "name", pfName, "switch", pfSwitchID, "port", pfSwitchPort) + udevRuleContent := fmt.Sprintf(consts.SwitchdevUdevRule, pfSwitchID, strings.TrimPrefix(pfSwitchPort, "p"), pfName) + return u.addUdevRule(pfPciAddress, "20-switchdev", udevRuleContent) +} + +// RemoveVfRepresentorUdevRule removes udev rule that renames VF representors on the concrete PF +func (u *udev) RemoveVfRepresentorUdevRule(pfPciAddress string) error { + log.Log.V(2).Info("RemoveVfRepresentorUdevRule()", "device", pfPciAddress) + return u.removeUdevRule(pfPciAddress, "20-switchdev") +} - err := os.MkdirAll(pathFile, os.ModePerm) +func (u *udev) addUdevRule(pfPciAddress, ruleName, ruleContent string) error { + log.Log.V(2).Info("addUdevRule()", "device", pfPciAddress, "rule", ruleName) + rulePath := u.getRuleFolderPath() + err := os.MkdirAll(rulePath, os.ModePerm) if err != nil && !os.IsExist(err) { - log.Log.Error(err, "AddUdevRule(): failed to create dir", "path", pathFile) + log.Log.Error(err, "ensureUdevRulePathExist(): failed to create dir", "path", rulePath) return err } - - filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) - // if the file does not exist or if oldContent != newContent - // write to file and create it if it doesn't exist - err = os.WriteFile(filePath, []byte(udevRuleContent), 0666) - if err != nil { - log.Log.Error(err, "AddUdevRule(): fail to write file", "path", filePath) + filePath := u.getRulePathForPF(ruleName, pfPciAddress) + if err := os.WriteFile(filePath, []byte(ruleContent), 0666); err != nil { + log.Log.Error(err, "addUdevRule(): fail to write file", "path", filePath) return err } return nil } -func (u *udev) RemoveUdevRule(pfPciAddress string) error { - pathFile := filepath.Join(vars.FilesystemRoot, consts.UdevRulesFolder) - filePath := path.Join(pathFile, fmt.Sprintf("10-nm-disable-%s.rules", pfPciAddress)) - err := os.Remove(filePath) +func (u *udev) removeUdevRule(pfPciAddress, ruleName string) error { + log.Log.V(2).Info("removeUdevRule()", "device", pfPciAddress, "rule", ruleName) + rulePath := u.getRulePathForPF(ruleName, pfPciAddress) + err := os.Remove(rulePath) if err != nil && !os.IsNotExist(err) { + log.Log.Error(err, "removeUdevRule(): fail to remove rule file", "path", rulePath) return err } return nil } + +func (u *udev) getRuleFolderPath() string { + return filepath.Join(vars.FilesystemRoot, consts.UdevRulesFolder) +} + +func (u *udev) getRulePathForPF(ruleName, pfPciAddress string) string { + return path.Join(u.getRuleFolderPath(), fmt.Sprintf("%s-%s.rules", ruleName, pfPciAddress)) +} diff --git a/pkg/host/internal/udev/udev_test.go b/pkg/host/internal/udev/udev_test.go new file mode 100644 index 000000000..d5f222385 --- /dev/null +++ b/pkg/host/internal/udev/udev_test.go @@ -0,0 +1,117 @@ +package udev + +import ( + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/fakefilesystem" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/helpers" +) + +const ( + testExpectedNMUdevRule = `SUBSYSTEM=="net", ACTION=="add|change|move", ` + + `ATTRS{device}=="0x1017|0x1018", ` + + `IMPORT{program}="/etc/udev/disable-nm-sriov.sh $env{INTERFACE} 0000:d8:00.0"` + testExpectedSwitchdevUdevRule = `SUBSYSTEM=="net", ACTION=="add|move", ` + + `ATTRS{phys_switch_id}=="7cfe90ff2cc0", ` + + `ATTR{phys_port_name}=="pf0vf*", IMPORT{program}="/etc/udev/switchdev-vf-link-name.sh $attr{phys_port_name}", ` + + `NAME="enp216s0f0np0_$env{NUMBER}"` +) + +var _ = Describe("UDEV", func() { + var ( + s types.UdevInterface + ) + BeforeEach(func() { + s = New(nil) + }) + Context("AddUdevRule", func() { + It("Created", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{}) + Expect(s.AddUdevRule("0000:d8:00.0")).To(BeNil()) + helpers.GinkgoAssertFileContentsEquals( + "/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules", + testExpectedNMUdevRule) + }) + It("Overwrite", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + Files: map[string][]byte{ + "/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules": []byte("something"), + }, + }) + Expect(s.AddUdevRule("0000:d8:00.0")).To(BeNil()) + helpers.GinkgoAssertFileContentsEquals( + "/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules", + testExpectedNMUdevRule) + }) + }) + Context("RemoveUdevRule", func() { + It("Exist", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + Files: map[string][]byte{ + "/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules": []byte(testExpectedNMUdevRule), + }, + }) + Expect(s.RemoveUdevRule("0000:d8:00.0")).To(BeNil()) + _, err := os.Stat(filepath.Join(vars.FilesystemRoot, + "/etc/udev/rules.d/10-nm-disable-0000:d8:00.0.rules")) + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + It("Not found", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + }) + Expect(s.RemoveUdevRule("0000:d8:00.0")).To(BeNil()) + }) + }) + Context("AddVfRepresentorUdevRule", func() { + It("Created", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{}) + Expect(s.AddVfRepresentorUdevRule("0000:d8:00.0", + "enp216s0f0np0", "7cfe90ff2cc0", "p0")).To(BeNil()) + helpers.GinkgoAssertFileContentsEquals( + "/etc/udev/rules.d/20-switchdev-0000:d8:00.0.rules", + testExpectedSwitchdevUdevRule) + }) + It("Overwrite", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + Files: map[string][]byte{ + "/etc/udev/rules.d/20-switchdev-0000:d8:00.0.rules": []byte("something"), + }, + }) + Expect(s.AddVfRepresentorUdevRule("0000:d8:00.0", + "enp216s0f0np0", "7cfe90ff2cc0", "p0")).To(BeNil()) + helpers.GinkgoAssertFileContentsEquals( + "/etc/udev/rules.d/20-switchdev-0000:d8:00.0.rules", + testExpectedSwitchdevUdevRule) + }) + }) + Context("RemoveVfRepresentorUdevRule", func() { + It("Exist", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + Files: map[string][]byte{ + "/etc/udev/rules.d/20-switchdev-0000:d8:00.0.rules": []byte(testExpectedSwitchdevUdevRule), + }, + }) + Expect(s.RemoveVfRepresentorUdevRule("0000:d8:00.0")).To(BeNil()) + _, err := os.Stat(filepath.Join(vars.FilesystemRoot, + "/etc/udev/rules.d/20-switchdev-0000:d8:00.0.rules")) + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + It("Not found", func() { + helpers.GinkgoConfigureFakeFS(&fakefilesystem.FS{ + Dirs: []string{"/etc/udev/rules.d"}, + }) + Expect(s.RemoveVfRepresentorUdevRule("0000:d8:00.0")).To(BeNil()) + }) + }) +}) diff --git a/pkg/host/mock/mock_host.go b/pkg/host/mock/mock_host.go index 459ac594e..ddba8626e 100644 --- a/pkg/host/mock/mock_host.go +++ b/pkg/host/mock/mock_host.go @@ -53,6 +53,20 @@ func (mr *MockHostManagerInterfaceMockRecorder) AddUdevRule(pfPciAddress interfa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).AddUdevRule), pfPciAddress) } +// AddVfRepresentorUdevRule mocks base method. +func (m *MockHostManagerInterface) AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddVfRepresentorUdevRule", pfPciAddress, pfName, pfSwitchID, pfSwitchPort) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddVfRepresentorUdevRule indicates an expected call of AddVfRepresentorUdevRule. +func (mr *MockHostManagerInterfaceMockRecorder) AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddVfRepresentorUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).AddVfRepresentorUdevRule), pfPciAddress, pfName, pfSwitchID, pfSwitchPort) +} + // BindDefaultDriver mocks base method. func (m *MockHostManagerInterface) BindDefaultDriver(pciAddr string) error { m.ctrl.T.Helper() @@ -729,6 +743,20 @@ func (mr *MockHostManagerInterfaceMockRecorder) RemoveUdevRule(pfPciAddress inte return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).RemoveUdevRule), pfPciAddress) } +// RemoveVfRepresentorUdevRule mocks base method. +func (m *MockHostManagerInterface) RemoveVfRepresentorUdevRule(pfPciAddress string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveVfRepresentorUdevRule", pfPciAddress) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveVfRepresentorUdevRule indicates an expected call of RemoveVfRepresentorUdevRule. +func (mr *MockHostManagerInterfaceMockRecorder) RemoveVfRepresentorUdevRule(pfPciAddress interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveVfRepresentorUdevRule", reflect.TypeOf((*MockHostManagerInterface)(nil).RemoveVfRepresentorUdevRule), pfPciAddress) +} + // ResetSriovDevice mocks base method. func (m *MockHostManagerInterface) ResetSriovDevice(ifaceStatus v1.InterfaceExt) error { m.ctrl.T.Helper() diff --git a/pkg/host/types/interfaces.go b/pkg/host/types/interfaces.go index 1edea916e..6a12f29cd 100644 --- a/pkg/host/types/interfaces.go +++ b/pkg/host/types/interfaces.go @@ -157,10 +157,14 @@ type UdevInterface interface { // PrepareNMUdevRule creates the needed udev rules to disable NetworkManager from // our managed SR-IOV virtual functions PrepareNMUdevRule(supportedVfIds []string) error - // AddUdevRule adds a specific udev rule to the system + // AddUdevRule adds a udev rule that disables network-manager for VFs on the concrete PF AddUdevRule(pfPciAddress string) error - // RemoveUdevRule removes a udev rule from the system + // RemoveUdevRule removes a udev rule that disables network-manager for VFs on the concrete PF RemoveUdevRule(pfPciAddress string) error + // AddVfRepresentorUdevRule adds udev rule that renames VF representors on the concrete PF + AddVfRepresentorUdevRule(pfPciAddress, pfName, pfSwitchID, pfSwitchPort string) error + // RemoveVfRepresentorUdevRule removes udev rule that renames VF representors on the concrete PF + RemoveVfRepresentorUdevRule(pfPciAddress string) error } type VdpaInterface interface { From b6de854ba250397a716a96a661cec9dcfa807969 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Thu, 25 Jan 2024 15:46:35 +0200 Subject: [PATCH 39/61] fix k8s cluster script we must disable the checksum offload on the virtual PF if not when we create virtual functions on the nic the host have checksum issues Signed-off-by: Sebastian Sch --- hack/run-e2e-conformance-virtual-cluster.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hack/run-e2e-conformance-virtual-cluster.sh b/hack/run-e2e-conformance-virtual-cluster.sh index 90670f2df..351614251 100755 --- a/hack/run-e2e-conformance-virtual-cluster.sh +++ b/hack/run-e2e-conformance-virtual-cluster.sh @@ -166,6 +166,23 @@ method=disabled [proxy]' > /etc/NetworkManager/system-connections/multi.nmconnection chmod 600 /etc/NetworkManager/system-connections/multi.nmconnection + +echo '[Unit] +Description=disable checksum offload to avoid vf bug +After=network.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/bash -c "ethtool --offload eth1 rx off tx off && ethtool -K eth1 gso off" +StandardOutput=journal+console +StandardError=journal+console + +[Install] +WantedBy=default.target' > /etc/systemd/system/disable-offload.service + +systemctl daemon-reload +systemctl enable --now disable-offload + systemctl restart NetworkManager EOF From dc299875ebd3e47dd6c8364dde49e956b22ac91e Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Tue, 9 Jan 2024 14:40:10 +0200 Subject: [PATCH 40/61] Fix LogLevel functional test Signed-off-by: Sebastian Sch --- test/conformance/tests/test_sriov_operator.go | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index 208ed2b9f..5b387cc5a 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -214,7 +214,7 @@ var _ = Describe("[sriov] operator", func() { setOperatorConfigLogLevel(2) By("Flip DisableDrain to trigger operator activity") - since := time.Now() + since := time.Now().Add(-10 * time.Second) Eventually(func() error { return cluster.SetDisableNodeDrainState(clients, operatorNamespace, !initialDisableDrain) }, 1*time.Minute, 5*time.Second).ShouldNot(HaveOccurred()) @@ -240,7 +240,7 @@ var _ = Describe("[sriov] operator", func() { setOperatorConfigLogLevel(0) By("Flip DisableDrain again to trigger operator activity") - since = time.Now() + since = time.Now().Add(-10 * time.Second) Eventually(func() error { return cluster.SetDisableNodeDrainState(clients, operatorNamespace, initialDisableDrain) }, 1*time.Minute, 5*time.Second).ShouldNot(HaveOccurred()) @@ -248,20 +248,32 @@ var _ = Describe("[sriov] operator", func() { By("Assert logs contains less operator activity") Eventually(func(g Gomega) { logs := getOperatorLogs(since) - g.Expect(logs).To( + + // time only contains sec, but we can have race here that in the same sec there was a sync + afterLogs := []string{} + found := false + for _, log := range logs { + if found { + afterLogs = append(afterLogs, log) + } + if strings.Contains(log, "{\"new-level\": 0, \"current-level\": 2}") { + found = true + } + } + g.Expect(found).To(BeTrue()) + g.Expect(afterLogs).To( ContainElement(And( ContainSubstring("Reconciling SriovOperatorConfig"), )), ) // Should not contain verbose logging - g.Expect(logs).ToNot( + g.Expect(afterLogs).ToNot( ContainElement( ContainSubstring("Start to sync webhook objects"), ), ) - }, 1*time.Minute, 5*time.Second).Should(Succeed()) - + }, 3*time.Minute, 5*time.Second).Should(Succeed()) }) }) }) From a16a0d7f4f8b4ed5e56fba5bff26e0e121df5e65 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Thu, 25 Jan 2024 19:57:00 +0200 Subject: [PATCH 41/61] fix ocp CI lane some time there is a registry push error so we just implement a retry Signed-off-by: Sebastian Sch --- hack/run-e2e-conformance-virtual-ocp.sh | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/hack/run-e2e-conformance-virtual-ocp.sh b/hack/run-e2e-conformance-virtual-ocp.sh index 66a1cc910..c1f4d3b74 100755 --- a/hack/run-e2e-conformance-virtual-ocp.sh +++ b/hack/run-e2e-conformance-virtual-ocp.sh @@ -214,11 +214,30 @@ internal_registry="image-registry.openshift-image-registry.svc:5000" pass=$( jq .\"$internal_registry\".password registry-login.conf ) podman login -u serviceaccount -p ${pass:1:-1} $registry --tls-verify=false -podman push --tls-verify=false "${SRIOV_NETWORK_OPERATOR_IMAGE}" +MAX_RETRIES=20 +DELAY_SECONDS=10 +retry_push() { + local command="podman push --tls-verify=false $@" + local retries=0 + + until [ $retries -ge $MAX_RETRIES ]; do + $command && break + retries=$((retries+1)) + echo "Command failed. Retrying... (Attempt $retries/$MAX_RETRIES)" + sleep $DELAY_SECONDS + done + + if [ $retries -eq $MAX_RETRIES ]; then + echo "Max retries reached. Exiting..." + exit 1 + fi +} + +retry_push "${SRIOV_NETWORK_OPERATOR_IMAGE}" podman rmi -fi ${SRIOV_NETWORK_OPERATOR_IMAGE} -podman push --tls-verify=false "${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE}" +retry_push "${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE}" podman rmi -fi ${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE} -podman push --tls-verify=false "${SRIOV_NETWORK_WEBHOOK_IMAGE}" +retry_push "${SRIOV_NETWORK_WEBHOOK_IMAGE}" podman rmi -fi ${SRIOV_NETWORK_WEBHOOK_IMAGE} podman logout $registry From 48808ae177e4a632436c603d977cd83992ad6b75 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Thu, 25 Jan 2024 15:50:18 +0200 Subject: [PATCH 42/61] re-enable mtu test on virtual cluster QEMU 8.2.0 introduce a fix to the kernel panic when allocation jumbo MTU so we can re-enable the test Signed-off-by: Sebastian Sch --- test/conformance/tests/test_sriov_operator.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index 5b387cc5a..7d13d3ae3 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -1446,10 +1446,6 @@ var _ = Describe("[sriov] operator", func() { Context("MTU", func() { BeforeEach(func() { - if cluster.VirtualCluster() { - // https://bugzilla.redhat.com/show_bug.cgi?id=2214977 - Skip("Bug in IGB driver") - } var node string resourceName := "mturesource" From eaa81ce27bd5e457163d7add28debea58fd2fec6 Mon Sep 17 00:00:00 2001 From: Sebastian Sch Date: Sun, 28 Jan 2024 15:58:04 +0200 Subject: [PATCH 43/61] add NET_RAW to allow pods to ping Signed-off-by: Sebastian Sch --- test/util/pod/pod.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/util/pod/pod.go b/test/util/pod/pod.go index 32a1549b9..4963ba3f7 100644 --- a/test/util/pod/pod.go +++ b/test/util/pod/pod.go @@ -29,7 +29,11 @@ func GetDefinition() *corev1.Pod { Spec: corev1.PodSpec{ TerminationGracePeriodSeconds: pointer.Int64Ptr(0), Containers: []corev1.Container{{Name: "test", - Image: images.Test(), + Image: images.Test(), + SecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{"NET_RAW"}, + }}, Command: []string{"/bin/bash", "-c", "sleep INF"}}}}} return podObject From d5d0273e7d9866a7b211e20816b627df7e5d8abc Mon Sep 17 00:00:00 2001 From: Andrea Panattoni Date: Tue, 10 Oct 2023 09:42:15 +0200 Subject: [PATCH 44/61] e2e: Allow testing custom cni and dp image Let `run-e2e-conformance-virtual-ocp.sh` and `run-e2e-conformance-virtual-cluster.sh` deploy clusters with specific SRIOV CNI and Device Plugin images. This will enable other projects to have full end-to-end test CI with operator's suite. Signed-off-by: Andrea Panattoni --- hack/run-e2e-conformance-common | 10 ++++++++++ hack/run-e2e-conformance-virtual-cluster.sh | 19 +++++++++++++++++++ hack/run-e2e-conformance-virtual-ocp.sh | 17 +++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 hack/run-e2e-conformance-common diff --git a/hack/run-e2e-conformance-common b/hack/run-e2e-conformance-common new file mode 100644 index 000000000..c2a71e518 --- /dev/null +++ b/hack/run-e2e-conformance-common @@ -0,0 +1,10 @@ +#!/bin/bash + +podman_tag_and_push() { + local_image=$1 + cluster_image=$2 + + echo "## Pushing ${local_image} to cluster registry ${cluster_image}" + podman tag ${local_image} ${cluster_image} + podman push --tls-verify=false ${cluster_image} +} diff --git a/hack/run-e2e-conformance-virtual-cluster.sh b/hack/run-e2e-conformance-virtual-cluster.sh index 351614251..66c32f66e 100755 --- a/hack/run-e2e-conformance-virtual-cluster.sh +++ b/hack/run-e2e-conformance-virtual-cluster.sh @@ -19,6 +19,8 @@ if [ "$NUM_OF_WORKERS" -lt 2 ]; then exit 1 fi +source $here/run-e2e-conformance-common + check_requirements() { for cmd in kcli virsh virt-edit podman make go; do if ! command -v "$cmd" &> /dev/null; then @@ -294,6 +296,23 @@ podman rmi -fi ${SRIOV_NETWORK_CONFIG_DAEMON_IMAGE} podman push --tls-verify=false "${SRIOV_NETWORK_WEBHOOK_IMAGE}" podman rmi -fi ${SRIOV_NETWORK_WEBHOOK_IMAGE} + +if [[ -v LOCAL_SRIOV_CNI_IMAGE ]]; then + export SRIOV_CNI_IMAGE="$controller_ip:5000/sriov-cni:latest" + podman_tag_and_push ${LOCAL_SRIOV_CNI_IMAGE} ${SRIOV_CNI_IMAGE} +fi + +if [[ -v LOCAL_SRIOV_DEVICE_PLUGIN_IMAGE ]]; then + export SRIOV_DEVICE_PLUGIN_IMAGE="$controller_ip:5000/sriov-network-device-plugin:latest" + podman_tag_and_push ${LOCAL_SRIOV_DEVICE_PLUGIN_IMAGE} ${SRIOV_DEVICE_PLUGIN_IMAGE} +fi + +if [[ -v LOCAL_NETWORK_RESOURCES_INJECTOR_IMAGE ]]; then + export NETWORK_RESOURCES_INJECTOR_IMAGE="$controller_ip:5000/network-resources-injector:latest" + podman_tag_and_push ${LOCAL_NETWORK_RESOURCES_INJECTOR_IMAGE} ${NETWORK_RESOURCES_INJECTOR_IMAGE} +fi + + # remove the crio bridge and let flannel to recreate kcli ssh $cluster_name-ctlplane-0 << EOF sudo su diff --git a/hack/run-e2e-conformance-virtual-ocp.sh b/hack/run-e2e-conformance-virtual-ocp.sh index c1f4d3b74..92e196185 100755 --- a/hack/run-e2e-conformance-virtual-ocp.sh +++ b/hack/run-e2e-conformance-virtual-ocp.sh @@ -21,6 +21,8 @@ fi here="$(dirname "$(readlink --canonicalize "${BASH_SOURCE[0]}")")" root="$(readlink --canonicalize "$here/..")" +source $here/run-e2e-conformance-common + check_requirements() { for cmd in kcli virsh podman make go jq base64 tar; do if ! command -v "$cmd" &> /dev/null; then @@ -263,6 +265,21 @@ export SRIOV_NETWORK_OPERATOR_IMAGE="image-registry.openshift-image-registry.svc export SRIOV_NETWORK_CONFIG_DAEMON_IMAGE="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/sriov-network-config-daemon:latest" export SRIOV_NETWORK_WEBHOOK_IMAGE="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/sriov-network-operator-webhook:latest" +if [[ -v LOCAL_SRIOV_CNI_IMAGE ]]; then + podman_tag_and_push ${LOCAL_SRIOV_CNI_IMAGE} "$registry/$NAMESPACE/sriov-cni:latest" + export SRIOV_CNI_IMAGE="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/sriov-cni:latest" +fi + +if [[ -v LOCAL_SRIOV_DEVICE_PLUGIN_IMAGE ]]; then + podman_tag_and_push ${LOCAL_SRIOV_DEVICE_PLUGIN_IMAGE} "$registry/$NAMESPACE/sriov-network-device-plugin:latest" + export SRIOV_DEVICE_PLUGIN_IMAGE="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/sriov-network-device-plugin:latest" +fi + +if [[ -v LOCAL_NETWORK_RESOURCES_INJECTOR_IMAGE ]]; then + podman_tag_and_push ${LOCAL_NETWORK_RESOURCES_INJECTOR_IMAGE} "$registry/$NAMESPACE/network-resources-injector:latest" + export NETWORK_RESOURCES_INJECTOR_IMAGE="image-registry.openshift-image-registry.svc:5000/$NAMESPACE/network-resources-injector:latest" +fi + echo "## deploying SRIOV Network Operator" hack/deploy-setup.sh $NAMESPACE From 46634125e683749bbf26d6cc98c2073ad68eb77e Mon Sep 17 00:00:00 2001 From: Andrea Panattoni Date: Fri, 3 Nov 2023 16:10:42 +0100 Subject: [PATCH 45/61] e2e: Gather `cluster-info` on test failure This is a leftover from - https://github.com/k8snetworkplumbingwg/sriov-network-operator/pull/534 Prior to this commit, `kubectl cluster-info ...` is invoked only if the conformance tests does not fail, which is not that useful. Signed-off-by: Andrea Panattoni --- hack/run-e2e-conformance-virtual-cluster.sh | 8 ++++++++ hack/run-e2e-conformance-virtual-ocp.sh | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/hack/run-e2e-conformance-virtual-cluster.sh b/hack/run-e2e-conformance-virtual-cluster.sh index 66c32f66e..5d78f7a8c 100755 --- a/hack/run-e2e-conformance-virtual-cluster.sh +++ b/hack/run-e2e-conformance-virtual-cluster.sh @@ -426,9 +426,17 @@ if [ -z $SKIP_TEST ]; then export JUNIT_OUTPUT="${root}/${TEST_REPORT_PATH}/conformance-test-report" fi + # Disable exit on error temporarily to gather cluster information + set +e SUITE=./test/conformance hack/run-e2e-conformance.sh + TEST_EXITE_CODE=$? + set -e if [[ -v TEST_REPORT_PATH ]]; then kubectl cluster-info dump --namespaces ${NAMESPACE} --output-directory "${root}/${TEST_REPORT_PATH}/cluster-info" fi + + if [[ $TEST_EXITE_CODE -ne 0 ]]; then + exit $TEST_EXITE_CODE + fi fi diff --git a/hack/run-e2e-conformance-virtual-ocp.sh b/hack/run-e2e-conformance-virtual-ocp.sh index 92e196185..1172baa35 100755 --- a/hack/run-e2e-conformance-virtual-ocp.sh +++ b/hack/run-e2e-conformance-virtual-ocp.sh @@ -293,9 +293,17 @@ if [ -z $SKIP_TEST ]; then export JUNIT_OUTPUT="${root}/${TEST_REPORT_PATH}/conformance-test-report" fi + # Disable exit on error temporarily to gather cluster information + set +e SUITE=./test/conformance hack/run-e2e-conformance.sh + TEST_EXITE_CODE=$? + set -e if [[ -v TEST_REPORT_PATH ]]; then kubectl cluster-info dump --namespaces ${NAMESPACE} --output-directory "${root}/${TEST_REPORT_PATH}/cluster-info" fi + + if [[ $TEST_EXITE_CODE -ne 0 ]]; then + exit $TEST_EXITE_CODE + fi fi From 5f525973eb942033521c9722d7fba598b2af8247 Mon Sep 17 00:00:00 2001 From: Ivan Kolodiazhnyi Date: Wed, 15 Nov 2023 12:32:34 +0200 Subject: [PATCH 46/61] Remove sriov-cni daemonset-related code sriov-cni daemonset isn't deployed anymore. It should be cleaned up during the previos release upgrade so we don't need to support it in the code anymore. --- .../sriovnetworknodepolicy_controller.go | 52 ------------------- controllers/sriovoperatorconfig_controller.go | 36 ++++++------- 2 files changed, 17 insertions(+), 71 deletions(-) diff --git a/controllers/sriovnetworknodepolicy_controller.go b/controllers/sriovnetworknodepolicy_controller.go index 3d1da743f..6f7cb44d1 100644 --- a/controllers/sriovnetworknodepolicy_controller.go +++ b/controllers/sriovnetworknodepolicy_controller.go @@ -30,7 +30,6 @@ import ( errs "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -423,57 +422,6 @@ func (r *SriovNetworkNodePolicyReconciler) syncPluginDaemonObjs(ctx context.Cont } } - // Sriov-cni container has been moved to sriov-network-config-daemon DaemonSet. - // Delete stale sriov-cni manifests. Revert this change once sriov-cni daemonSet - // is deprecated. - err = r.deleteSriovCniManifests(ctx) - if err != nil { - return err - } - - return nil -} - -func (r *SriovNetworkNodePolicyReconciler) deleteSriovCniManifests(ctx context.Context) error { - ds := &appsv1.DaemonSet{} - err := r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "sriov-cni"}, ds) - if err != nil { - if !errors.IsNotFound(err) { - return err - } - } else { - err = r.Delete(ctx, ds) - if err != nil { - return err - } - } - - rb := &rbacv1.RoleBinding{} - err = r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "sriov-cni"}, rb) - if err != nil { - if !errors.IsNotFound(err) { - return err - } - } else { - err = r.Delete(ctx, rb) - if err != nil { - return err - } - } - - sa := &corev1.ServiceAccount{} - err = r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "sriov-cni"}, sa) - if err != nil { - if !errors.IsNotFound(err) { - return err - } - } else { - err = r.Delete(ctx, sa) - if err != nil { - return err - } - } - return nil } diff --git a/controllers/sriovoperatorconfig_controller.go b/controllers/sriovoperatorconfig_controller.go index 1e4c7728b..3eff3857a 100644 --- a/controllers/sriovoperatorconfig_controller.go +++ b/controllers/sriovoperatorconfig_controller.go @@ -157,27 +157,25 @@ func (r *SriovOperatorConfigReconciler) syncPluginDaemonSet(ctx context.Context, logger.V(1).Info("Start to sync SRIOV plugin daemonsets nodeSelector") ds := &appsv1.DaemonSet{} - names := []string{"sriov-cni", "sriov-device-plugin"} + name := "sriov-device-plugin" - for _, name := range names { - err := r.Client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, ds) - if err != nil { - if apierrors.IsNotFound(err) { - continue - } - logger.Error(err, "Couldn't get daemonset", "name", name) - return err - } - if len(dc.Spec.ConfigDaemonNodeSelector) == 0 { - ds.Spec.Template.Spec.NodeSelector = GetDefaultNodeSelector() - } else { - ds.Spec.Template.Spec.NodeSelector = dc.Spec.ConfigDaemonNodeSelector - } - err = r.Client.Update(ctx, ds) - if err != nil { - logger.Error(err, "Couldn't update daemonset", "name", name) - return err + err := r.Client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, ds) + if err != nil { + if apierrors.IsNotFound(err) { + return nil } + logger.Error(err, "Couldn't get daemonset", "name", name) + return err + } + if len(dc.Spec.ConfigDaemonNodeSelector) == 0 { + ds.Spec.Template.Spec.NodeSelector = GetDefaultNodeSelector() + } else { + ds.Spec.Template.Spec.NodeSelector = dc.Spec.ConfigDaemonNodeSelector + } + err = r.Client.Update(ctx, ds) + if err != nil { + logger.Error(err, "Couldn't update daemonset", "name", name) + return err } return nil From 9026a2df4cf6b2eb49247c32515d7fb24bbb3cb3 Mon Sep 17 00:00:00 2001 From: Andrea Panattoni Date: Mon, 29 Jan 2024 10:18:15 +0100 Subject: [PATCH 47/61] e2e: Skip tests when no VF-IO devices are available Test cases in ``` ... Create vfio-pci node policy Should be possible to create a vfio-pci resource ... PF Partitioning Should be possible to partition the pf's vfs ``` should be skipped if there are no available SR-IOV devices in the cluster that support vfio-pci mode. Make `ExternallyManaged Validation` test cases don't need vfio-pci devices. Use a the function `FindOneSriovNodeAndDevice()` to less striclty discover NICs. Refs: - https://github.com/k8snetworkplumbingwg/sriov-network-operator/commit/aeb60e2f64aa6f61d74613c68a3f7ba7cc520e3d Signed-off-by: Andrea Panattoni --- test/conformance/tests/test_sriov_operator.go | 24 +++++++++++-------- test/util/cluster/cluster.go | 19 +++++++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/test/conformance/tests/test_sriov_operator.go b/test/conformance/tests/test_sriov_operator.go index 5b387cc5a..d95b4609d 100644 --- a/test/conformance/tests/test_sriov_operator.go +++ b/test/conformance/tests/test_sriov_operator.go @@ -1071,7 +1071,9 @@ var _ = Describe("[sriov] operator", func() { } vfioNode, vfioNic = sriovInfos.FindOneVfioSriovDevice() - Expect(vfioNode).ToNot(Equal("")) + if vfioNode == "" { + Skip("skip test as no vfio-pci capable PF was found") + } By("Using device " + vfioNic.Name + " on node " + vfioNode) }) @@ -1108,20 +1110,20 @@ var _ = Describe("[sriov] operator", func() { }) Context("PF Partitioning", func() { - var vfioNode string - var vfioNic sriovv1.InterfaceExt - // 27633 BeforeEach(func() { if discovery.Enabled() { Skip("Test unsuitable to be run in discovery mode") } - vfioNode, vfioNic = sriovInfos.FindOneVfioSriovDevice() - Expect(vfioNode).ToNot(Equal("")) - By("Using device " + vfioNic.Name + " on node " + vfioNode) }) It("Should be possible to partition the pf's vfs", func() { + vfioNode, vfioNic := sriovInfos.FindOneVfioSriovDevice() + if vfioNode == "" { + Skip("skip test as no vfio-pci capable PF was found") + } + By("Using device " + vfioNic.Name + " on node " + vfioNode) + _, err := network.CreateSriovPolicy(clients, "test-policy-", operatorNamespace, vfioNic.Name+"#2-4", vfioNode, 5, testResourceName, "netdevice") Expect(err).ToNot(HaveOccurred()) @@ -2030,14 +2032,16 @@ var _ = Describe("[sriov] operator", func() { Context("ExternallyManaged Validation", func() { numVfs := 5 var node string - var nic sriovv1.InterfaceExt + var nic *sriovv1.InterfaceExt externallyManage := func(policy *sriovv1.SriovNetworkNodePolicy) { policy.Spec.ExternallyManaged = true } execute.BeforeAll(func() { - node, nic = sriovInfos.FindOneVfioSriovDevice() - Expect(node).ToNot(Equal("")) + var err error + node, nic, err = sriovInfos.FindOneSriovNodeAndDevice() + Expect(err).ToNot(HaveOccurred()) + By("Using device " + nic.Name + " on node " + node) }) diff --git a/test/util/cluster/cluster.go b/test/util/cluster/cluster.go index af2230cff..b79e61ad2 100644 --- a/test/util/cluster/cluster.go +++ b/test/util/cluster/cluster.go @@ -2,6 +2,7 @@ package cluster import ( "context" + "errors" "fmt" "io" "os" @@ -181,6 +182,24 @@ func (n *EnabledNodes) FindSriovDevicesIgnoreFilters(node string) ([]*sriovv1.In return devices, nil } +// FindOneSriovNodeAndDevice finds a cluster node with one SR-IOV devices respecting the `SRIOV_NODE_AND_DEVICE_NAME_FILTER` filter. +func (n *EnabledNodes) FindOneSriovNodeAndDevice() (string, *sriovv1.InterfaceExt, error) { + errs := []error{} + for _, node := range n.Nodes { + devices, err := n.FindSriovDevices(node) + if err != nil { + errs = append(errs, err) + continue + } + + if len(devices) > 0 { + return node, devices[0], nil + } + } + + return "", nil, fmt.Errorf("can't find any SR-IOV devices in cluster's nodes: %w", errors.Join(errs...)) +} + // FindOneVfioSriovDevice retrieves a node with a valid sriov device for vfio func (n *EnabledNodes) FindOneVfioSriovDevice() (string, sriovv1.InterfaceExt) { for _, node := range n.Nodes { From cfbfd2eb18eae405db9250ea7d10ce8127fc0cb1 Mon Sep 17 00:00:00 2001 From: adrianc Date: Mon, 29 Jan 2024 15:05:19 +0200 Subject: [PATCH 48/61] Makefile enhancements - remove redundant "vet" target as lint tests already cover its functionality - remove commented out code - add option to provide specific pkgs to test in make test target via TESTPKGS env var, preserving current behaviour if not provided Signed-off-by: adrianc --- Makefile | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index df5f6c91d..a7f063780 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ export WATCH_NAMESPACE?=openshift-sriov-network-operator export GOFLAGS+=-mod=vendor export GO111MODULE=on PKGS=$(shell go list ./... | grep -v -E '/vendor/|/test|/examples') +TESTPKGS?=./... # go source files, ignore vendor directory SRC = $(shell find . -type f -name '*.go' -not -path "./vendor/*") @@ -56,7 +57,7 @@ GOLANGCI_LINT_VER = v1.55.2 .PHONY: all build clean gendeepcopy test test-e2e test-e2e-k8s run image fmt sync-manifests test-e2e-conformance manifests update-codegen -all: generate vet build +all: generate lint build build: manager _build-sriov-network-config-daemon _build-webhook @@ -76,14 +77,14 @@ image: ; $(info Building images...) $(IMAGE_BUILDER) build -f $(DOCKERFILE_WEBHOOK) -t $(WEBHOOK_IMAGE_TAG) $(CURPATH) $(IMAGE_BUILD_OPTS) # Run tests -test: generate vet manifests envtest - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir=/tmp -p path)" HOME="$(shell pwd)" go test ./... -coverprofile cover.out -v +test: generate lint manifests envtest + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir=/tmp -p path)" HOME="$(shell pwd)" go test -coverprofile cover.out -v ${TESTPKGS} # Build manager binary -manager: generate vet _build-manager +manager: generate _build-manager # Run against the configured Kubernetes cluster in ~/.kube/config -run: vet skopeo install +run: skopeo install hack/run-locally.sh # Install CRDs into a cluster @@ -132,10 +133,6 @@ fmt: ## Go fmt your code fmt-code: go fmt ./... -# Run go vet against code -vet: - go vet ./... - # Generate code generate: controller-gen $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." @@ -205,7 +202,7 @@ redeploy-operator-virtual-cluster: test-e2e-validation-only: SUITE=./test/validation ./hack/run-e2e-conformance.sh -test-e2e: generate vet manifests skopeo envtest +test-e2e: generate manifests skopeo envtest KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir=/tmp -p path)"; source hack/env.sh; HOME="$(shell pwd)" go test ./test/e2e/... -timeout 60m -coverprofile cover.out -v test-e2e-k8s: export NAMESPACE=sriov-network-operator @@ -214,14 +211,9 @@ test-e2e-k8s: test-e2e test-bindata-scripts: fakechroot fakechroot ./test/scripts/enable-kargs_test.sh -test-%: generate vet manifests envtest +test-%: generate manifests envtest KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir=/tmp -p path)" HOME="$(shell pwd)" go test ./$*/... -coverprofile cover-$*.out -coverpkg ./... -v -# deploy-setup-k8s: export NAMESPACE=sriov-network-operator -# deploy-setup-k8s: export ADMISSION_CONTROLLERS_ENABLED=false -# deploy-setup-k8s: export CNI_BIN_PATH=/opt/cni/bin -# test-e2e-k8s: test-e2e - GOCOVMERGE = $(BIN_DIR)/gocovmerge gocovmerge: ## Download gocovmerge locally if necessary. $(call go-install-tool,$(GOCOVMERGE),github.com/shabbyrobe/gocovmerge/cmd/gocovmerge@latest) From 3c15708a6b7e0df16bb0d6469c244f18ef8402cf Mon Sep 17 00:00:00 2001 From: adrianc Date: Mon, 29 Jan 2024 15:08:10 +0200 Subject: [PATCH 49/61] run controllers test with kubernetes cluster type Add step to run controller tests with k8s cluster type as well. Signed-off-by: adrianc --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4476a96d7..cbab249e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,6 +46,9 @@ jobs: - name: test controllers on opensfhit run: CLUSTER_TYPE=openshift make test-controllers + - name: test controllers on kubernetes + run: CLUSTER_TYPE=kubernetes make test-controllers + - name: test bindata/scripts run: make test-bindata-scripts From 41075810212f0c2bc41026d7dd483c84f073fbf5 Mon Sep 17 00:00:00 2001 From: adrianc Date: Mon, 29 Jan 2024 15:09:08 +0200 Subject: [PATCH 50/61] Remove envtest from webhook tests its not needed to start envtest. moreover without this change, envtest environment would have remained running in the system as it was not stopped when test finished. Signed-off-by: adrianc --- pkg/webhook/validate_test.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/webhook/validate_test.go b/pkg/webhook/validate_test.go index 6197ad660..d67e1a011 100644 --- a/pkg/webhook/validate_test.go +++ b/pkg/webhook/validate_test.go @@ -10,8 +10,6 @@ import ( . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "sigs.k8s.io/controller-runtime/pkg/envtest" . "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" @@ -1044,13 +1042,8 @@ func TestValidatePolicyForNodeStateWithInvalidDevice(t *testing.T) { }, } g := NewGomegaWithT(t) - var testEnv = &envtest.Environment{} - cfg, err := testEnv.Start() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cfg).ToNot(BeNil()) - kubeclient = kubernetes.NewForConfigOrDie(cfg) - _, err = validatePolicyForNodeState(policy, state, NewNode()) + _, err := validatePolicyForNodeState(policy, state, NewNode()) g.Expect(err).NotTo(HaveOccurred()) } From 78fabc85f6979b0153fb876de281120c81e6314d Mon Sep 17 00:00:00 2001 From: adrianc Date: Mon, 29 Jan 2024 15:11:33 +0200 Subject: [PATCH 51/61] Controllers test enhancements - skip sriovnetworkpoolconfig only test-case in kubernetes cluster as it only valid for openshift. - general: only stop envtest if it was successfully started to avoid nil pointer dereference in case system was missconfigured since AfterSuite Ginkgo node would run even if BeforeSuite node failed Signed-off-by: adrianc --- controllers/sriovnetworkpoolconfig_controller_test.go | 6 ++++++ controllers/suite_test.go | 11 ++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/controllers/sriovnetworkpoolconfig_controller_test.go b/controllers/sriovnetworkpoolconfig_controller_test.go index 5b76d1d19..b95f5edac 100644 --- a/controllers/sriovnetworkpoolconfig_controller_test.go +++ b/controllers/sriovnetworkpoolconfig_controller_test.go @@ -13,12 +13,18 @@ import ( mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var _ = Describe("Operator", func() { Context("When is up", func() { It("should be able to create machine config for MachineConfigPool specified in sriov pool config", func() { + if vars.ClusterType != consts.ClusterTypeOpenshift { + Skip("test should only be executed with openshift cluster type") + } + config := &sriovnetworkv1.SriovNetworkPoolConfig{} config.SetNamespace(testNamespace) config.SetName("ovs-hw-offload-config") diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 0493ab7c6..6a9b1af5d 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -67,7 +67,7 @@ const ( interval = time.Millisecond * 250 ) -var _ = BeforeSuite(func(done Done) { +var _ = BeforeSuite(func() { logf.SetLogger(zap.New( zap.WriteTo(GinkgoWriter), zap.UseDevMode(true), @@ -213,15 +213,16 @@ var _ = BeforeSuite(func(done Done) { poolConfig.SetName(constants.DefaultConfigName) poolConfig.Spec = sriovnetworkv1.SriovNetworkPoolConfigSpec{} Expect(k8sClient.Create(context.TODO(), poolConfig)).Should(Succeed()) - close(done) }) var _ = AfterSuite(func() { By("tearing down the test environment") cancel() - Eventually(func() error { - return testEnv.Stop() - }, timeout, time.Second).ShouldNot(HaveOccurred()) + if testEnv != nil { + Eventually(func() error { + return testEnv.Stop() + }, timeout, time.Second).ShouldNot(HaveOccurred()) + } }) func TestAPIs(t *testing.T) { From 6867541c5d2bb839bf30ef7cf6a3461eabe84fa2 Mon Sep 17 00:00:00 2001 From: adrianc Date: Mon, 29 Jan 2024 15:15:34 +0200 Subject: [PATCH 52/61] e2e tests enhancements - remove deprecated use of async node - fail if creating client returned nil - use ptr pkg instead of pointer package as its deprecated Signed-off-by: adrianc --- test/conformance/tests/init.go | 3 +++ test/e2e/e2e_tests_suite_test.go | 8 +++----- test/e2e/sriovoperatornodepolicy_test.go | 2 ++ test/util/clean/clean.go | 4 ++++ test/validation/tests/test_validation.go | 19 ++++++++++--------- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/test/conformance/tests/init.go b/test/conformance/tests/init.go index 56b836dd9..99458e8dc 100644 --- a/test/conformance/tests/init.go +++ b/test/conformance/tests/init.go @@ -18,4 +18,7 @@ func init() { } clients = testclient.New("") + if clients == nil { + panic("failed package init, failed to create ClientSet") + } } diff --git a/test/e2e/e2e_tests_suite_test.go b/test/e2e/e2e_tests_suite_test.go index d6c132d14..920def35a 100644 --- a/test/e2e/e2e_tests_suite_test.go +++ b/test/e2e/e2e_tests_suite_test.go @@ -13,7 +13,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -55,7 +55,7 @@ func TestSriovTests(t *testing.T) { var sriovIface *sriovnetworkv1.InterfaceExt -var _ = BeforeSuite(func(done Done) { +var _ = BeforeSuite(func() { logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) // Go to project root directory @@ -64,7 +64,7 @@ var _ = BeforeSuite(func(done Done) { By("bootstrapping test environment") testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("config", "crd", "bases"), filepath.Join("test", "util", "crds")}, - UseExistingCluster: pointer.BoolPtr(true), + UseExistingCluster: ptr.To[bool](true), } var err error @@ -102,8 +102,6 @@ var _ = BeforeSuite(func(done Done) { doneNetNsSet = make(chan error, 1) go netns.SetPfVfLinkNetNs(testPciDev, testNsPath, devPollInterval, quitNetNsSet, doneNetNsSet) } - - close(done) }) var _ = AfterSuite(func() { diff --git a/test/e2e/sriovoperatornodepolicy_test.go b/test/e2e/sriovoperatornodepolicy_test.go index 891c06d12..ba2ec5e64 100644 --- a/test/e2e/sriovoperatornodepolicy_test.go +++ b/test/e2e/sriovoperatornodepolicy_test.go @@ -28,6 +28,8 @@ var _ = Describe("Operator", func() { execute.BeforeAll(func() { clients := testclient.New("") + Expect(clients).ToNot(BeNil()) + Eventually(func() *cluster.EnabledNodes { sriovInfos, _ = cluster.DiscoverSriov(clients, testNamespace) return sriovInfos diff --git a/test/util/clean/clean.go b/test/util/clean/clean.go index 74e6b13d3..fbc1ae1c4 100644 --- a/test/util/clean/clean.go +++ b/test/util/clean/clean.go @@ -20,6 +20,10 @@ func All() error { operatorNamespace = "openshift-sriov-network-operator" } clients := client.New("") + if clients == nil { + return fmt.Errorf("failed to create ClientSet") + } + if RestoreNodeDrainState { err := cluster.SetDisableNodeDrainState(clients, operatorNamespace, false) if err != nil { diff --git a/test/validation/tests/test_validation.go b/test/validation/tests/test_validation.go index 0df4fefb9..4c7980389 100644 --- a/test/validation/tests/test_validation.go +++ b/test/validation/tests/test_validation.go @@ -24,15 +24,6 @@ var ( operatorNamespace string ) -func init() { - operatorNamespace = os.Getenv("OPERATOR_NAMESPACE") - if operatorNamespace == "" { - operatorNamespace = "openshift-sriov-network-operator" - } - - clients = testclient.New("") -} - const ( sriovOperatorDeploymentName = "sriov-network-operator" // SriovNetworkNodePolicies contains the name of the sriov network node policies CRD @@ -45,6 +36,16 @@ const ( sriovOperatorConfigs = "sriovoperatorconfigs.sriovnetwork.openshift.io" ) +var _ = BeforeSuite(func() { + operatorNamespace = os.Getenv("OPERATOR_NAMESPACE") + if operatorNamespace == "" { + operatorNamespace = "openshift-sriov-network-operator" + } + + clients = testclient.New("") + Expect(clients).ToNot(BeNil()) +}) + var _ = Describe("validation", func() { Context("sriov", func() { From ddf5eb8490c6183b34898c805ef5fec58901c2cb Mon Sep 17 00:00:00 2001 From: Ivan Kolodiazhnyi Date: Fri, 17 Nov 2023 16:50:50 +0200 Subject: [PATCH 53/61] Refactor render of SR-IOV Device plugin We need to render SR-IOV Device plugin daemonset in the same way in all controllers. --- controllers/helper.go | 169 ++++++++++++++++++ .../sriovnetworknodepolicy_controller.go | 157 +--------------- controllers/sriovoperatorconfig_controller.go | 46 ++--- .../sriovoperatorconfig_controller_test.go | 18 ++ pkg/consts/constants.go | 2 + test/util/util.go | 2 +- 6 files changed, 210 insertions(+), 184 deletions(-) diff --git a/controllers/helper.go b/controllers/helper.go index f36ce44bc..0b0ac6c27 100644 --- a/controllers/helper.go +++ b/controllers/helper.go @@ -18,11 +18,27 @@ package controllers import ( "bytes" + "context" "encoding/json" + "fmt" "os" "strings" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/errors" + uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + kscheme "k8s.io/client-go/kubernetes/scheme" + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/log" + + sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apply" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" ) var webhooks = map[string](string){ @@ -62,3 +78,156 @@ func GetDefaultNodeSelector() map[string]string { return map[string]string{"node-role.kubernetes.io/worker": "", "kubernetes.io/os": "linux"} } + +func syncPluginDaemonObjs(ctx context.Context, client k8sclient.Client, scheme *runtime.Scheme, dp *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList) error { + logger := log.Log.WithName("syncPluginDaemonObjs") + logger.V(1).Info("Start to sync sriov daemons objects") + + // render plugin manifests + data := render.MakeRenderData() + data.Data["Namespace"] = namespace + data.Data["SRIOVDevicePluginImage"] = os.Getenv("SRIOV_DEVICE_PLUGIN_IMAGE") + data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") + data.Data["ResourcePrefix"] = os.Getenv("RESOURCE_PREFIX") + data.Data["ImagePullSecrets"] = GetImagePullSecrets() + data.Data["NodeSelectorField"] = GetDefaultNodeSelector() + + defaultConfig := &sriovnetworkv1.SriovOperatorConfig{} + err := client.Get(ctx, types.NamespacedName{ + Name: constants.DefaultConfigName, Namespace: namespace}, defaultConfig) + if err != nil { + return err + } + data.Data["UseCDI"] = defaultConfig.Spec.UseCDI + objs, err := renderDsForCR(constants.PluginPath, &data) + if err != nil { + logger.Error(err, "Fail to render SR-IoV manifests") + return err + } + + if len(pl.Items) < 2 { + for _, obj := range objs { + err := deleteK8sResource(ctx, client, obj) + if err != nil { + return err + } + } + return nil + } + + // Sync DaemonSets + for _, obj := range objs { + if obj.GetKind() == constants.DaemonSet && len(defaultConfig.Spec.ConfigDaemonNodeSelector) > 0 { + scheme := kscheme.Scheme + ds := &appsv1.DaemonSet{} + err = scheme.Convert(obj, ds, nil) + if err != nil { + logger.Error(err, "Fail to convert to DaemonSet") + return err + } + ds.Spec.Template.Spec.NodeSelector = defaultConfig.Spec.ConfigDaemonNodeSelector + err = scheme.Convert(ds, obj, nil) + if err != nil { + logger.Error(err, "Fail to convert to Unstructured") + return err + } + } + err = syncDsObject(ctx, client, scheme, dp, pl, obj) + if err != nil { + logger.Error(err, "Couldn't sync SR-IoV daemons objects") + return err + } + } + + return nil +} + +func deleteK8sResource(ctx context.Context, client k8sclient.Client, in *uns.Unstructured) error { + if err := apply.DeleteObject(ctx, client, in); err != nil { + return fmt.Errorf("failed to delete object %v with err: %v", in, err) + } + return nil +} + +func syncDsObject(ctx context.Context, client k8sclient.Client, scheme *runtime.Scheme, dp *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList, obj *uns.Unstructured) error { + logger := log.Log.WithName("syncDsObject") + kind := obj.GetKind() + logger.V(1).Info("Start to sync Objects", "Kind", kind) + switch kind { + case constants.ServiceAccount, constants.Role, constants.RoleBinding: + if err := controllerutil.SetControllerReference(dp, obj, scheme); err != nil { + return err + } + if err := apply.ApplyObject(ctx, client, obj); err != nil { + logger.Error(err, "Fail to sync", "Kind", kind) + return err + } + case constants.DaemonSet: + ds := &appsv1.DaemonSet{} + err := scheme.Convert(obj, ds, nil) + if err != nil { + logger.Error(err, "Fail to convert to DaemonSet") + return err + } + err = syncDaemonSet(ctx, client, scheme, dp, pl, ds) + if err != nil { + logger.Error(err, "Fail to sync DaemonSet", "Namespace", ds.Namespace, "Name", ds.Name) + return err + } + } + return nil +} + +func syncDaemonSet(ctx context.Context, client k8sclient.Client, scheme *runtime.Scheme, cr *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList, in *appsv1.DaemonSet) error { + logger := log.Log.WithName("syncDaemonSet") + logger.V(1).Info("Start to sync DaemonSet", "Namespace", in.Namespace, "Name", in.Name) + var err error + + if pl != nil { + if err = setDsNodeAffinity(pl, in); err != nil { + return err + } + } + if err = controllerutil.SetControllerReference(cr, in, scheme); err != nil { + return err + } + ds := &appsv1.DaemonSet{} + err = client.Get(ctx, types.NamespacedName{Namespace: in.Namespace, Name: in.Name}, ds) + if err != nil { + if errors.IsNotFound(err) { + logger.V(1).Info("Created DaemonSet", in.Namespace, in.Name) + err = client.Create(ctx, in) + if err != nil { + logger.Error(err, "Fail to create Daemonset", "Namespace", in.Namespace, "Name", in.Name) + return err + } + } else { + logger.Error(err, "Fail to get Daemonset", "Namespace", in.Namespace, "Name", in.Name) + return err + } + } else { + logger.V(1).Info("DaemonSet already exists, updating") + // DeepDerivative checks for changes only comparing non-zero fields in the source struct. + // This skips default values added by the api server. + // References in https://github.com/kubernetes-sigs/kubebuilder/issues/592#issuecomment-625738183 + if equality.Semantic.DeepDerivative(in.Spec, ds.Spec) { + // DeepDerivative has issue detecting nodeAffinity change + // https://bugzilla.redhat.com/show_bug.cgi?id=1914066 + // DeepDerivative doesn't detect changes in containers args section + // This code should be fixed both with NodeAffinity comparation + if equality.Semantic.DeepEqual(in.Spec.Template.Spec.Affinity.NodeAffinity, + ds.Spec.Template.Spec.Affinity.NodeAffinity) && + equality.Semantic.DeepEqual(in.Spec.Template.Spec.Containers[0].Args, + ds.Spec.Template.Spec.Containers[0].Args) { + logger.V(1).Info("Daemonset spec did not change, not updating") + return nil + } + } + err = client.Update(ctx, in) + if err != nil { + logger.Error(err, "Fail to update DaemonSet", "Namespace", in.Namespace, "Name", in.Name) + return err + } + } + return nil +} diff --git a/controllers/sriovnetworknodepolicy_controller.go b/controllers/sriovnetworknodepolicy_controller.go index 6f7cb44d1..14acc9a8d 100644 --- a/controllers/sriovnetworknodepolicy_controller.go +++ b/controllers/sriovnetworknodepolicy_controller.go @@ -20,13 +20,10 @@ import ( "context" "encoding/json" "fmt" - "os" "sort" "strings" "time" - utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" - errs "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -36,7 +33,6 @@ import ( uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - kscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/util/workqueue" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -46,10 +42,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" + utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + dptypes "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apply" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" ) @@ -153,7 +150,7 @@ func (r *SriovNetworkNodePolicyReconciler) Reconcile(ctx context.Context, req ct return reconcile.Result{}, err } // Render and sync Daemon objects - if err = r.syncPluginDaemonObjs(ctx, defaultOpConf, defaultPolicy, policyList); err != nil { + if err = syncPluginDaemonObjs(ctx, r.Client, r.Scheme, defaultPolicy, policyList); err != nil { return reconcile.Result{}, err } @@ -361,152 +358,6 @@ func (r *SriovNetworkNodePolicyReconciler) syncSriovNetworkNodeState(ctx context return nil } -func (r *SriovNetworkNodePolicyReconciler) syncPluginDaemonObjs(ctx context.Context, operatorConfig *sriovnetworkv1.SriovOperatorConfig, dp *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList) error { - logger := log.Log.WithName("syncPluginDaemonObjs") - logger.V(1).Info("Start to sync sriov daemons objects") - - // render plugin manifests - data := render.MakeRenderData() - data.Data["Namespace"] = namespace - data.Data["SRIOVDevicePluginImage"] = os.Getenv("SRIOV_DEVICE_PLUGIN_IMAGE") - data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") - data.Data["ResourcePrefix"] = os.Getenv("RESOURCE_PREFIX") - data.Data["ImagePullSecrets"] = GetImagePullSecrets() - data.Data["NodeSelectorField"] = GetDefaultNodeSelector() - data.Data["UseCDI"] = operatorConfig.Spec.UseCDI - - objs, err := renderDsForCR(constants.PluginPath, &data) - if err != nil { - logger.Error(err, "Fail to render SR-IoV manifests") - return err - } - - defaultConfig := &sriovnetworkv1.SriovOperatorConfig{} - err = r.Get(ctx, types.NamespacedName{ - Name: constants.DefaultConfigName, Namespace: namespace}, defaultConfig) - if err != nil { - return err - } - - if len(pl.Items) < 2 { - for _, obj := range objs { - err := r.deleteK8sResource(ctx, obj) - if err != nil { - return err - } - } - return nil - } - - // Sync DaemonSets - for _, obj := range objs { - if obj.GetKind() == constants.DaemonSet && len(defaultConfig.Spec.ConfigDaemonNodeSelector) > 0 { - scheme := kscheme.Scheme - ds := &appsv1.DaemonSet{} - err = scheme.Convert(obj, ds, nil) - if err != nil { - logger.Error(err, "Fail to convert to DaemonSet") - return err - } - ds.Spec.Template.Spec.NodeSelector = defaultConfig.Spec.ConfigDaemonNodeSelector - err = scheme.Convert(ds, obj, nil) - if err != nil { - logger.Error(err, "Fail to convert to Unstructured") - return err - } - } - err = r.syncDsObject(ctx, dp, pl, obj) - if err != nil { - logger.Error(err, "Couldn't sync SR-IoV daemons objects") - return err - } - } - - return nil -} - -func (r *SriovNetworkNodePolicyReconciler) deleteK8sResource(ctx context.Context, in *uns.Unstructured) error { - if err := apply.DeleteObject(ctx, r.Client, in); err != nil { - return fmt.Errorf("failed to delete object %v with err: %v", in, err) - } - return nil -} - -func (r *SriovNetworkNodePolicyReconciler) syncDsObject(ctx context.Context, dp *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList, obj *uns.Unstructured) error { - logger := log.Log.WithName("syncDsObject") - kind := obj.GetKind() - logger.V(1).Info("Start to sync Objects", "Kind", kind) - switch kind { - case "ServiceAccount", "Role", "RoleBinding": - if err := controllerutil.SetControllerReference(dp, obj, r.Scheme); err != nil { - return err - } - if err := apply.ApplyObject(ctx, r.Client, obj); err != nil { - logger.Error(err, "Fail to sync", "Kind", kind) - return err - } - case constants.DaemonSet: - ds := &appsv1.DaemonSet{} - err := r.Scheme.Convert(obj, ds, nil) - r.syncDaemonSet(ctx, dp, pl, ds) - if err != nil { - logger.Error(err, "Fail to sync DaemonSet", "Namespace", ds.Namespace, "Name", ds.Name) - return err - } - } - return nil -} - -func (r *SriovNetworkNodePolicyReconciler) syncDaemonSet(ctx context.Context, cr *sriovnetworkv1.SriovNetworkNodePolicy, pl *sriovnetworkv1.SriovNetworkNodePolicyList, in *appsv1.DaemonSet) error { - logger := log.Log.WithName("syncDaemonSet") - logger.V(1).Info("Start to sync DaemonSet", "Namespace", in.Namespace, "Name", in.Name) - var err error - - if pl != nil { - if err = setDsNodeAffinity(pl, in); err != nil { - return err - } - } - if err = controllerutil.SetControllerReference(cr, in, r.Scheme); err != nil { - return err - } - ds := &appsv1.DaemonSet{} - err = r.Get(ctx, types.NamespacedName{Namespace: in.Namespace, Name: in.Name}, ds) - if err != nil { - if errors.IsNotFound(err) { - logger.Info("Created DaemonSet", in.Namespace, in.Name) - err = r.Create(ctx, in) - if err != nil { - logger.Error(err, "Fail to create Daemonset", "Namespace", in.Namespace, "Name", in.Name) - return err - } - } else { - logger.Error(err, "Fail to get Daemonset", "Namespace", in.Namespace, "Name", in.Name) - return err - } - } else { - logger.V(1).Info("DaemonSet already exists, updating") - // DeepDerivative checks for changes only comparing non zero fields in the source struct. - // This skips default values added by the api server. - // References in https://github.com/kubernetes-sigs/kubebuilder/issues/592#issuecomment-625738183 - if equality.Semantic.DeepDerivative(in.Spec, ds.Spec) { - // DeepDerivative has issue detecting nodeAffinity change - // https://bugzilla.redhat.com/show_bug.cgi?id=1914066 - if equality.Semantic.DeepEqual(in.Spec.Template.Spec.Affinity.NodeAffinity, - ds.Spec.Template.Spec.Affinity.NodeAffinity) { - logger.V(1).Info("Daemonset spec did not change, not updating") - return nil - } - } - err = r.Update(ctx, in) - if err != nil { - logger.Error(err, "Fail to update DaemonSet", "Namespace", in.Namespace, "Name", in.Name) - return err - } - } - return nil -} - func setDsNodeAffinity(pl *sriovnetworkv1.SriovNetworkNodePolicyList, ds *appsv1.DaemonSet) error { terms := nodeSelectorTermsForPolicyList(pl.Items) if len(terms) > 0 { @@ -557,7 +408,7 @@ func renderDsForCR(path string, data *render.RenderData) ([]*uns.Unstructured, e objs, err := render.RenderDir(path, data) if err != nil { - return nil, errs.Wrap(err, "failed to render OpenShiftSRIOV Network manifests") + return nil, errs.Wrap(err, "failed to render SR-IOV Network Operator manifests") } return objs, nil } diff --git a/controllers/sriovoperatorconfig_controller.go b/controllers/sriovoperatorconfig_controller.go index 3eff3857a..d6fe28e78 100644 --- a/controllers/sriovoperatorconfig_controller.go +++ b/controllers/sriovoperatorconfig_controller.go @@ -109,6 +109,21 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. return reconcile.Result{}, err } + // Fetch the SriovNetworkNodePolicyList + policyList := &sriovnetworkv1.SriovNetworkNodePolicyList{} + err = r.List(ctx, policyList, &client.ListOptions{}) + if err != nil { + // Error reading the object - requeue the request. + return reconcile.Result{}, err + } + + defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} + err = r.Get(ctx, types.NamespacedName{Name: consts.DefaultPolicyName, Namespace: namespace}, defaultPolicy) + if err != nil { + // Error reading the object - requeue the request. + return reconcile.Result{}, err + } + if req.Namespace != namespace { return reconcile.Result{}, nil } @@ -123,7 +138,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. return reconcile.Result{}, err } - if err = r.syncPluginDaemonSet(ctx, defaultConfig); err != nil { + if err = syncPluginDaemonObjs(ctx, r.Client, r.Scheme, defaultPolicy, policyList); err != nil { return reconcile.Result{}, err } @@ -152,35 +167,6 @@ func (r *SriovOperatorConfigReconciler) SetupWithManager(mgr ctrl.Manager) error Complete(r) } -func (r *SriovOperatorConfigReconciler) syncPluginDaemonSet(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig) error { - logger := log.Log.WithName("syncConfigDaemonset") - logger.V(1).Info("Start to sync SRIOV plugin daemonsets nodeSelector") - ds := &appsv1.DaemonSet{} - - name := "sriov-device-plugin" - - err := r.Client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, ds) - if err != nil { - if apierrors.IsNotFound(err) { - return nil - } - logger.Error(err, "Couldn't get daemonset", "name", name) - return err - } - if len(dc.Spec.ConfigDaemonNodeSelector) == 0 { - ds.Spec.Template.Spec.NodeSelector = GetDefaultNodeSelector() - } else { - ds.Spec.Template.Spec.NodeSelector = dc.Spec.ConfigDaemonNodeSelector - } - err = r.Client.Update(ctx, ds) - if err != nil { - logger.Error(err, "Couldn't update daemonset", "name", name) - return err - } - - return nil -} - func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig) error { logger := log.Log.WithName("syncConfigDaemonset") logger.V(1).Info("Start to sync config daemonset") diff --git a/controllers/sriovoperatorconfig_controller_test.go b/controllers/sriovoperatorconfig_controller_test.go index c925324b9..70ec3fd07 100644 --- a/controllers/sriovoperatorconfig_controller_test.go +++ b/controllers/sriovoperatorconfig_controller_test.go @@ -11,11 +11,29 @@ import ( . "github.com/onsi/gomega" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" util "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" ) var _ = Describe("Operator", func() { var config *sriovnetworkv1.SriovOperatorConfig + BeforeEach(func() { + defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} + defaultPolicy.SetNamespace(namespace) + defaultPolicy.SetName(constants.DefaultPolicyName) + defaultPolicy.Spec = sriovnetworkv1.SriovNetworkNodePolicySpec{ + NumVfs: 0, + NodeSelector: make(map[string]string), + NicSelector: sriovnetworkv1.SriovNetworkNicSelector{}, + } + Expect(k8sClient.Create(goctx.TODO(), defaultPolicy)).Should(Succeed()) + }) + AfterEach(func() { + defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} + defaultPolicy.SetNamespace(namespace) + defaultPolicy.SetName(constants.DefaultPolicyName) + Expect(k8sClient.Delete(goctx.TODO(), defaultPolicy)).Should(Succeed()) + }) // BeforeEach(func() { // config = &sriovnetworkv1.SriovOperatorConfig{} // config.SetNamespace(testNamespace) diff --git a/pkg/consts/constants.go b/pkg/consts/constants.go index d3ddd3f6d..f1edc903f 100644 --- a/pkg/consts/constants.go +++ b/pkg/consts/constants.go @@ -30,6 +30,8 @@ const ( DefaultPolicyName = "default" ConfigMapName = "device-plugin-config" DaemonSet = "DaemonSet" + Role = "Role" + RoleBinding = "RoleBinding" ServiceAccount = "ServiceAccount" DPConfigFileName = "config.json" OVSHWOLMachineConfigNameSuffix = "ovs-hw-offload" diff --git a/test/util/util.go b/test/util/util.go index 0194fb5e9..096962b3c 100644 --- a/test/util/util.go +++ b/test/util/util.go @@ -26,7 +26,7 @@ import ( var ( RetryInterval = time.Second * 1 - APITimeout = time.Second * 10 + APITimeout = time.Second * 20 Timeout = time.Second * 60 CleanupRetryInterval = time.Second * 1 CleanupTimeout = time.Second * 5 From d739284c81f94c619c21696833a92df692f65342 Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 23 Jan 2024 15:16:33 +0200 Subject: [PATCH 54/61] Add wrapper for dputils package Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/lib/dputils/dputils.go | 78 +++++++++ .../internal/lib/dputils/mock/mock_dputils.go | 164 ++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 pkg/host/internal/lib/dputils/dputils.go create mode 100644 pkg/host/internal/lib/dputils/mock/mock_dputils.go diff --git a/pkg/host/internal/lib/dputils/dputils.go b/pkg/host/internal/lib/dputils/dputils.go new file mode 100644 index 000000000..ef503a851 --- /dev/null +++ b/pkg/host/internal/lib/dputils/dputils.go @@ -0,0 +1,78 @@ +package dputils + +import ( + dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" +) + +func New() DPUtilsLib { + return &libWrapper{} +} + +//go:generate ../../../../../bin/mockgen -destination mock/mock_dputils.go -source dputils.go +type DPUtilsLib interface { + // GetNetNames returns host net interface names as string for a PCI device from its pci address + GetNetNames(pciAddr string) ([]string, error) + // GetDriverName returns current driver attached to a pci device from its pci address + GetDriverName(pciAddr string) (string, error) + // GetVFID returns VF ID index (within specific PF) based on PCI address + GetVFID(pciAddr string) (vfID int, err error) + // IsSriovVF check if a pci device has link to a PF + IsSriovVF(pciAddr string) bool + // IsSriovPF check if a pci device SRIOV capable given its pci address + IsSriovPF(pciAddr string) bool + // GetSriovVFcapacity returns SRIOV VF capacity + GetSriovVFcapacity(pf string) int + // GetVFconfigured returns number of VF configured for a PF + GetVFconfigured(pf string) int + // SriovConfigured returns true if sriov_numvfs reads > 0 else false + SriovConfigured(addr string) bool + // GetVFList returns a List containing PCI addr for all VF discovered in a given PF + GetVFList(pf string) (vfList []string, err error) +} + +type libWrapper struct{} + +// GetNetNames returns host net interface names as string for a PCI device from its pci address +func (w *libWrapper) GetNetNames(pciAddr string) ([]string, error) { + return dputils.GetNetNames(pciAddr) +} + +// GetDriverName returns current driver attached to a pci device from its pci address +func (w *libWrapper) GetDriverName(pciAddr string) (string, error) { + return dputils.GetDriverName(pciAddr) +} + +// GetVFID returns VF ID index (within specific PF) based on PCI address +func (w *libWrapper) GetVFID(pciAddr string) (vfID int, err error) { + return dputils.GetVFID(pciAddr) +} + +// IsSriovVF check if a pci device has link to a PF +func (w *libWrapper) IsSriovVF(pciAddr string) bool { + return dputils.IsSriovVF(pciAddr) +} + +// IsSriovPF check if a pci device SRIOV capable given its pci address +func (w *libWrapper) IsSriovPF(pciAddr string) bool { + return dputils.IsSriovPF(pciAddr) +} + +// GetSriovVFcapacity returns SRIOV VF capacity +func (w *libWrapper) GetSriovVFcapacity(pf string) int { + return dputils.GetSriovVFcapacity(pf) +} + +// GetVFconfigured returns number of VF configured for a PF +func (w *libWrapper) GetVFconfigured(pf string) int { + return dputils.GetVFconfigured(pf) +} + +// SriovConfigured returns true if sriov_numvfs reads > 0 else false +func (w *libWrapper) SriovConfigured(addr string) bool { + return dputils.SriovConfigured(addr) +} + +// GetVFList returns a List containing PCI addr for all VF discovered in a given PF +func (w *libWrapper) GetVFList(pf string) (vfList []string, err error) { + return dputils.GetVFList(pf) +} diff --git a/pkg/host/internal/lib/dputils/mock/mock_dputils.go b/pkg/host/internal/lib/dputils/mock/mock_dputils.go new file mode 100644 index 000000000..de32180f2 --- /dev/null +++ b/pkg/host/internal/lib/dputils/mock/mock_dputils.go @@ -0,0 +1,164 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: dputils.go + +// Package mock_dputils is a generated GoMock package. +package mock_dputils + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockDPUtilsLib is a mock of DPUtilsLib interface. +type MockDPUtilsLib struct { + ctrl *gomock.Controller + recorder *MockDPUtilsLibMockRecorder +} + +// MockDPUtilsLibMockRecorder is the mock recorder for MockDPUtilsLib. +type MockDPUtilsLibMockRecorder struct { + mock *MockDPUtilsLib +} + +// NewMockDPUtilsLib creates a new mock instance. +func NewMockDPUtilsLib(ctrl *gomock.Controller) *MockDPUtilsLib { + mock := &MockDPUtilsLib{ctrl: ctrl} + mock.recorder = &MockDPUtilsLibMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDPUtilsLib) EXPECT() *MockDPUtilsLibMockRecorder { + return m.recorder +} + +// GetDriverName mocks base method. +func (m *MockDPUtilsLib) GetDriverName(pciAddr string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDriverName", pciAddr) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDriverName indicates an expected call of GetDriverName. +func (mr *MockDPUtilsLibMockRecorder) GetDriverName(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDriverName", reflect.TypeOf((*MockDPUtilsLib)(nil).GetDriverName), pciAddr) +} + +// GetNetNames mocks base method. +func (m *MockDPUtilsLib) GetNetNames(pciAddr string) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNetNames", pciAddr) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetNetNames indicates an expected call of GetNetNames. +func (mr *MockDPUtilsLibMockRecorder) GetNetNames(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetNames", reflect.TypeOf((*MockDPUtilsLib)(nil).GetNetNames), pciAddr) +} + +// GetSriovVFcapacity mocks base method. +func (m *MockDPUtilsLib) GetSriovVFcapacity(pf string) int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSriovVFcapacity", pf) + ret0, _ := ret[0].(int) + return ret0 +} + +// GetSriovVFcapacity indicates an expected call of GetSriovVFcapacity. +func (mr *MockDPUtilsLibMockRecorder) GetSriovVFcapacity(pf interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSriovVFcapacity", reflect.TypeOf((*MockDPUtilsLib)(nil).GetSriovVFcapacity), pf) +} + +// GetVFID mocks base method. +func (m *MockDPUtilsLib) GetVFID(pciAddr string) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVFID", pciAddr) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetVFID indicates an expected call of GetVFID. +func (mr *MockDPUtilsLibMockRecorder) GetVFID(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVFID", reflect.TypeOf((*MockDPUtilsLib)(nil).GetVFID), pciAddr) +} + +// GetVFList mocks base method. +func (m *MockDPUtilsLib) GetVFList(pf string) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVFList", pf) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetVFList indicates an expected call of GetVFList. +func (mr *MockDPUtilsLibMockRecorder) GetVFList(pf interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVFList", reflect.TypeOf((*MockDPUtilsLib)(nil).GetVFList), pf) +} + +// GetVFconfigured mocks base method. +func (m *MockDPUtilsLib) GetVFconfigured(pf string) int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVFconfigured", pf) + ret0, _ := ret[0].(int) + return ret0 +} + +// GetVFconfigured indicates an expected call of GetVFconfigured. +func (mr *MockDPUtilsLibMockRecorder) GetVFconfigured(pf interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVFconfigured", reflect.TypeOf((*MockDPUtilsLib)(nil).GetVFconfigured), pf) +} + +// IsSriovPF mocks base method. +func (m *MockDPUtilsLib) IsSriovPF(pciAddr string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSriovPF", pciAddr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSriovPF indicates an expected call of IsSriovPF. +func (mr *MockDPUtilsLibMockRecorder) IsSriovPF(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSriovPF", reflect.TypeOf((*MockDPUtilsLib)(nil).IsSriovPF), pciAddr) +} + +// IsSriovVF mocks base method. +func (m *MockDPUtilsLib) IsSriovVF(pciAddr string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSriovVF", pciAddr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSriovVF indicates an expected call of IsSriovVF. +func (mr *MockDPUtilsLibMockRecorder) IsSriovVF(pciAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSriovVF", reflect.TypeOf((*MockDPUtilsLib)(nil).IsSriovVF), pciAddr) +} + +// SriovConfigured mocks base method. +func (m *MockDPUtilsLib) SriovConfigured(addr string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SriovConfigured", addr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// SriovConfigured indicates an expected call of SriovConfigured. +func (mr *MockDPUtilsLibMockRecorder) SriovConfigured(addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SriovConfigured", reflect.TypeOf((*MockDPUtilsLib)(nil).SriovConfigured), addr) +} From a7a885a9a05efb4f190df2e56572da33d93c8e8e Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Tue, 23 Jan 2024 18:50:20 +0200 Subject: [PATCH 55/61] Use dputils wrapper in network and sriov packages Signed-off-by: Yury Kulazhenkov --- pkg/host/internal/network/network.go | 15 ++++++----- pkg/host/internal/sriov/sriov.go | 36 ++++++++++++++------------- pkg/host/internal/sriov/sriov_test.go | 29 +++++++++++---------- pkg/host/manager.go | 6 +++-- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/pkg/host/internal/network/network.go b/pkg/host/internal/network/network.go index 4f97b2634..f9ede5fc8 100644 --- a/pkg/host/internal/network/network.go +++ b/pkg/host/internal/network/network.go @@ -11,9 +11,8 @@ import ( "github.com/cenkalti/backoff" "sigs.k8s.io/controller-runtime/pkg/log" - dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + dputilsPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/dputils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" @@ -21,10 +20,14 @@ import ( type network struct { utilsHelper utils.CmdInterface + dputilsLib dputilsPkg.DPUtilsLib } -func New(utilsHelper utils.CmdInterface) types.NetworkInterface { - return &network{utilsHelper: utilsHelper} +func New(utilsHelper utils.CmdInterface, dputilsLib dputilsPkg.DPUtilsLib) types.NetworkInterface { + return &network{ + utilsHelper: utilsHelper, + dputilsLib: dputilsLib, + } } // TryToGetVirtualInterfaceName get the interface name of a virtio interface @@ -61,7 +64,7 @@ func (n *network) TryToGetVirtualInterfaceName(pciAddr string) string { } func (n *network) TryGetInterfaceName(pciAddr string) string { - names, err := dputils.GetNetNames(pciAddr) + names, err := n.dputilsLib.GetNetNames(pciAddr) if err != nil || len(names) < 1 { return "" } @@ -152,7 +155,7 @@ func (n *network) SetNetdevMTU(pciAddr string, mtu int) error { } b := backoff.NewConstantBackOff(1 * time.Second) err := backoff.Retry(func() error { - ifaceName, err := dputils.GetNetNames(pciAddr) + ifaceName, err := n.dputilsLib.GetNetNames(pciAddr) if err != nil { log.Log.Error(err, "SetNetdevMTU(): fail to get interface name", "device", pciAddr) return err diff --git a/pkg/host/internal/sriov/sriov.go b/pkg/host/internal/sriov/sriov.go index 9541c8bcd..3d8d0a48c 100644 --- a/pkg/host/internal/sriov/sriov.go +++ b/pkg/host/internal/sriov/sriov.go @@ -15,10 +15,9 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/log" - dputils "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" - sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + dputilsPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/dputils" netlinkPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/store" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" @@ -33,18 +32,21 @@ type sriov struct { networkHelper types.NetworkInterface udevHelper types.UdevInterface netlinkLib netlinkPkg.NetlinkLib + dputilsLib dputilsPkg.DPUtilsLib } func New(utilsHelper utils.CmdInterface, kernelHelper types.KernelInterface, networkHelper types.NetworkInterface, udevHelper types.UdevInterface, - netlinkLib netlinkPkg.NetlinkLib) types.SriovInterface { + netlinkLib netlinkPkg.NetlinkLib, + dputilsLib dputilsPkg.DPUtilsLib) types.SriovInterface { return &sriov{utilsHelper: utilsHelper, kernelHelper: kernelHelper, networkHelper: networkHelper, udevHelper: udevHelper, netlinkLib: netlinkLib, + dputilsLib: dputilsLib, } } @@ -94,11 +96,11 @@ func (s *sriov) ResetSriovDevice(ifaceStatus sriovnetworkv1.InterfaceExt) error } func (s *sriov) GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) sriovnetworkv1.VirtualFunction { - driver, err := dputils.GetDriverName(pciAddr) + driver, err := s.dputilsLib.GetDriverName(pciAddr) if err != nil { log.Log.Error(err, "getVfInfo(): unable to parse device driver", "device", pciAddr) } - id, err := dputils.GetVFID(pciAddr) + id, err := s.dputilsLib.GetVFID(pciAddr) if err != nil { log.Log.Error(err, "getVfInfo(): unable to get VF index", "device", pciAddr) } @@ -129,7 +131,7 @@ func (s *sriov) GetVfInfo(pciAddr string, devices []*ghw.PCIDevice) sriovnetwork func (s *sriov) SetVfGUID(vfAddr string, pfLink netlink.Link) error { log.Log.Info("SetVfGUID()", "vf", vfAddr) - vfID, err := dputils.GetVFID(vfAddr) + vfID, err := s.dputilsLib.GetVFID(vfAddr) if err != nil { log.Log.Error(err, "SetVfGUID(): unable to get VF id", "address", vfAddr) return err @@ -169,7 +171,7 @@ func (s *sriov) VFIsReady(pciAddr string) (netlink.Link, error) { func (s *sriov) SetVfAdminMac(vfAddr string, pfLink, vfLink netlink.Link) error { log.Log.Info("SetVfAdminMac()", "vf", vfAddr) - vfID, err := dputils.GetVFID(vfAddr) + vfID, err := s.dputilsLib.GetVFID(vfAddr) if err != nil { log.Log.Error(err, "SetVfAdminMac(): unable to get VF id", "address", vfAddr) return err @@ -210,17 +212,17 @@ func (s *sriov) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]sri // TODO: exclude devices used by host system - if dputils.IsSriovVF(device.Address) { + if s.dputilsLib.IsSriovVF(device.Address) { continue } - driver, err := dputils.GetDriverName(device.Address) + driver, err := s.dputilsLib.GetDriverName(device.Address) if err != nil { log.Log.Error(err, "DiscoverSriovDevices(): unable to parse device driver for device, skipping", "device", device) continue } - deviceNames, err := dputils.GetNetNames(device.Address) + deviceNames, err := s.dputilsLib.GetNetNames(device.Address) if err != nil { log.Log.Error(err, "DiscoverSriovDevices(): unable to get device names for device, skipping", "device", device) continue @@ -263,15 +265,15 @@ func (s *sriov) DiscoverSriovDevices(storeManager store.ManagerInterface) ([]sri } } - if dputils.IsSriovPF(device.Address) { - iface.TotalVfs = dputils.GetSriovVFcapacity(device.Address) - iface.NumVfs = dputils.GetVFconfigured(device.Address) + if s.dputilsLib.IsSriovPF(device.Address) { + iface.TotalVfs = s.dputilsLib.GetSriovVFcapacity(device.Address) + iface.NumVfs = s.dputilsLib.GetVFconfigured(device.Address) if iface.EswitchMode, err = s.GetNicSriovMode(device.Address); err != nil { log.Log.Error(err, "DiscoverSriovDevices(): warning, unable to get device eswitch mode", "device", device.Address) } - if dputils.SriovConfigured(device.Address) { - vfs, err := dputils.GetVFList(device.Address) + if s.dputilsLib.SriovConfigured(device.Address) { + vfs, err := s.dputilsLib.GetVFList(device.Address) if err != nil { log.Log.Error(err, "DiscoverSriovDevices(): unable to parse VFs for device, skipping", "device", device) @@ -340,7 +342,7 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * } // Config VFs if iface.NumVfs > 0 { - vfAddrs, err := dputils.GetVFList(iface.PciAddress) + vfAddrs, err := s.dputilsLib.GetVFList(iface.PciAddress) if err != nil { log.Log.Error(err, "configSriovDevice(): unable to parse VFs for device", "device", iface.PciAddress) } @@ -353,7 +355,7 @@ func (s *sriov) ConfigSriovDevice(iface *sriovnetworkv1.Interface, ifaceStatus * for _, addr := range vfAddrs { var group *sriovnetworkv1.VfGroup - vfID, err := dputils.GetVFID(addr) + vfID, err := s.dputilsLib.GetVFID(addr) if err != nil { log.Log.Error(err, "configSriovDevice(): unable to get VF id", "device", iface.PciAddress) return err diff --git a/pkg/host/internal/sriov/sriov_test.go b/pkg/host/internal/sriov/sriov_test.go index 8a87a6de6..b380c5644 100644 --- a/pkg/host/internal/sriov/sriov_test.go +++ b/pkg/host/internal/sriov/sriov_test.go @@ -11,6 +11,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + dputilsMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/dputils/mock" netlinkMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink/mock" hostMockPkg "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/mock" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/types" @@ -20,9 +21,10 @@ import ( var _ = Describe("SRIOV", func() { var ( - s types.SriovInterface - libMock *netlinkMockPkg.MockNetlinkLib - hostMock *hostMockPkg.MockHostManagerInterface + s types.SriovInterface + netlinkLibMock *netlinkMockPkg.MockNetlinkLib + dputilsLibMock *dputilsMockPkg.MockDPUtilsLib + hostMock *hostMockPkg.MockHostManagerInterface testCtrl *gomock.Controller @@ -30,9 +32,10 @@ var _ = Describe("SRIOV", func() { ) BeforeEach(func() { testCtrl = gomock.NewController(GinkgoT()) - libMock = netlinkMockPkg.NewMockNetlinkLib(testCtrl) + netlinkLibMock = netlinkMockPkg.NewMockNetlinkLib(testCtrl) + dputilsLibMock = dputilsMockPkg.NewMockDPUtilsLib(testCtrl) hostMock = hostMockPkg.NewMockHostManagerInterface(testCtrl) - s = New(nil, hostMock, hostMock, hostMock, libMock) + s = New(nil, hostMock, hostMock, hostMock, netlinkLibMock, dputilsLibMock) }) AfterEach(func() { @@ -55,7 +58,7 @@ var _ = Describe("SRIOV", func() { Context("GetNicSriovMode", func() { It("devlink returns info", func() { - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return( + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return( &netlink.DevlinkDevice{Attrs: netlink.DevlinkDevAttrs{Eswitch: netlink.DevlinkDevEswitchAttr{Mode: "switchdev"}}}, nil) mode, err := s.GetNicSriovMode("0000:d8:00.0") @@ -63,12 +66,12 @@ var _ = Describe("SRIOV", func() { Expect(mode).To(Equal("switchdev")) }) It("devlink returns error", func() { - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) _, err := s.GetNicSriovMode("0000:d8:00.0") Expect(err).To(MatchError(testError)) }) It("devlink not supported - fail to get name", func() { - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, syscall.ENODEV) + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, syscall.ENODEV) mode, err := s.GetNicSriovMode("0000:d8:00.0") Expect(err).NotTo(HaveOccurred()) Expect(mode).To(BeEmpty()) @@ -78,18 +81,18 @@ var _ = Describe("SRIOV", func() { Context("SetNicSriovMode", func() { It("set", func() { testDev := &netlink.DevlinkDevice{} - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) - libMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(nil) + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) + netlinkLibMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(nil) Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).NotTo(HaveOccurred()) }) It("fail to get dev", func() { - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(nil, testError) Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError)) }) It("fail to set mode", func() { testDev := &netlink.DevlinkDevice{} - libMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) - libMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(testError) + netlinkLibMock.EXPECT().DevLinkGetDeviceByName("pci", "0000:d8:00.0").Return(&netlink.DevlinkDevice{}, nil) + netlinkLibMock.EXPECT().DevLinkSetEswitchMode(testDev, "legacy").Return(testError) Expect(s.SetNicSriovMode("0000:d8:00.0", "legacy")).To(MatchError(testError)) }) }) diff --git a/pkg/host/manager.go b/pkg/host/manager.go index f883ffe06..83399ab90 100644 --- a/pkg/host/manager.go +++ b/pkg/host/manager.go @@ -2,6 +2,7 @@ package host import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/kernel" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/dputils" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/govdpa" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/lib/netlink" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/host/internal/network" @@ -36,11 +37,12 @@ type hostManager struct { } func NewHostManager(utilsInterface utils.CmdInterface) HostManagerInterface { + dpUtils := dputils.New() k := kernel.New(utilsInterface) - n := network.New(utilsInterface) + n := network.New(utilsInterface, dpUtils) sv := service.New(utilsInterface) u := udev.New(utilsInterface) - sr := sriov.New(utilsInterface, k, n, u, netlink.New()) + sr := sriov.New(utilsInterface, k, n, u, netlink.New(), dpUtils) v := vdpa.New(k, govdpa.New()) return &hostManager{ From 4d080def7940592fc29b4802836595e9260e475c Mon Sep 17 00:00:00 2001 From: Ivan Kolodiazhnyi Date: Tue, 30 Jan 2024 12:47:21 +0200 Subject: [PATCH 56/61] Use APITimeout and RetryInterval constant in tests --- .../sriovnetworkpoolconfig_controller_test.go | 3 +- .../sriovoperatorconfig_controller_test.go | 44 +++++++++---------- controllers/suite_test.go | 10 ++--- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/controllers/sriovnetworkpoolconfig_controller_test.go b/controllers/sriovnetworkpoolconfig_controller_test.go index b95f5edac..ff20c0535 100644 --- a/controllers/sriovnetworkpoolconfig_controller_test.go +++ b/controllers/sriovnetworkpoolconfig_controller_test.go @@ -16,6 +16,7 @@ import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" ) var _ = Describe("Operator", func() { @@ -65,7 +66,7 @@ var _ = Describe("Operator", func() { return err } return nil - }, timeout*3, interval).Should(Succeed()) + }, util.APITimeout*3, util.RetryInterval).Should(Succeed()) }) }) }) diff --git a/controllers/sriovoperatorconfig_controller_test.go b/controllers/sriovoperatorconfig_controller_test.go index 70ec3fd07..c36b2a91f 100644 --- a/controllers/sriovoperatorconfig_controller_test.go +++ b/controllers/sriovoperatorconfig_controller_test.go @@ -56,7 +56,7 @@ var _ = Describe("Operator", func() { Context("When is up", func() { JustBeforeEach(func() { config = &sriovnetworkv1.SriovOperatorConfig{} - err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) config.Spec = sriovnetworkv1.SriovOperatorConfigSpec{ EnableInjector: func() *bool { b := true; return &b }(), @@ -70,11 +70,11 @@ var _ = Describe("Operator", func() { It("should have webhook enable", func() { mutateCfg := &admv1.MutatingWebhookConfiguration{} - err := util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err := util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) validateCfg := &admv1.ValidatingWebhookConfiguration{} - err = util.WaitForNamespacedObject(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err = util.WaitForNamespacedObject(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) }) @@ -82,7 +82,7 @@ var _ = Describe("Operator", func() { func(dsName string) { // wait for sriov-network-operator to be ready daemonSet := &appsv1.DaemonSet{} - err := util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, dsName, interval, timeout) + err := util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, dsName, util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) }, Entry("operator-webhook", "operator-webhook"), @@ -93,7 +93,7 @@ var _ = Describe("Operator", func() { It("should be able to turn network-resources-injector on/off", func() { By("set disable to enableInjector") config := &sriovnetworkv1.SriovOperatorConfig{} - err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) *config.Spec.EnableInjector = false @@ -101,15 +101,15 @@ var _ = Describe("Operator", func() { Expect(err).NotTo(HaveOccurred()) daemonSet := &appsv1.DaemonSet{} - err = util.WaitForNamespacedObjectDeleted(daemonSet, k8sClient, testNamespace, "network-resources-injector", interval, timeout) + err = util.WaitForNamespacedObjectDeleted(daemonSet, k8sClient, testNamespace, "network-resources-injector", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) mutateCfg := &admv1.MutatingWebhookConfiguration{} - err = util.WaitForNamespacedObjectDeleted(mutateCfg, k8sClient, testNamespace, "network-resources-injector-config", interval, timeout) + err = util.WaitForNamespacedObjectDeleted(mutateCfg, k8sClient, testNamespace, "network-resources-injector-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) By("set enable to enableInjector") - err = util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err = util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) *config.Spec.EnableInjector = true @@ -117,11 +117,11 @@ var _ = Describe("Operator", func() { Expect(err).NotTo(HaveOccurred()) daemonSet = &appsv1.DaemonSet{} - err = util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, "network-resources-injector", interval, timeout) + err = util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, "network-resources-injector", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) mutateCfg = &admv1.MutatingWebhookConfiguration{} - err = util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "network-resources-injector-config", interval, timeout) + err = util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "network-resources-injector-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) }) @@ -129,7 +129,7 @@ var _ = Describe("Operator", func() { By("set disable to enableOperatorWebhook") config := &sriovnetworkv1.SriovOperatorConfig{} - err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) *config.Spec.EnableOperatorWebhook = false @@ -137,19 +137,19 @@ var _ = Describe("Operator", func() { Expect(err).NotTo(HaveOccurred()) daemonSet := &appsv1.DaemonSet{} - err = util.WaitForNamespacedObjectDeleted(daemonSet, k8sClient, testNamespace, "operator-webhook", interval, timeout) + err = util.WaitForNamespacedObjectDeleted(daemonSet, k8sClient, testNamespace, "operator-webhook", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) mutateCfg := &admv1.MutatingWebhookConfiguration{} - err = util.WaitForNamespacedObjectDeleted(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err = util.WaitForNamespacedObjectDeleted(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) validateCfg := &admv1.ValidatingWebhookConfiguration{} - err = util.WaitForNamespacedObjectDeleted(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err = util.WaitForNamespacedObjectDeleted(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) By("set disable to enableOperatorWebhook") - err = util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err = util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) *config.Spec.EnableOperatorWebhook = true @@ -157,22 +157,22 @@ var _ = Describe("Operator", func() { Expect(err).NotTo(HaveOccurred()) daemonSet = &appsv1.DaemonSet{} - err = util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, "operator-webhook", interval, timeout) + err = util.WaitForNamespacedObject(daemonSet, k8sClient, testNamespace, "operator-webhook", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) mutateCfg = &admv1.MutatingWebhookConfiguration{} - err = util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err = util.WaitForNamespacedObject(mutateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) validateCfg = &admv1.ValidatingWebhookConfiguration{} - err = util.WaitForNamespacedObject(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", interval, timeout) + err = util.WaitForNamespacedObject(validateCfg, k8sClient, testNamespace, "sriov-operator-webhook-config", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) }) It("should be able to update the node selector of sriov-network-config-daemon", func() { By("specify the configDaemonNodeSelector") config := &sriovnetworkv1.SriovOperatorConfig{} - err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) config.Spec.ConfigDaemonNodeSelector = map[string]string{"node-role.kubernetes.io/worker": ""} err = k8sClient.Update(goctx.TODO(), config) @@ -186,13 +186,13 @@ var _ = Describe("Operator", func() { return nil } return daemonSet.Spec.Template.Spec.NodeSelector - }, timeout*10, interval).Should(Equal(config.Spec.ConfigDaemonNodeSelector)) + }, util.APITimeout*10, util.RetryInterval).Should(Equal(config.Spec.ConfigDaemonNodeSelector)) }) It("should be able to do multiple updates to the node selector of sriov-network-config-daemon", func() { By("changing the configDaemonNodeSelector") config := &sriovnetworkv1.SriovOperatorConfig{} - err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", interval, timeout) + err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) config.Spec.ConfigDaemonNodeSelector = map[string]string{"labelA": "", "labelB": "", "labelC": ""} err = k8sClient.Update(goctx.TODO(), config) @@ -208,7 +208,7 @@ var _ = Describe("Operator", func() { return nil } return daemonSet.Spec.Template.Spec.NodeSelector - }, timeout*10, interval).Should(Equal(config.Spec.ConfigDaemonNodeSelector)) + }, util.APITimeout*10, util.RetryInterval).Should(Equal(config.Spec.ConfigDaemonNodeSelector)) }) }) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 6a9b1af5d..07bc9a7c1 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -46,6 +46,7 @@ import ( constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" mock_platforms "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/mock" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms/openshift" + "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -60,12 +61,7 @@ var ( ) // Define utility constants for object names and testing timeouts/durations and intervals. -const ( - testNamespace = "openshift-sriov-network-operator" - - timeout = time.Second * 10 - interval = time.Millisecond * 250 -) +const testNamespace = "openshift-sriov-network-operator" var _ = BeforeSuite(func() { logf.SetLogger(zap.New( @@ -221,7 +217,7 @@ var _ = AfterSuite(func() { if testEnv != nil { Eventually(func() error { return testEnv.Stop() - }, timeout, time.Second).ShouldNot(HaveOccurred()) + }, util.APITimeout, time.Second).ShouldNot(HaveOccurred()) } }) From da7011ab82f4ec23f5f7531b066b24503c6d5eec Mon Sep 17 00:00:00 2001 From: adrianc Date: Tue, 30 Jan 2024 15:40:58 +0200 Subject: [PATCH 57/61] move namespace to vars pkg Namespace variable is used in both controllers and daemon. Move it to vars pkg and use in both. Signed-off-by: adrianc --- controllers/helper.go | 7 +++---- controllers/sriovibnetwork_controller.go | 3 ++- controllers/sriovnetwork_controller.go | 3 ++- .../sriovnetworknodepolicy_controller.go | 17 ++++++++-------- .../sriovnetworknodepolicy_controller_test.go | 3 ++- controllers/sriovoperatorconfig_controller.go | 14 ++++++------- .../sriovoperatorconfig_controller_test.go | 5 +++-- pkg/daemon/daemon.go | 20 +++++++++---------- pkg/daemon/daemon_test.go | 12 +++++------ pkg/daemon/event_recorder.go | 2 +- pkg/daemon/writer.go | 4 ++-- pkg/vars/vars.go | 5 +++++ 12 files changed, 51 insertions(+), 44 deletions(-) diff --git a/controllers/helper.go b/controllers/helper.go index 0b0ac6c27..f0380f671 100644 --- a/controllers/helper.go +++ b/controllers/helper.go @@ -39,6 +39,7 @@ import ( "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apply" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/render" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) var webhooks = map[string](string){ @@ -55,8 +56,6 @@ const ( trueString = "true" ) -var namespace = os.Getenv("NAMESPACE") - func GetImagePullSecrets() []string { imagePullSecrets := os.Getenv("IMAGE_PULL_SECRETS") if imagePullSecrets != "" { @@ -85,7 +84,7 @@ func syncPluginDaemonObjs(ctx context.Context, client k8sclient.Client, scheme * // render plugin manifests data := render.MakeRenderData() - data.Data["Namespace"] = namespace + data.Data["Namespace"] = vars.Namespace data.Data["SRIOVDevicePluginImage"] = os.Getenv("SRIOV_DEVICE_PLUGIN_IMAGE") data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") data.Data["ResourcePrefix"] = os.Getenv("RESOURCE_PREFIX") @@ -94,7 +93,7 @@ func syncPluginDaemonObjs(ctx context.Context, client k8sclient.Client, scheme * defaultConfig := &sriovnetworkv1.SriovOperatorConfig{} err := client.Get(ctx, types.NamespacedName{ - Name: constants.DefaultConfigName, Namespace: namespace}, defaultConfig) + Name: constants.DefaultConfigName, Namespace: vars.Namespace}, defaultConfig) if err != nil { return err } diff --git a/controllers/sriovibnetwork_controller.go b/controllers/sriovibnetwork_controller.go index 0ffe5fba0..65b66f167 100644 --- a/controllers/sriovibnetwork_controller.go +++ b/controllers/sriovibnetwork_controller.go @@ -35,6 +35,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // SriovIBNetworkReconciler reconciles a SriovIBNetwork object @@ -58,7 +59,7 @@ type SriovIBNetworkReconciler struct { // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile func (r *SriovIBNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { // The SriovNetwork CR shall only be defined in operator namespace. - req.Namespace = namespace + req.Namespace = vars.Namespace reqLogger := log.FromContext(ctx).WithValues("sriovnetwork", req.NamespacedName) reqLogger.Info("Reconciling SriovIBNetwork") var err error diff --git a/controllers/sriovnetwork_controller.go b/controllers/sriovnetwork_controller.go index f89d524c1..7ef991e93 100644 --- a/controllers/sriovnetwork_controller.go +++ b/controllers/sriovnetwork_controller.go @@ -35,6 +35,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) // SriovNetworkReconciler reconciles a SriovNetwork object @@ -57,7 +58,7 @@ type SriovNetworkReconciler struct { // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile func (r *SriovNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - req.Namespace = namespace + req.Namespace = vars.Namespace reqLogger := log.FromContext(ctx).WithValues("sriovnetwork", req.NamespacedName) reqLogger.Info("Reconciling SriovNetwork") diff --git a/controllers/sriovnetworknodepolicy_controller.go b/controllers/sriovnetworknodepolicy_controller.go index 14acc9a8d..fa67a54aa 100644 --- a/controllers/sriovnetworknodepolicy_controller.go +++ b/controllers/sriovnetworknodepolicy_controller.go @@ -43,6 +43,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" utils "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" dptypes "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" @@ -82,11 +83,11 @@ func (r *SriovNetworkNodePolicyReconciler) Reconcile(ctx context.Context, req ct reqLogger.Info("Reconciling") defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - err := r.Get(ctx, types.NamespacedName{Name: constants.DefaultPolicyName, Namespace: namespace}, defaultPolicy) + err := r.Get(ctx, types.NamespacedName{Name: constants.DefaultPolicyName, Namespace: vars.Namespace}, defaultPolicy) if err != nil { if errors.IsNotFound(err) { // Default policy object not found, create it. - defaultPolicy.SetNamespace(namespace) + defaultPolicy.SetNamespace(vars.Namespace) defaultPolicy.SetName(constants.DefaultPolicyName) defaultPolicy.Spec = sriovnetworkv1.SriovNetworkNodePolicySpec{ NumVfs: 0, @@ -95,7 +96,7 @@ func (r *SriovNetworkNodePolicyReconciler) Reconcile(ctx context.Context, req ct } err = r.Create(ctx, defaultPolicy) if err != nil { - reqLogger.Error(err, "Failed to create default Policy", "Namespace", namespace, "Name", constants.DefaultPolicyName) + reqLogger.Error(err, "Failed to create default Policy", "Namespace", vars.Namespace, "Name", constants.DefaultPolicyName) return reconcile.Result{}, err } reqLogger.Info("Default policy created") @@ -125,7 +126,7 @@ func (r *SriovNetworkNodePolicyReconciler) Reconcile(ctx context.Context, req ct "kubernetes.io/os": "linux", } defaultOpConf := &sriovnetworkv1.SriovOperatorConfig{} - if err := r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: constants.DefaultConfigName}, defaultOpConf); err != nil { + if err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: constants.DefaultConfigName}, defaultOpConf); err != nil { return reconcile.Result{}, err } if len(defaultOpConf.Spec.ConfigDaemonNodeSelector) > 0 { @@ -216,7 +217,7 @@ func (r *SriovNetworkNodePolicyReconciler) syncDevicePluginConfigMap(ctx context }, ObjectMeta: metav1.ObjectMeta{ Name: constants.ConfigMapName, - Namespace: namespace, + Namespace: vars.Namespace, }, Data: configData, } @@ -246,14 +247,14 @@ func (r *SriovNetworkNodePolicyReconciler) syncAllSriovNetworkNodeStates(ctx con logger := log.Log.WithName("syncAllSriovNetworkNodeStates") logger.V(1).Info("Start to sync all SriovNetworkNodeState custom resource") found := &corev1.ConfigMap{} - if err := r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: constants.ConfigMapName}, found); err != nil { + if err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: constants.ConfigMapName}, found); err != nil { logger.V(1).Info("Fail to get", "ConfigMap", constants.ConfigMapName) } for _, node := range nl.Items { logger.V(1).Info("Sync SriovNetworkNodeState CR", "name", node.Name) ns := &sriovnetworkv1.SriovNetworkNodeState{} ns.Name = node.Name - ns.Namespace = namespace + ns.Namespace = vars.Namespace j, _ := json.Marshal(ns) logger.V(2).Info("SriovNetworkNodeState CR", "content", j) if err := r.syncSriovNetworkNodeState(ctx, np, npl, ns, &node, utils.HashConfigMap(found)); err != nil { @@ -428,7 +429,7 @@ func (r *SriovNetworkNodePolicyReconciler) renderDevicePluginConfigData(ctx cont } nodeState := &sriovnetworkv1.SriovNetworkNodeState{} - err := r.Get(ctx, types.NamespacedName{Namespace: namespace, Name: node.Name}, nodeState) + err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: node.Name}, nodeState) if err != nil { return rcl, err } diff --git a/controllers/sriovnetworknodepolicy_controller_test.go b/controllers/sriovnetworknodepolicy_controller_test.go index bd4579d78..3894f5a93 100644 --- a/controllers/sriovnetworknodepolicy_controller_test.go +++ b/controllers/sriovnetworknodepolicy_controller_test.go @@ -18,6 +18,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" v1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" ) func TestNodeSelectorMerge(t *testing.T) { @@ -213,7 +214,7 @@ func TestRenderDevicePluginConfigData(t *testing.T) { reconciler := SriovNetworkNodePolicyReconciler{} node := corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "node1"}} - nodeState := sriovnetworkv1.SriovNetworkNodeState{ObjectMeta: metav1.ObjectMeta{Name: node.Name, Namespace: namespace}} + nodeState := sriovnetworkv1.SriovNetworkNodeState{ObjectMeta: metav1.ObjectMeta{Name: node.Name, Namespace: vars.Namespace}} scheme := runtime.NewScheme() utilruntime.Must(sriovnetworkv1.AddToScheme(scheme)) diff --git a/controllers/sriovoperatorconfig_controller.go b/controllers/sriovoperatorconfig_controller.go index d6fe28e78..d75371581 100644 --- a/controllers/sriovoperatorconfig_controller.go +++ b/controllers/sriovoperatorconfig_controller.go @@ -77,7 +77,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. } defaultConfig := &sriovnetworkv1.SriovOperatorConfig{} err := r.Get(ctx, types.NamespacedName{ - Name: consts.DefaultConfigName, Namespace: namespace}, defaultConfig) + Name: consts.DefaultConfigName, Namespace: vars.Namespace}, defaultConfig) if err != nil { if apierrors.IsNotFound(err) { singleNode, err := utils.IsSingleNodeCluster(r.Client) @@ -86,7 +86,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. } // Default Config object not found, create it. - defaultConfig.SetNamespace(namespace) + defaultConfig.SetNamespace(vars.Namespace) defaultConfig.SetName(consts.DefaultConfigName) defaultConfig.Spec = sriovnetworkv1.SriovOperatorConfigSpec{ EnableInjector: func() *bool { b := vars.EnableAdmissionController; return &b }(), @@ -100,7 +100,7 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. err = r.Create(ctx, defaultConfig) if err != nil { logger.Error(err, "Failed to create default Operator Config", "Namespace", - namespace, "Name", consts.DefaultConfigName) + vars.Namespace, "Name", consts.DefaultConfigName) return reconcile.Result{}, err } return reconcile.Result{}, nil @@ -118,13 +118,13 @@ func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl. } defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - err = r.Get(ctx, types.NamespacedName{Name: consts.DefaultPolicyName, Namespace: namespace}, defaultPolicy) + err = r.Get(ctx, types.NamespacedName{Name: consts.DefaultPolicyName, Namespace: vars.Namespace}, defaultPolicy) if err != nil { // Error reading the object - requeue the request. return reconcile.Result{}, err } - if req.Namespace != namespace { + if req.Namespace != vars.Namespace { return reconcile.Result{}, nil } @@ -173,7 +173,7 @@ func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(ctx context.Context, data := render.MakeRenderData() data.Data["Image"] = os.Getenv("SRIOV_NETWORK_CONFIG_DAEMON_IMAGE") - data.Data["Namespace"] = namespace + data.Data["Namespace"] = vars.Namespace data.Data["SRIOVCNIImage"] = os.Getenv("SRIOV_CNI_IMAGE") data.Data["SRIOVInfiniBandCNIImage"] = os.Getenv("SRIOV_INFINIBAND_CNI_IMAGE") data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION") @@ -231,7 +231,7 @@ func (r *SriovOperatorConfigReconciler) syncWebhookObjs(ctx context.Context, dc for name, path := range webhooks { // Render Webhook manifests data := render.MakeRenderData() - data.Data["Namespace"] = namespace + data.Data["Namespace"] = vars.Namespace data.Data["SRIOVMutatingWebhookName"] = name data.Data["NetworkResourcesInjectorImage"] = os.Getenv("NETWORK_RESOURCES_INJECTOR_IMAGE") data.Data["SriovNetworkWebhookImage"] = os.Getenv("SRIOV_NETWORK_WEBHOOK_IMAGE") diff --git a/controllers/sriovoperatorconfig_controller_test.go b/controllers/sriovoperatorconfig_controller_test.go index 70ec3fd07..06955df89 100644 --- a/controllers/sriovoperatorconfig_controller_test.go +++ b/controllers/sriovoperatorconfig_controller_test.go @@ -12,6 +12,7 @@ import ( sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" + "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" util "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" ) @@ -19,7 +20,7 @@ var _ = Describe("Operator", func() { var config *sriovnetworkv1.SriovOperatorConfig BeforeEach(func() { defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - defaultPolicy.SetNamespace(namespace) + defaultPolicy.SetNamespace(vars.Namespace) defaultPolicy.SetName(constants.DefaultPolicyName) defaultPolicy.Spec = sriovnetworkv1.SriovNetworkNodePolicySpec{ NumVfs: 0, @@ -30,7 +31,7 @@ var _ = Describe("Operator", func() { }) AfterEach(func() { defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - defaultPolicy.SetNamespace(namespace) + defaultPolicy.SetNamespace(vars.Namespace) defaultPolicy.SetName(constants.DefaultPolicyName) Expect(k8sClient.Delete(goctx.TODO(), defaultPolicy)).Should(Succeed()) }) diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 9d4a43e94..c6c845cb0 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -112,8 +112,6 @@ const ( annoMcpPaused = "Draining_MCP_Paused" ) -var namespace = os.Getenv("NAMESPACE") - // writer implements io.Writer interface as a pass-through for log.Log. type writer struct { logFunc func(msg string, keysAndValues ...interface{}) @@ -210,7 +208,7 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { dn.mu = &sync.Mutex{} informerFactory := sninformer.NewFilteredSharedInformerFactory(dn.client, time.Second*15, - namespace, + vars.Namespace, func(lo *metav1.ListOptions) { lo.FieldSelector = metadataKey + "=" + vars.NodeName lo.TimeoutSeconds = &timeout @@ -227,7 +225,7 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error { cfgInformerFactory := sninformer.NewFilteredSharedInformerFactory(dn.client, time.Second*30, - namespace, + vars.Namespace, func(lo *metav1.ListOptions) { lo.FieldSelector = metadataKey + "=" + "default" }, @@ -410,7 +408,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { // Get the latest NodeState var latestState *sriovnetworkv1.SriovNetworkNodeState var sriovResult = &systemd.SriovResult{SyncStatus: consts.SyncStatusSucceeded, LastSyncError: ""} - latestState, err = dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) + latestState, err = dn.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", vars.NodeName) return err @@ -502,7 +500,7 @@ func (dn *Daemon) nodeStateSyncHandler() error { // we need to load the latest status to our object // if we don't do it we can have a race here where the user remove the virtual functions but the operator didn't // trigger the refresh - updatedState, err := dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) + updatedState, err := dn.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { log.Log.Error(err, "nodeStateSyncHandler(): Failed to fetch node state", "name", vars.NodeName) return err @@ -733,7 +731,7 @@ func (dn *Daemon) restartDevicePluginPod() error { log.Log.V(2).Info("restartDevicePluginPod(): try to restart device plugin pod") var podToDelete string - pods, err := dn.kubeClient.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{ + pods, err := dn.kubeClient.CoreV1().Pods(vars.Namespace).List(context.Background(), metav1.ListOptions{ LabelSelector: "app=sriov-device-plugin", FieldSelector: "spec.nodeName=" + vars.NodeName, }) @@ -753,7 +751,7 @@ func (dn *Daemon) restartDevicePluginPod() error { podToDelete = pods.Items[0].Name log.Log.V(2).Info("restartDevicePluginPod(): Found device plugin pod, deleting it", "pod-name", podToDelete) - err = dn.kubeClient.CoreV1().Pods(namespace).Delete(context.Background(), podToDelete, metav1.DeleteOptions{}) + err = dn.kubeClient.CoreV1().Pods(vars.Namespace).Delete(context.Background(), podToDelete, metav1.DeleteOptions{}) if errors.IsNotFound(err) { log.Log.Info("restartDevicePluginPod(): pod to delete not found") return nil @@ -764,7 +762,7 @@ func (dn *Daemon) restartDevicePluginPod() error { } if err := wait.PollImmediateUntil(3*time.Second, func() (bool, error) { - _, err := dn.kubeClient.CoreV1().Pods(namespace).Get(context.Background(), podToDelete, metav1.GetOptions{}) + _, err := dn.kubeClient.CoreV1().Pods(vars.Namespace).Get(context.Background(), podToDelete, metav1.GetOptions{}) if errors.IsNotFound(err) { log.Log.Info("restartDevicePluginPod(): device plugin pod exited") return true, nil @@ -875,7 +873,7 @@ func (dn *Daemon) getDrainLock(ctx context.Context, done chan bool) { lock := &resourcelock.LeaseLock{ LeaseMeta: metav1.ObjectMeta{ Name: "config-daemon-draining-lock", - Namespace: namespace, + Namespace: vars.Namespace, }, Client: dn.kubeClient.CoordinationV1(), LockConfig: resourcelock.ResourceLockConfig{ @@ -1052,7 +1050,7 @@ func (dn *Daemon) drainNode() error { // TODO: move this to host interface func (dn *Daemon) tryCreateSwitchdevUdevRule() error { log.Log.V(2).Info("tryCreateSwitchdevUdevRule()") - nodeState, nodeStateErr := dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get( + nodeState, nodeStateErr := dn.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).Get( context.Background(), vars.NodeName, metav1.GetOptions{}, diff --git a/pkg/daemon/daemon_test.go b/pkg/daemon/daemon_test.go index b804888fa..e81f7b677 100644 --- a/pkg/daemon/daemon_test.go +++ b/pkg/daemon/daemon_test.go @@ -30,7 +30,7 @@ import ( var FakeSupportedNicIDs corev1.ConfigMap = corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: sriovnetworkv1.SupportedNicIDConfigmap, - Namespace: namespace, + Namespace: vars.Namespace, }, Data: map[string]string{ "Intel_i40e_XXV710": "8086 158a 154c", @@ -41,7 +41,7 @@ var FakeSupportedNicIDs corev1.ConfigMap = corev1.ConfigMap{ var SriovDevicePluginPod corev1.Pod = corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: "sriov-device-plugin-xxxx", - Namespace: namespace, + Namespace: vars.Namespace, Labels: map[string]string{ "app": "sriov-device-plugin", }, @@ -110,7 +110,7 @@ var _ = Describe("Config Daemon", func() { kubeClient := fakek8s.NewSimpleClientset(&FakeSupportedNicIDs, &SriovDevicePluginPod) client := fakesnclientset.NewSimpleClientset() - err = sriovnetworkv1.InitNicIDMapFromConfigMap(kubeClient, namespace) + err = sriovnetworkv1.InitNicIDMapFromConfigMap(kubeClient, vars.Namespace) Expect(err).ToNot(HaveOccurred()) er := NewEventRecorder(client, kubeClient) @@ -203,7 +203,7 @@ var _ = Describe("Config Daemon", func() { Expect(msg.syncStatus).To(Equal("Succeeded")) Eventually(func() (int, error) { - podList, err := sut.kubeClient.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{ + podList, err := sut.kubeClient.CoreV1().Pods(vars.Namespace).List(context.Background(), metav1.ListOptions{ LabelSelector: "app=sriov-device-plugin", FieldSelector: "spec.nodeName=test-node", }) @@ -260,14 +260,14 @@ var _ = Describe("Config Daemon", func() { func createSriovNetworkNodeState(c snclientset.Interface, nodeState *sriovnetworkv1.SriovNetworkNodeState) error { _, err := c.SriovnetworkV1(). - SriovNetworkNodeStates(namespace). + SriovNetworkNodeStates(vars.Namespace). Create(context.Background(), nodeState, metav1.CreateOptions{}) return err } func updateSriovNetworkNodeState(c snclientset.Interface, nodeState *sriovnetworkv1.SriovNetworkNodeState) error { _, err := c.SriovnetworkV1(). - SriovNetworkNodeStates(namespace). + SriovNetworkNodeStates(vars.Namespace). Update(context.Background(), nodeState, metav1.UpdateOptions{}) return err } diff --git a/pkg/daemon/event_recorder.go b/pkg/daemon/event_recorder.go index ed9b34ee7..25b2d2351 100644 --- a/pkg/daemon/event_recorder.go +++ b/pkg/daemon/event_recorder.go @@ -36,7 +36,7 @@ func NewEventRecorder(c snclientset.Interface, kubeclient kubernetes.Interface) // SendEvent Send an Event on the NodeState object func (e *EventRecorder) SendEvent(eventType string, msg string) { - nodeState, err := e.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) + nodeState, err := e.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if err != nil { log.Log.V(2).Error(err, "SendEvent(): Failed to fetch node state, skip SendEvent", "name", vars.NodeName) return diff --git a/pkg/daemon/writer.go b/pkg/daemon/writer.go index 1a83c77d8..c796546ef 100644 --- a/pkg/daemon/writer.go +++ b/pkg/daemon/writer.go @@ -150,7 +150,7 @@ func (w *NodeStateStatusWriter) updateNodeStateStatusRetry(f func(*sriovnetworkv lastError = n.Status.LastSyncError var err error - nodeState, err = w.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).UpdateStatus(context.Background(), n, metav1.UpdateOptions{}) + nodeState, err = w.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).UpdateStatus(context.Background(), n, metav1.UpdateOptions{}) if err != nil { log.Log.V(0).Error(err, "updateNodeStateStatusRetry(): fail to update the node status") } @@ -207,7 +207,7 @@ func (w *NodeStateStatusWriter) getNodeState() (*sriovnetworkv1.SriovNetworkNode var lastErr error var n *sriovnetworkv1.SriovNetworkNodeState err := wait.PollImmediate(10*time.Second, 5*time.Minute, func() (bool, error) { - n, lastErr = w.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) + n, lastErr = w.client.SriovnetworkV1().SriovNetworkNodeStates(vars.Namespace).Get(context.Background(), vars.NodeName, metav1.GetOptions{}) if lastErr == nil { return true, nil } diff --git a/pkg/vars/vars.go b/pkg/vars/vars.go index a34cab8af..ebc49fa25 100644 --- a/pkg/vars/vars.go +++ b/pkg/vars/vars.go @@ -57,6 +57,9 @@ var ( // PfPhysPortNameRe regex to find switchdev devices on the host PfPhysPortNameRe = regexp.MustCompile(`p\d+`) + + // Namespace contains k8s namespace + Namespace = "" ) func init() { @@ -79,4 +82,6 @@ func init() { if enableAdmissionController == "True" { EnableAdmissionController = true } + + Namespace = os.Getenv("NAMESPACE") } From fe7d6bd3c5a12142ab61396e1db0fef0b855395b Mon Sep 17 00:00:00 2001 From: Carlos Goncalves Date: Wed, 31 Jan 2024 13:19:51 +0100 Subject: [PATCH 58/61] Fix log messages in ReloadDriver & GetOSPrettyName --- pkg/host/internal/kernel/kernel.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/host/internal/kernel/kernel.go b/pkg/host/internal/kernel/kernel.go index 3b3ab5fe6..3bb539374 100644 --- a/pkg/host/internal/kernel/kernel.go +++ b/pkg/host/internal/kernel/kernel.go @@ -535,7 +535,7 @@ func (k *kernel) ReloadDriver(driverName string) error { _, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("%s modprobe -r %s && %s modprobe %s", chrootDefinition, driverName, chrootDefinition, driverName)) if err != nil && len(stderr) != 0 { - log.Log.Error(err, "InstallRDMA(): failed to reload kernel module", + log.Log.Error(err, "ReloadDriver(): failed to reload kernel module", "name", driverName, "stderr", stderr) return err } @@ -553,7 +553,7 @@ func (k *kernel) GetOSPrettyName() (string, error) { stdout, stderr, err := k.utilsHelper.RunCommand("/bin/sh", "-c", fmt.Sprintf("cat %s | grep PRETTY_NAME | cut -c 13-", path)) if err != nil && len(stderr) != 0 { - log.Log.Error(err, "IsUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file", "stderr", stderr) + log.Log.Error(err, "GetOSPrettyName(): failed to check for operating system name in os-release file", "stderr", stderr) return "", fmt.Errorf(stderr) } From 224f2c02c72aebdd8106828664ea38853cbbcdee Mon Sep 17 00:00:00 2001 From: Yury Kulazhenkov Date: Wed, 31 Jan 2024 18:57:54 +0200 Subject: [PATCH 59/61] Move default policy creation in controller tests to BeforeSuite. This is required to fix the following problem: SriovOperatorConfigReconciler starts in the BeforeSuite handler, the default OperatorConfig is also created in BeforeSuite. That means the SriovOperatorConfigReconciler will be triggered with the first test in the controller suite. SriovOperatorConfigReconciler will fail (return an error) until DefaultPolicy is created by the BeforeEach function in sriovoperatorconfig_controller_test.go. The problem is that tests in sriovoperatorconfig_controller_test.go starts after the test in some other *_test.go files in the controller package. At the time when tests from sriovoperatorconfig_controller_test.go are eventually executed, SriovOperatorConfigReconciler controller is already failed multiple times in a row (because there was no default policy) and is waiting with a backoff delay (already quite large) before reconcilation retry. Signed-off-by: Yury Kulazhenkov --- .../sriovoperatorconfig_controller_test.go | 41 +------------------ controllers/suite_test.go | 10 +++++ 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/controllers/sriovoperatorconfig_controller_test.go b/controllers/sriovoperatorconfig_controller_test.go index a871f69a1..c2e779ee1 100644 --- a/controllers/sriovoperatorconfig_controller_test.go +++ b/controllers/sriovoperatorconfig_controller_test.go @@ -11,52 +11,13 @@ import ( . "github.com/onsi/gomega" sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" - constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts" - "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars" util "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util" ) var _ = Describe("Operator", func() { - var config *sriovnetworkv1.SriovOperatorConfig - BeforeEach(func() { - defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - defaultPolicy.SetNamespace(vars.Namespace) - defaultPolicy.SetName(constants.DefaultPolicyName) - defaultPolicy.Spec = sriovnetworkv1.SriovNetworkNodePolicySpec{ - NumVfs: 0, - NodeSelector: make(map[string]string), - NicSelector: sriovnetworkv1.SriovNetworkNicSelector{}, - } - Expect(k8sClient.Create(goctx.TODO(), defaultPolicy)).Should(Succeed()) - }) - AfterEach(func() { - defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} - defaultPolicy.SetNamespace(vars.Namespace) - defaultPolicy.SetName(constants.DefaultPolicyName) - Expect(k8sClient.Delete(goctx.TODO(), defaultPolicy)).Should(Succeed()) - }) - // BeforeEach(func() { - // config = &sriovnetworkv1.SriovOperatorConfig{} - // config.SetNamespace(testNamespace) - // config.SetName(DEFAULT_CONFIG_NAME) - // config.Spec = sriovnetworkv1.SriovOperatorConfigSpec{ - // EnableInjector: func() *bool { b := true; return &b }(), - // EnableOperatorWebhook: func() *bool { b := true; return &b }(), - // ConfigDaemonNodeSelector: map[string]string{}, - // LogLevel: 2, - // } - // Expect(k8sClient.Create(goctx.TODO(), config)).Should(Succeed()) - // }) - // AfterEach(func() { - // config := &sriovnetworkv1.SriovOperatorConfig{} - // config.SetNamespace(testNamespace) - // config.SetName(DEFAULT_CONFIG_NAME) - // Expect(k8sClient.Delete(goctx.TODO(), config)).Should(Succeed()) - // }) - Context("When is up", func() { JustBeforeEach(func() { - config = &sriovnetworkv1.SriovOperatorConfig{} + config := &sriovnetworkv1.SriovOperatorConfig{} err := util.WaitForNamespacedObject(config, k8sClient, testNamespace, "default", util.RetryInterval, util.APITimeout) Expect(err).NotTo(HaveOccurred()) config.Spec = sriovnetworkv1.SriovOperatorConfigSpec{ diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 07bc9a7c1..b0776f473 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -193,6 +193,16 @@ var _ = BeforeSuite(func() { } Expect(k8sClient.Create(context.TODO(), config)).Should(Succeed()) + defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} + defaultPolicy.SetNamespace(testNamespace) + defaultPolicy.SetName(constants.DefaultPolicyName) + defaultPolicy.Spec = sriovnetworkv1.SriovNetworkNodePolicySpec{ + NumVfs: 0, + NodeSelector: make(map[string]string), + NicSelector: sriovnetworkv1.SriovNetworkNicSelector{}, + } + Expect(k8sClient.Create(context.TODO(), defaultPolicy)).Should(Succeed()) + infra := &openshiftconfigv1.Infrastructure{ ObjectMeta: metav1.ObjectMeta{ Name: "cluster", From 0258c5a6a916f81557769dc8232beddaf028ea84 Mon Sep 17 00:00:00 2001 From: adrianc Date: Thu, 1 Feb 2024 10:19:54 +0200 Subject: [PATCH 60/61] Cleanup Created object in controller tests some controller tests were not cleaning up created objects, add cleanup for those tests. Signed-off-by: adrianc --- controllers/sriovibnetwork_controller_test.go | 11 +++++++++-- controllers/sriovnetwork_controller_test.go | 11 +++++++++-- controllers/sriovnetworkpoolconfig_controller_test.go | 9 +++++++++ controllers/suite_test.go | 4 ++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/controllers/sriovibnetwork_controller_test.go b/controllers/sriovibnetwork_controller_test.go index fa676c369..6ba0d2bd8 100644 --- a/controllers/sriovibnetwork_controller_test.go +++ b/controllers/sriovibnetwork_controller_test.go @@ -223,11 +223,18 @@ var _ = Describe("SriovIBNetwork Controller", func() { err = k8sClient.Get(ctx, types.NamespacedName{Name: cr.GetName(), Namespace: "ib-ns-xxx"}, netAttDef) Expect(err).To(HaveOccurred()) - err = k8sClient.Create(goctx.TODO(), &corev1.Namespace{ + // Create Namespace + nsObj := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{Name: "ib-ns-xxx"}, - }) + } + err = k8sClient.Create(goctx.TODO(), nsObj) Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + err = k8sClient.Delete(goctx.TODO(), nsObj) + Expect(err).NotTo(HaveOccurred()) + }) + // Check that net-attach-def has been created err = util.WaitForNamespacedObject(netAttDef, k8sClient, "ib-ns-xxx", cr.GetName(), util.RetryInterval, util.Timeout) Expect(err).NotTo(HaveOccurred()) diff --git a/controllers/sriovnetwork_controller_test.go b/controllers/sriovnetwork_controller_test.go index f4eb42020..9f2e5a6ae 100644 --- a/controllers/sriovnetwork_controller_test.go +++ b/controllers/sriovnetwork_controller_test.go @@ -260,11 +260,18 @@ var _ = Describe("SriovNetwork Controller", func() { err = k8sClient.Get(ctx, types.NamespacedName{Name: cr.GetName(), Namespace: "ns-xxx"}, netAttDef) Expect(err).To(HaveOccurred()) - err = k8sClient.Create(goctx.TODO(), &corev1.Namespace{ + // Create Namespace + nsObj := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{Name: "ns-xxx"}, - }) + } + err = k8sClient.Create(goctx.TODO(), nsObj) Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + err = k8sClient.Delete(goctx.TODO(), nsObj) + Expect(err).NotTo(HaveOccurred()) + }) + // Check that net-attach-def has been created err = util.WaitForNamespacedObject(netAttDef, k8sClient, "ns-xxx", cr.GetName(), util.RetryInterval, util.Timeout) Expect(err).NotTo(HaveOccurred()) diff --git a/controllers/sriovnetworkpoolconfig_controller_test.go b/controllers/sriovnetworkpoolconfig_controller_test.go index ff20c0535..d0a7090c5 100644 --- a/controllers/sriovnetworkpoolconfig_controller_test.go +++ b/controllers/sriovnetworkpoolconfig_controller_test.go @@ -53,12 +53,21 @@ var _ = Describe("Operator", func() { } err = k8sClient.Create(goctx.TODO(), mcp) Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + err = k8sClient.Delete(goctx.TODO(), mcp) + Expect(err).ToNot(HaveOccurred()) + }) config.Spec.OvsHardwareOffloadConfig = sriovnetworkv1.OvsHardwareOffloadConfig{ Name: mcpName, } err = k8sClient.Create(goctx.TODO(), config) Expect(err).NotTo(HaveOccurred()) + DeferCleanup(func() { + err = k8sClient.Delete(goctx.TODO(), config) + Expect(err).ToNot(HaveOccurred()) + }) + Eventually(func() error { mc := &mcfgv1.MachineConfig{} err := k8sClient.Get(goctx.TODO(), types.NamespacedName{Name: mcName, Namespace: testNamespace}, mc) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index b0776f473..7723c27a8 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -182,6 +182,7 @@ var _ = BeforeSuite(func() { } Expect(k8sClient.Create(context.TODO(), ns)).Should(Succeed()) + // Create default SriovOperatorConfig config := &sriovnetworkv1.SriovOperatorConfig{} config.SetNamespace(testNamespace) config.SetName(constants.DefaultConfigName) @@ -193,6 +194,7 @@ var _ = BeforeSuite(func() { } Expect(k8sClient.Create(context.TODO(), config)).Should(Succeed()) + // Create default SriovNetworkNodePolicy defaultPolicy := &sriovnetworkv1.SriovNetworkNodePolicy{} defaultPolicy.SetNamespace(testNamespace) defaultPolicy.SetName(constants.DefaultPolicyName) @@ -203,6 +205,7 @@ var _ = BeforeSuite(func() { } Expect(k8sClient.Create(context.TODO(), defaultPolicy)).Should(Succeed()) + // Create openshift Infrastructure infra := &openshiftconfigv1.Infrastructure{ ObjectMeta: metav1.ObjectMeta{ Name: "cluster", @@ -214,6 +217,7 @@ var _ = BeforeSuite(func() { } Expect(k8sClient.Create(context.TODO(), infra)).Should(Succeed()) + // Create default SriovNetworkPoolConfig poolConfig := &sriovnetworkv1.SriovNetworkPoolConfig{} poolConfig.SetNamespace(testNamespace) poolConfig.SetName(constants.DefaultConfigName) From 7c2029fe889b226805afe3d637d8920e48c81577 Mon Sep 17 00:00:00 2001 From: adrianc Date: Thu, 1 Feb 2024 10:27:05 +0200 Subject: [PATCH 61/61] Start manager at end of BeforeSuite Signed-off-by: adrianc --- controllers/suite_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 7723c27a8..13505c1a2 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -165,12 +165,6 @@ var _ = BeforeSuite(func() { ctx, cancel = context.WithCancel(ctrl.SetupSignalHandler()) - go func() { - defer GinkgoRecover() - err = k8sManager.Start(ctx) - Expect(err).ToNot(HaveOccurred()) - }() - // Create test namespace ns := &corev1.Namespace{ TypeMeta: metav1.TypeMeta{}, @@ -223,6 +217,12 @@ var _ = BeforeSuite(func() { poolConfig.SetName(constants.DefaultConfigName) poolConfig.Spec = sriovnetworkv1.SriovNetworkPoolConfigSpec{} Expect(k8sClient.Create(context.TODO(), poolConfig)).Should(Succeed()) + + go func() { + defer GinkgoRecover() + err = k8sManager.Start(ctx) + Expect(err).ToNot(HaveOccurred()) + }() }) var _ = AfterSuite(func() {