diff --git a/pkg/apis/k8s.cni.cncf.io/v1/types.go b/pkg/apis/k8s.cni.cncf.io/v1/types.go index 0eceddc5c..b5742ab33 100644 --- a/pkg/apis/k8s.cni.cncf.io/v1/types.go +++ b/pkg/apis/k8s.cni.cncf.io/v1/types.go @@ -38,15 +38,74 @@ type DNS struct { Options []string `json:"options,omitempty"` } +const ( + DeviceInfoTypePCI = "pci" + DeviceInfoTypeVHostUser = "vhost-user" + DeviceInfoTypeMemif = "memif" + DeviceInfoTypeVDPA = "vdpa" + DeviceInfoVersion = "1.0.0" +) + +// DeviceInfo contains the information of the device associated +// with this network (if any) +type DeviceInfo struct { + Type string `json:"type,omitempty"` + Version string `json:"version,omitempty"` + Pci *PciDevice `json:"pci,omitempty"` + Vdpa *VdpaDevice `json:"vdpa,omitempty"` + VhostUser *VhostDevice `json:"vhost-user,omitempty"` + Memif *MemifDevice `json:"memif,omitempty"` +} + +type PciDevice struct { + PciAddress string `json:"pci-address,omitempty"` + Vhostnet string `json:"vhost-net,omitempty"` + RdmaDevice string `json:"rdma-device,omitempty"` + PfPciAddress string `json:"pf-pci-address,omitempty"` +} + +type VdpaDevice struct { + ParentDevice string `json:"parent-device,omitempty"` + Driver string `json:"driver,omitempty"` + Path string `json:"path,omitempty"` + PciAddress string `json:"pci-address,omitempty"` + PfPciAddress string `json:"pf-pci-address,omitempty"` +} + +const ( + VhostDeviceModeClient = "client" + VhostDeviceModeServer = "server" +) + +type VhostDevice struct { + Mode string `json:"mode,omitempty"` + Path string `json:"path,omitempty"` +} + +const ( + MemifDeviceRoleMaster = "master" + MemitDeviceRoleSlave = "slave" + MemifDeviceModeEthernet = "ethernet" + MemitDeviceModeIP = "ip" + MemitDeviceModePunt = "punt" +) + +type MemifDevice struct { + Role string `json:"role,omitempty"` + Path string `json:"path,omitempty"` + Mode string `json:"mode,omitempty"` +} + // NetworkStatus is for network status annotation for pod // +k8s:deepcopy-gen=false type NetworkStatus struct { - Name string `json:"name"` - Interface string `json:"interface,omitempty"` - IPs []string `json:"ips,omitempty"` - Mac string `json:"mac,omitempty"` - Default bool `json:"default,omitempty"` - DNS DNS `json:"dns,omitempty"` + Name string `json:"name"` + Interface string `json:"interface,omitempty"` + IPs []string `json:"ips,omitempty"` + Mac string `json:"mac,omitempty"` + Default bool `json:"default,omitempty"` + DNS DNS `json:"dns,omitempty"` + DeviceInfo *DeviceInfo `json:"device-info,omitempty"` } // PortMapEntry for CNI PortMapEntry diff --git a/pkg/apis/k8s.cni.cncf.io/v1/zz_generated.deepcopy.go b/pkg/apis/k8s.cni.cncf.io/v1/zz_generated.deepcopy.go index 8f74abde0..1ceb1e6e4 100644 --- a/pkg/apis/k8s.cni.cncf.io/v1/zz_generated.deepcopy.go +++ b/pkg/apis/k8s.cni.cncf.io/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ // +build !ignore_autogenerated /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,6 +24,58 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeviceInfo) DeepCopyInto(out *DeviceInfo) { + *out = *in + if in.Pci != nil { + in, out := &in.Pci, &out.Pci + *out = new(PciDevice) + **out = **in + } + if in.Vdpa != nil { + in, out := &in.Vdpa, &out.Vdpa + *out = new(VdpaDevice) + **out = **in + } + if in.VhostUser != nil { + in, out := &in.VhostUser, &out.VhostUser + *out = new(VhostDevice) + **out = **in + } + if in.Memif != nil { + in, out := &in.Memif, &out.Memif + *out = new(MemifDevice) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeviceInfo. +func (in *DeviceInfo) DeepCopy() *DeviceInfo { + if in == nil { + return nil + } + out := new(DeviceInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MemifDevice) DeepCopyInto(out *MemifDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemifDevice. +func (in *MemifDevice) DeepCopy() *MemifDevice { + if in == nil { + return nil + } + out := new(MemifDevice) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkAttachmentDefinition) DeepCopyInto(out *NetworkAttachmentDefinition) { *out = *in @@ -99,3 +151,51 @@ func (in *NetworkAttachmentDefinitionSpec) DeepCopy() *NetworkAttachmentDefiniti in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PciDevice) DeepCopyInto(out *PciDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PciDevice. +func (in *PciDevice) DeepCopy() *PciDevice { + if in == nil { + return nil + } + out := new(PciDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VdpaDevice) DeepCopyInto(out *VdpaDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VdpaDevice. +func (in *VdpaDevice) DeepCopy() *VdpaDevice { + if in == nil { + return nil + } + out := new(VdpaDevice) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VhostDevice) DeepCopyInto(out *VhostDevice) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VhostDevice. +func (in *VhostDevice) DeepCopy() *VhostDevice { + if in == nil { + return nil + } + out := new(VhostDevice) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 2b86a7d12..f4238c549 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/doc.go b/pkg/client/clientset/versioned/doc.go index 10f4419bd..22485f354 100644 --- a/pkg/client/clientset/versioned/doc.go +++ b/pkg/client/clientset/versioned/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 672626c4d..344a0efa1 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/fake/doc.go b/pkg/client/clientset/versioned/fake/doc.go index ff9007d25..c5afab287 100644 --- a/pkg/client/clientset/versioned/fake/doc.go +++ b/pkg/client/clientset/versioned/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 05d477740..98d4014d5 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/scheme/doc.go b/pkg/client/clientset/versioned/scheme/doc.go index 25a11f92f..49f3510bf 100644 --- a/pkg/client/clientset/versioned/scheme/doc.go +++ b/pkg/client/clientset/versioned/scheme/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 466c4f329..93942f6cb 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/doc.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/doc.go index c334e6f27..32d02a1a0 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/doc.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/doc.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/doc.go index af8696366..50576b381 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/doc.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_k8s.cni.cncf.io_client.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_k8s.cni.cncf.io_client.go index e039808ef..3e07e0eef 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_k8s.cni.cncf.io_client.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_k8s.cni.cncf.io_client.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_networkattachmentdefinition.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_networkattachmentdefinition.go index 9564be369..05c055f75 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_networkattachmentdefinition.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/fake/fake_networkattachmentdefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/generated_expansion.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/generated_expansion.go index 03219735a..245ff707b 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/generated_expansion.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/k8s.cni.cncf.io_client.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/k8s.cni.cncf.io_client.go index b9f5e8e22..9317b8034 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/k8s.cni.cncf.io_client.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/k8s.cni.cncf.io_client.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/networkattachmentdefinition.go b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/networkattachmentdefinition.go index cac55f71c..1f0ddac45 100644 --- a/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/networkattachmentdefinition.go +++ b/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1/networkattachmentdefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 0bbeb4ff8..2476f9fe6 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index f480520e0..649781164 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 459122027..edc84dd9b 100644 --- a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/k8s.cni.cncf.io/interface.go b/pkg/client/informers/externalversions/k8s.cni.cncf.io/interface.go index d2347d03e..f4d418cb0 100644 --- a/pkg/client/informers/externalversions/k8s.cni.cncf.io/interface.go +++ b/pkg/client/informers/externalversions/k8s.cni.cncf.io/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/interface.go b/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/interface.go index 412814d75..aa1b0762f 100644 --- a/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/interface.go +++ b/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/interface.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/networkattachmentdefinition.go b/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/networkattachmentdefinition.go index 69b95f73a..35f2f931d 100644 --- a/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/networkattachmentdefinition.go +++ b/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1/networkattachmentdefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/listers/k8s.cni.cncf.io/v1/expansion_generated.go b/pkg/client/listers/k8s.cni.cncf.io/v1/expansion_generated.go index 7f367379a..cb9a39138 100644 --- a/pkg/client/listers/k8s.cni.cncf.io/v1/expansion_generated.go +++ b/pkg/client/listers/k8s.cni.cncf.io/v1/expansion_generated.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/client/listers/k8s.cni.cncf.io/v1/networkattachmentdefinition.go b/pkg/client/listers/k8s.cni.cncf.io/v1/networkattachmentdefinition.go index 133c09a3e..fb9b666ed 100644 --- a/pkg/client/listers/k8s.cni.cncf.io/v1/networkattachmentdefinition.go +++ b/pkg/client/listers/k8s.cni.cncf.io/v1/networkattachmentdefinition.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors +Copyright 2021 The Kubernetes Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pkg/utils/cniconfig.go b/pkg/utils/cniconfig.go index 174c1658a..4b54909bb 100644 --- a/pkg/utils/cniconfig.go +++ b/pkg/utils/cniconfig.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Kubernetes Network Plumbing Working Group +// Copyright (c) 2021 Kubernetes Network Plumbing Working Group // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,11 +18,20 @@ import ( "encoding/json" "fmt" "github.com/containernetworking/cni/libcni" + "io/ioutil" + "os" + "path/filepath" "strings" v1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" ) +const ( + baseDevInfoPath = "/var/run/k8s.cni.cncf.io/devinfo" + dpDevInfoSubDir = "dp" + cniDevInfoSubDir = "cni" +) + // GetCNIConfig (from annotation string to CNI JSON bytes) func GetCNIConfig(net *v1.NetworkAttachmentDefinition, confDir string) (config []byte, err error) { emptySpec := v1.NetworkAttachmentDefinitionSpec{} @@ -117,3 +126,112 @@ func GetCNIConfigFromSpec(configData, netName string) ([]byte, error) { return configBytes, nil } + +// loadDeviceInfo loads a Device Information file +func loadDeviceInfo(path string) (*v1.DeviceInfo, error) { + var devInfo v1.DeviceInfo + + bytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + err = json.Unmarshal(bytes, &devInfo) + if err != nil { + return nil, err + } + + return &devInfo, nil +} + +// cleanDeviceInfo removes a Device Information file +func cleanDeviceInfo(path string) error { + if _, err := os.Stat(path); !os.IsNotExist(err) { + return os.Remove(path) + } + return nil +} + +// saveDeviceInfo writes a Device Information file +func saveDeviceInfo(devInfo *v1.DeviceInfo, path string) error { + if devInfo == nil { + return fmt.Errorf("Device Information is null") + } + + dir := filepath.Dir(path) + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err := os.MkdirAll(dir, os.ModeDir); err != nil { + return err + } + } + + if _, err := os.Stat(path); !os.IsNotExist(err) { + return fmt.Errorf("Device Information file already exists: %s", path) + } + + devInfoJSON, err := json.Marshal(devInfo) + if err != nil { + return err + } + + if err := ioutil.WriteFile(path, devInfoJSON, 0444); err != nil { + return err + } + return nil +} + +// getDPDeviceInfoPath returns the standard Device Plugin DevInfo filename +// This filename is fixed because Device Plugin and NPWG Implementation need +// to both access file and name is not passed between them. So name is generated +// from Resource Name and DeviceID. +func getDPDeviceInfoPath(resourceName string, deviceID string) string { + return filepath.Join(baseDevInfoPath, dpDevInfoSubDir, fmt.Sprintf("%s-%s-device.json", + strings.ReplaceAll(resourceName, "/", "-"), strings.ReplaceAll(deviceID, "/", "-"))) +} + +// GetCNIDeviceInfoPath returns the standard Device Plugin DevInfo filename +// The path is fixed but the filename is flexible and determined by the caller. +func GetCNIDeviceInfoPath(filename string) string { + return filepath.Join(baseDevInfoPath, cniDevInfoSubDir, strings.ReplaceAll(filename, "/", "-")) +} + +// LoadDeviceInfoFromDP loads a DeviceInfo structure from file created by a Device Plugin +// Returns an error if the device information is malformed and (nil, nil) if it does not exist +func LoadDeviceInfoFromDP(resourceName string, deviceID string) (*v1.DeviceInfo, error) { + return loadDeviceInfo(getDPDeviceInfoPath(resourceName, deviceID)) +} + +// SaveDeviceInfoForDP saves a DeviceInfo structure created by a Device Plugin +func SaveDeviceInfoForDP(resourceName string, deviceID string, devInfo *v1.DeviceInfo) error { + return saveDeviceInfo(devInfo, getDPDeviceInfoPath(resourceName, deviceID)) +} + +// CleanDeviceInfoForDP removes a DeviceInfo DP File. +func CleanDeviceInfoForDP(resourceName string, deviceID string) error { + return cleanDeviceInfo(getDPDeviceInfoPath(resourceName, deviceID)) +} + +// LoadDeviceInfoFromCNI loads a DeviceInfo structure from created by a CNI. +// Returns an error if the device information is malformed and (nil, nil) if it does not exist +func LoadDeviceInfoFromCNI(cniPath string) (*v1.DeviceInfo, error) { + return loadDeviceInfo(cniPath) +} + +// SaveDeviceInfoForCNI saves a DeviceInfo structure created by a CNI +func SaveDeviceInfoForCNI(cniPath string, devInfo *v1.DeviceInfo) error { + return saveDeviceInfo(devInfo, cniPath) +} + +// CopyDeviceInfoForCNIFromDP saves a DeviceInfo structure created by a DP to a CNI File. +func CopyDeviceInfoForCNIFromDP(cniPath string, resourceName string, deviceID string) error { + devInfo, err := loadDeviceInfo(getDPDeviceInfoPath(resourceName, deviceID)) + if err != nil { + return err + } + return saveDeviceInfo(devInfo, cniPath) +} + +// CleanDeviceInfoForCNI removes a DeviceInfo CNI File. +func CleanDeviceInfoForCNI(cniPath string) error { + return cleanDeviceInfo(cniPath) +} diff --git a/pkg/utils/cniconfig_test.go b/pkg/utils/cniconfig_test.go index e6eac0d4a..bca65d9d5 100644 --- a/pkg/utils/cniconfig_test.go +++ b/pkg/utils/cniconfig_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Kubernetes Network Plumbing Working Group +// Copyright (c) 2021 Kubernetes Network Plumbing Working Group // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/utils/net-attach-def.go b/pkg/utils/net-attach-def.go index be89cc511..c9bc2900b 100644 --- a/pkg/utils/net-attach-def.go +++ b/pkg/utils/net-attach-def.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Kubernetes Network Plumbing Working Group +// Copyright (c) 2021 Kubernetes Network Plumbing Working Group // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -65,40 +65,41 @@ func SetNetworkStatus(client kubernetes.Interface, pod *corev1.Pod, statuses []v } } - _, err := setPodNetworkStatus(client, pod, fmt.Sprintf("[%s]", strings.Join(networkStatus, ","))) + err := setPodNetworkStatus(client, pod, fmt.Sprintf("[%s]", strings.Join(networkStatus, ","))) if err != nil { return fmt.Errorf("SetNetworkStatus: failed to update the pod %s in out of cluster comm: %v", pod.Name, err) } return nil } -func setPodNetworkStatus(client kubernetes.Interface, pod *corev1.Pod, networkstatus string) (*corev1.Pod, error) { +func setPodNetworkStatus(client kubernetes.Interface, pod *corev1.Pod, networkstatus string) (error) { if len(pod.Annotations) == 0 { pod.Annotations = make(map[string]string) } coreClient := client.CoreV1() - - pod.Annotations[v1.NetworkStatusAnnot] = networkstatus - pod.Annotations[v1.OldNetworkStatusAnnot] = networkstatus - pod = pod.DeepCopy() var err error + name := pod.Name + namespace := pod.Namespace - if resultErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + resultErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + pod, err = coreClient.Pods(namespace).Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { - // Re-get the pod unless it's the first attempt to update - pod, err = coreClient.Pods(pod.Namespace).Get(context.TODO(), pod.Name, metav1.GetOptions{}) - if err != nil { - return err - } + return err } - pod, err = coreClient.Pods(pod.Namespace).UpdateStatus(context.TODO(), pod, metav1.UpdateOptions{}) + if len(pod.Annotations) == 0 { + pod.Annotations = make(map[string]string) + } + pod.Annotations[v1.NetworkStatusAnnot] = networkstatus + pod.Annotations[v1.OldNetworkStatusAnnot] = networkstatus + _, err = coreClient.Pods(namespace).UpdateStatus(context.TODO(), pod, metav1.UpdateOptions{}) return err - }); resultErr != nil { - return nil, fmt.Errorf("status update failed for pod %s/%s: %v", pod.Namespace, pod.Name, resultErr) + }) + if resultErr != nil { + return fmt.Errorf("status update failed for pod %s/%s: %v", pod.Namespace, pod.Name, resultErr) } - return pod, nil + return nil } // GetNetworkStatus returns pod's network status @@ -122,7 +123,7 @@ func GetNetworkStatus(pod *corev1.Pod) ([]v1.NetworkStatus, error) { } // CreateNetworkStatus create NetworkStatus from CNI result -func CreateNetworkStatus(r cnitypes.Result, networkName string, defaultNetwork bool) (*v1.NetworkStatus, error) { +func CreateNetworkStatus(r cnitypes.Result, networkName string, defaultNetwork bool, dev *v1.DeviceInfo) (*v1.NetworkStatus, error) { netStatus := &v1.NetworkStatus{} netStatus.Name = networkName netStatus.Default = defaultNetwork @@ -148,6 +149,10 @@ func CreateNetworkStatus(r cnitypes.Result, networkName string, defaultNetwork b v1dns := convertDNS(result.DNS) netStatus.DNS = *v1dns + if dev != nil { + netStatus.DeviceInfo = dev + } + return netStatus, nil } diff --git a/pkg/utils/net-attach-def_test.go b/pkg/utils/net-attach-def_test.go index 60c843ff4..20d496ef8 100644 --- a/pkg/utils/net-attach-def_test.go +++ b/pkg/utils/net-attach-def_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Kubernetes Network Plumbing Working Group +// Copyright (c) 2021 Kubernetes Network Plumbing Working Group // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -34,10 +34,10 @@ import ( // EnsureCIDR parses/verify CIDR ip string and convert to net.IPNet func EnsureCIDR(cidr string) *net.IPNet { - ip, net, err := net.ParseCIDR(cidr) - Expect(err).NotTo(HaveOccurred()) - net.IP = ip - return net + ip, net, err := net.ParseCIDR(cidr) + Expect(err).NotTo(HaveOccurred()) + net.IP = ip + return net } func TestNetworkAttachmentDefinition(t *testing.T) { @@ -49,10 +49,10 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { It("test convertDNS", func() { cniDNS := cnitypes.DNS{ - Nameservers: []string{ "aaa", "bbb" }, - Domain: "testDomain", - Search: []string{ "1.example.com", "2.example.com" }, - Options: []string{ "debug", "inet6" }, + Nameservers: []string{"aaa", "bbb"}, + Domain: "testDomain", + Search: []string{"1.example.com", "2.example.com"}, + Options: []string{"debug", "inet6"}, } v1DNS := convertDNS(cniDNS) @@ -65,40 +65,42 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { It("set network status into pod", func() { fakePod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "fakePod1", + Name: "fakePod1", Namespace: "fakeNamespace1", }, Spec: corev1.PodSpec{ Containers: []corev1.Container{ { - Name: "fakeContainer", + Name: "fakeContainer", Image: "fakeImage", }, }, }, } fakeStatus := []v1.NetworkStatus{ - v1.NetworkStatus{ - Name: "cbr0", + { + Name: "cbr0", Interface: "eth0", - IPs: []string{ "10.244.1.2" }, - Mac: "92:79:27:01:7c:ce", + IPs: []string{"10.244.1.2"}, + Mac: "92:79:27:01:7c:ce", }, - v1.NetworkStatus{ - Name: "test-net-attach-def-1", + { + Name: "test-net-attach-def-1", Interface: "net1", - IPs: []string{ "1.1.1.1" }, - Mac: "ea:0e:fa:63:95:f9", + IPs: []string{"1.1.1.1"}, + Mac: "ea:0e:fa:63:95:f9", }, } clientSet := fake.NewSimpleClientset(fakePod) - pod, err:= clientSet.CoreV1().Pods("fakeNamespace1").Get(context.TODO(), "fakePod1", metav1.GetOptions{}) + pod, err := clientSet.CoreV1().Pods("fakeNamespace1").Get(context.TODO(), "fakePod1", metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) err = SetNetworkStatus(clientSet, pod, fakeStatus) Expect(err).NotTo(HaveOccurred()) + pod, err = clientSet.CoreV1().Pods("fakeNamespace1").Get(context.TODO(), "fakePod1", metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) getStatuses, err := GetNetworkStatus(pod) Expect(err).NotTo(HaveOccurred()) Expect(fakeStatus).To(Equal(getStatuses)) @@ -108,9 +110,9 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { cniResult := &cnicurrent.Result{ CNIVersion: "0.3.1", Interfaces: []*cnicurrent.Interface{ - &cnicurrent.Interface{ - Name: "net1", - Mac: "92:79:27:01:7c:cf", + { + Name: "net1", + Mac: "92:79:27:01:7c:cf", Sandbox: "/proc/1123/ns/net", }, }, @@ -125,12 +127,24 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { }, }, } - status, err := CreateNetworkStatus(cniResult, "test-net-attach-def", false) + devInfo := v1.DeviceInfo{ + Type: "pci", + Version: "v1.0.0", + Pci: &v1.PciDevice{ + PciAddress: "0000:01:02.2", + PfPciAddress: "0000:01:02.0", + }, + } + status, err := CreateNetworkStatus(cniResult, "test-net-attach-def", false, &devInfo) Expect(err).NotTo(HaveOccurred()) Expect(status.Name).To(Equal("test-net-attach-def")) Expect(status.Interface).To(Equal("net1")) Expect(status.Mac).To(Equal("92:79:27:01:7c:cf")) - Expect(status.IPs).To(Equal([]string{ "1.1.1.3", "2001::1" })) + Expect(status.IPs).To(Equal([]string{"1.1.1.3", "2001::1"})) + Expect(status.DeviceInfo.Type).To(Equal("pci")) + Expect(status.DeviceInfo.Version).To(Equal("v1.0.0")) + Expect(status.DeviceInfo.Pci.PciAddress).To(Equal("0000:01:02.2")) + Expect(status.DeviceInfo.Pci.PfPciAddress).To(Equal("0000:01:02.0")) }) It("parse network selection element in pod", func() { @@ -140,16 +154,16 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { "interface": "test1" }]` expectedElement := []*v1.NetworkSelectionElement{ - &v1.NetworkSelectionElement{ - Name: "test-net-attach-def", + { + Name: "test-net-attach-def", InterfaceRequest: "test1", - Namespace: "fakeNamespace1", + Namespace: "fakeNamespace1", }, } fakePod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "fakePod1", + Name: "fakePod1", Namespace: "fakeNamespace1", Annotations: map[string]string{ "k8s.v1.cni.cncf.io/networks": selectionElement, @@ -158,7 +172,7 @@ var _ = Describe("Netwok Attachment Definition manipulations", func() { Spec: corev1.PodSpec{ Containers: []corev1.Container{ { - Name: "fakeContainer", + Name: "fakeContainer", Image: "fakeImage", }, },