Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions crd/multitenancy/api/v1alpha1/nicnetworkconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//go:build !ignore_uncovered
// +build !ignore_uncovered

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Important: Run "make" to regenerate code after modifying this file

// +kubebuilder:object:root=true

// NICNetworkConfig is the Schema for the nicnetworkconfigs API
// +kubebuilder:resource:shortName=nicnc,scope=Namespaced
// +kubebuilder:subresource:status
// +kubebuilder:metadata:labels=managed=
// +kubebuilder:metadata:labels=owner=
// +kubebuilder:printcolumn:name="Node",type=string,JSONPath=`.spec.nodeName`
// +kubebuilder:printcolumn:name="NIC",type=string,JSONPath=`.spec.nicName`
// +kubebuilder:printcolumn:name="PodNetwork",type=string,JSONPath=`.spec.podNetwork`
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status`
type NICNetworkConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec NICNetworkConfigSpec `json:"spec,omitempty"`
Status NICNetworkConfigStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// NICNetworkConfigList contains a list of NICNetworkConfig
type NICNetworkConfigList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []NICNetworkConfig `json:"items"`
}

// NICNetworkConfigSpec defines the desired state of NICNetworkConfig
type NICNetworkConfigSpec struct {
// PodNetwork is the name of the PodNetwork
PodNetwork string `json:"podNetwork"`
// NodeName is the name of the node this NIC belongs to
NodeName string `json:"nodeName"`
// NICName is the name of the physical NIC on the node (e.g., eth1)
NICName string `json:"nicName"`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to device-id or macaddress

// SubnetID is the ARM resource ID of the subnet (e.g., /subscriptions/.../subnets/pod-subnet)
SubnetID string `json:"subnetID"`
// NetworkID is the VNET GUID or network identifier
NetworkID string `json:"networkID"`
// PodAllocations tracks which pods are allocated on this NIC
// +kubebuilder:validation:Optional
PodAllocations []PodAllocationRequest `json:"podAllocations,omitempty"`
}

// PodAllocationRequest represents a pod's IP allocation request on this NIC
type PodAllocationRequest struct {
// PodName is the name of the pod
PodName string `json:"podName"`
// PodNamespace is the namespace of the pod
PodNamespace string `json:"podNamespace"`
// MTPNC is the name of the MultitenantPodNetworkConfig
MTPNC string `json:"mtpnc"`
}

// PodAllocation represents a pod's IP allocation on this NIC
type PodAllocation struct {
// PodName is the name of the pod
PodName string `json:"podName"`
// PodNamespace is the namespace of the pod
PodNamespace string `json:"podNamespace"`
// AllocatedIP is the IP address allocated to the pod
AllocatedIP string `json:"allocatedIP"`
// MTPNC is the name of the MultitenantPodNetworkConfig
MTPNC string `json:"mtpnc"`
}

// NICNetworkConfigStatus defines the observed state of NICNetworkConfig
type NICNetworkConfigStatus struct {
// Status indicates the current status of the NIC Network Config
// +kubebuilder:validation:Enum=Ready;Pending;Error
Status NICNC `json:"status,omitempty"`
// NCID is the network container id created for this NIC
// +kubebuilder:validation:Optional
NCID string `json:"ncID,omitempty"`
// PrimaryIP is the primary IP allocated to the network container
// +kubebuilder:validation:Optional
PrimaryIP string `json:"primaryIP,omitempty"`
// MacAddress is the MAC Address of the VM's NIC
MacAddress string `json:"macAddress,omitempty"`
// GatewayIP is the gateway ip of the injected subnet
// +kubebuilder:validation:Optional
GatewayIP string `json:"gatewayIP,omitempty"`
// SubnetAddressSpace is the subnet address space of the injected subnet
// +kubebuilder:validation:Optional
SubnetAddressSpace string `json:"subnetAddressSpace,omitempty"`
// AvailableIPs tracks the available IP addresses in this NC block
// +kubebuilder:validation:Optional
AvailableIPs []string `json:"availableIPs,omitempty"`
// PodAllocations tracks the allocated IP addresses to pod mapping.
// +kubebuilder:validation:Optional
PodAllocations map[string]PodAllocation `json:"podAllocations,omitempty"`
// ErrorMessage contains error details if status is Error
// +kubebuilder:validation:Optional
ErrorMessage string `json:"errorMessage,omitempty"`
// CooldownPeriodInSeconds is the cooldown duration before retrying NIC NC operations.
// +kubebuilder:default=30
CooldownPeriodInSeconds int `json:"cooldownPeriodInSeconds,omitempty"`
// DeviceType is the device type that this NC was created for
DeviceType DeviceType `json:"deviceType,omitempty"`
// AccelnetEnabled determines if the CNI will provision the NIC with accelerated networking enabled
// +kubebuilder:validation:Optional
AccelnetEnabled bool `json:"accelnetEnabled,omitempty"`
}

// NICNC indicates the status of NIC Network Config
type NICNC string

const (
NICNCReady NICNC = "Ready"
NICNCPending NICNC = "Pending"
NICNCError NICNC = "Error"
)

func init() {
SchemeBuilder.Register(&NICNetworkConfig{}, &NICNetworkConfigList{})
}
6 changes: 3 additions & 3 deletions crd/multitenancy/api/v1alpha1/podnetwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ type PodNetworkStatus struct {
// +kubebuilder:validation:Optional
Status Status `json:"status,omitempty"`
AddressPrefixes []string `json:"addressPrefixes,omitempty"`
// PrefixBlockAllocationSize indicates the size of IP block allocated to the subnet
// +kubebuilder:default=16
PrefixBlockAllocationSize int `json:"prefixBlockAllocationSize,omitempty"`
// PrefixBlockCIDRLength indicates the prefix length of IP block allocated to the subnet
// +kubebuilder:default=28
PrefixBlockCIDRLength int `json:"prefixBlockCIDRLength,omitempty"`
}

func init() {
Expand Down
136 changes: 136 additions & 0 deletions crd/multitenancy/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions crd/multitenancy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,42 @@ func (i *Installer) InstallOrUpdatePodNetworkInstance(ctx context.Context) (*v1.
return current, nil
}

// Install installs the embedded NICNetworkConfig CRD definition in the cluster.
func (i *Installer) InstallNICNetworkConfig(ctx context.Context) (*v1.CustomResourceDefinition, error) {
nicNetworkConfig, err := GetNICNetworkConfigs()
if err != nil {
return nil, errors.Wrap(err, "failed to get embedded nicnetworkconfig crd")
}
return i.create(ctx, nicNetworkConfig)
}

// InstallOrUpdateNICNetworkConfig installs the embedded NICNetworkConfig CRD definition in the cluster or updates it if present.
func (i *Installer) InstallOrUpdateNICNetworkConfig(ctx context.Context) (*v1.CustomResourceDefinition, error) {
nicNetworkConfig, err := GetNICNetworkConfigs()
if err != nil {
return nil, errors.Wrap(err, "failed to get embedded nicnetworkconfig crd")
}
current, err := i.create(ctx, nicNetworkConfig)
if !apierrors.IsAlreadyExists(err) {
return current, err
}
if current == nil {
current, err = i.cli.Get(ctx, nicNetworkConfig.Name, metav1.GetOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to get existing nicnetworkconfig crd")
}
}
if !reflect.DeepEqual(nicNetworkConfig.Spec.Versions, current.Spec.Versions) {
nicNetworkConfig.SetResourceVersion(current.GetResourceVersion())
previous := *current
current, err = i.cli.Update(ctx, nicNetworkConfig, metav1.UpdateOptions{})
if err != nil {
return &previous, errors.Wrap(err, "failed to update existing nicnetworkconfig crd")
}
}
return current, nil
}

type NodeInfoClient struct {
Cli client.Client
}
Expand Down
15 changes: 15 additions & 0 deletions crd/multitenancy/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,18 @@ func GetPodNetworkInstances() (*apiextensionsv1.CustomResourceDefinition, error)
}
return podNetworkInstances, nil
}

// NICNetworkConfigsYAML embeds the CRD YAML for downstream consumers.
//
//go:embed manifests/multitenancy.acn.azure.com_nicnetworkconfigs.yaml
var NICNetworkConfigsYAML []byte

// GetNICNetworkConfigs parses the raw []byte NICNetworkConfigs in
// to a CustomResourceDefinition and returns it or an unmarshalling error.
func GetNICNetworkConfigs() (*apiextensionsv1.CustomResourceDefinition, error) {
nicNetworkConfigs := &apiextensionsv1.CustomResourceDefinition{}
if err := yaml.Unmarshal(NICNetworkConfigsYAML, &nicNetworkConfigs); err != nil {
return nil, errors.Wrap(err, "error unmarshalling embedded nicNetworkConfig")
}
return nicNetworkConfigs, nil
}
14 changes: 14 additions & 0 deletions crd/multitenancy/embed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const mtpncFilename = "manifests/multitenancy.acn.azure.com_multitenantpodnetworkconfigs.yaml"
Expand Down Expand Up @@ -58,3 +59,16 @@ func TestGetPodNetworkInstances(t *testing.T) {
_, err := GetPodNetworkInstances()
assert.NoError(t, err)
}

const nicNetworkConfigFilename = "manifests/multitenancy.acn.azure.com_nicnetworkconfigs.yaml"

func TestEmbedNICNetworkConfig(t *testing.T) {
b, err := os.ReadFile(nicNetworkConfigFilename)
require.NoError(t, err)
assert.YAMLEq(t, string(b), string(NICNetworkConfigsYAML))
}

func TestGetNICNetworkConfigs(t *testing.T) {
_, err := GetNICNetworkConfigs()
require.NoError(t, err)
}
Loading
Loading