diff --git a/cmd/dra-multus-driver/README.md b/cmd/dra-multus-driver/README.md index 83f8abaa8..2f062e47f 100644 --- a/cmd/dra-multus-driver/README.md +++ b/cmd/dra-multus-driver/README.md @@ -1,2 +1,8 @@ # DRA Multus Driver. +## TODO! + +* Plurality is a mess all over the place. + * I tested with only one attachment, and I focused on it. +* Things might belong on one side or the other DRA vs. CNI + * And I just chucked it where convenient at the time. \ No newline at end of file diff --git a/cmd/dra-multus-driver/example.yaml b/cmd/dra-multus-driver/example.yaml index 1c13d8aa5..45eb6ae68 100644 --- a/cmd/dra-multus-driver/example.yaml +++ b/cmd/dra-multus-driver/example.yaml @@ -57,8 +57,8 @@ metadata: spec: containers: - name: app - image: ubuntu:22.04 - command: ["bash", "-c"] + image: alpine + command: ["/bin/ash", "-c", "trap : TERM INT; sleep infinity & wait"] args: ["export; trap 'exit 0' TERM; sleep 9999 & wait"] resources: claims: diff --git a/cmd/dra-multus-driver/main.go b/cmd/dra-multus-driver/main.go index 2493b293e..25c5aa24a 100644 --- a/cmd/dra-multus-driver/main.go +++ b/cmd/dra-multus-driver/main.go @@ -115,7 +115,7 @@ func StartPlugin(ctx context.Context, config *Config) error { return fmt.Errorf("path for cdi file generation is not a directory: '%v'", err) } - klog.Infof("Starting %s", DriverName) + klog.Infof("Starting %s (version 0.0.0)", DriverName) driver, err := NewDriver(ctx, config) if err != nil { return err diff --git a/cmd/dra-multus-driver/state.go b/cmd/dra-multus-driver/state.go index a9cec3cc5..88ff9c70e 100644 --- a/cmd/dra-multus-driver/state.go +++ b/cmd/dra-multus-driver/state.go @@ -6,8 +6,10 @@ import ( "fmt" "os" "path/filepath" + "strings" "sync" + "github.com/containernetworking/cni/libcni" resourceapi "k8s.io/api/resource/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -18,7 +20,6 @@ import ( configapi "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/dra/api/multus-cni.io/resource/net/v1alpha1" multusk8sutils "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/k8sclient" "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/types" - multustypes "gopkg.in/k8snetworkplumbingwg/multus-cni.v4/pkg/types" cdiapi "tags.cncf.io/container-device-interface/pkg/cdi" cdispec "tags.cncf.io/container-device-interface/specs-go" @@ -248,36 +249,80 @@ func (s *DeviceState) applyConfig( claimUID string, ) (PerDeviceCDIContainerEdits, error) { perDeviceEdits := make(PerDeviceCDIContainerEdits) + var delegates []*types.DelegateNetConf + // --- Add the cluster default network as the first delegate --- + multusConfPath := "/host/etc/cni/net.d/00-multus.conf" + multusConfBytes, err := os.ReadFile(multusConfPath) + if err != nil { + return nil, fmt.Errorf("failed to read multus config from %s: %w", multusConfPath, err) + } + + var multusConf struct { + ClusterNetwork string `json:"clusterNetwork"` + } + if err := json.Unmarshal(multusConfBytes, &multusConf); err != nil { + return nil, fmt.Errorf("failed to parse multus config json: %w", err) + } + if multusConf.ClusterNetwork == "" { + return nil, fmt.Errorf("no clusterNetwork field found in multus config") + } + + // Load the default network CNI config + var defaultConfBytes []byte + isconflist := false + if strings.HasSuffix(multusConf.ClusterNetwork, ".conflist") { + confList, err := libcni.ConfListFromFile(multusConf.ClusterNetwork) + if err != nil { + return nil, fmt.Errorf("failed to load CNI conflist from %s: %w", multusConf.ClusterNetwork, err) + } + isconflist = true + defaultConfBytes = confList.Bytes + } else { + conf, err := libcni.ConfFromFile(multusConf.ClusterNetwork) + if err != nil { + return nil, fmt.Errorf("failed to load CNI config from %s: %w", multusConf.ClusterNetwork, err) + } + if conf.Network.Type == "" { + return nil, fmt.Errorf("CNI config in %s missing type field", multusConf.ClusterNetwork) + } + defaultConfBytes = conf.Bytes + } + + // Create and append the default delegate + defaultDelegate, err := types.LoadDelegateNetConf(defaultConfBytes, nil, "", "") + if err != nil { + return nil, fmt.Errorf("failed to load delegate from default CNI config: %w", err) + } + defaultDelegate.MasterPlugin = true + defaultDelegate.ConfListPlugin = isconflist + delegates = append(delegates, defaultDelegate) + + // --- Add the user-defined network attachments --- parsedNets, err := multusk8sutils.ParsePodNetworkAnnotation(config.Networks, podNamespace) if err != nil { return nil, fmt.Errorf("failed to parse networks string: %w", err) } - var delegates []*types.DelegateNetConf - for _, net := range parsedNets { nad, err := s.nadClient.K8sCniCncfIoV1().NetworkAttachmentDefinitions(net.Namespace).Get(context.TODO(), net.Name, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("failed to fetch NAD %s/%s: %w", net.Namespace, net.Name, err) } - klog.Infof("!bang: Whole net-attach-def: %+v", nad) - - delegate, err := multustypes.LoadDelegateNetConf([]byte(nad.Spec.Config), net, "", "") + delegate, err := types.LoadDelegateNetConf([]byte(nad.Spec.Config), net, "", "") if err != nil { - // Handle error loading delegate return nil, fmt.Errorf("failed to load delegate netconf from NAD %s/%s: %w", net.Namespace, net.Name, err) } - // Preserve ifname from network selection if net.InterfaceRequest != "" { delegate.IfnameRequest = net.InterfaceRequest } - delegates = append(delegates, delegate) } + klog.Infof("Delegate information for pod %s/%s: %+v", podNamespace, podName, delegates) + // Save delegates to a file delegatesPath := filepath.Join("/run/k8s.cni.cncf.io/dra", fmt.Sprintf("%s_%s.json", podNamespace, podName)) if err := os.MkdirAll(filepath.Dir(delegatesPath), 0755); err != nil { diff --git a/deployments/dra.yml b/deployments/dra.yml index 58f6ed764..ead6895e7 100644 --- a/deployments/dra.yml +++ b/deployments/dra.yml @@ -97,6 +97,8 @@ spec: mountPath: /var/run/cdi - name: host-run-k8s-cni-cncf-io mountPath: /run/k8s.cni.cncf.io + - name: cni + mountPath: /host/etc/cni/net.d volumes: - name: plugins-registry hostPath: @@ -110,4 +112,7 @@ spec: - name: host-run-k8s-cni-cncf-io hostPath: path: /run/k8s.cni.cncf.io + - name: cni + hostPath: + path: /etc/cni/net.d diff --git a/pkg/types/types.go b/pkg/types/types.go index 1a410db59..07a1326fb 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -110,9 +110,9 @@ type DelegateNetConf struct { IsFilterV4Gateway bool IsFilterV6Gateway bool // MasterPlugin is only used internal housekeeping - MasterPlugin bool `json:"-"` + MasterPlugin bool `json:"masterPlugin"` // Conflist plugin is only used internal housekeeping - ConfListPlugin bool `json:"-"` + ConfListPlugin bool `json:"confListPlugin"` // DeviceID is only used internal housekeeping DeviceID string `json:"deviceID,omitempty"` // ResourceName is only used internal housekeeping