diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml index b5b8a753b..aa21aa72b 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml @@ -270,6 +270,29 @@ spec: required: - type type: object + gpus: + description: List of GPU devices that need to be added + to the machines. + items: + properties: + deviceID: + description: deviceID is the id of the GPU entity. + format: int64 + type: integer + name: + description: name is the GPU name + type: string + type: + description: Type is the identifier type to use + for this resource. + enum: + - deviceID + - name + type: string + required: + - type + type: object + type: array image: description: |- image identifies the image uploaded to Prism Central (PC). The identifier diff --git a/api/v1alpha1/crds/caren.nutanix.com_nutanixnodeconfigs.yaml b/api/v1alpha1/crds/caren.nutanix.com_nutanixnodeconfigs.yaml index d06c890a8..f1944aca2 100644 --- a/api/v1alpha1/crds/caren.nutanix.com_nutanixnodeconfigs.yaml +++ b/api/v1alpha1/crds/caren.nutanix.com_nutanixnodeconfigs.yaml @@ -88,6 +88,29 @@ spec: required: - type type: object + gpus: + description: List of GPU devices that need to be added to + the machines. + items: + properties: + deviceID: + description: deviceID is the id of the GPU entity. + format: int64 + type: integer + name: + description: name is the GPU name + type: string + type: + description: Type is the identifier type to use for + this resource. + enum: + - deviceID + - name + type: string + required: + - type + type: object + type: array image: description: |- image identifies the image uploaded to Prism Central (PC). The identifier diff --git a/api/v1alpha1/nutanix_node_types.go b/api/v1alpha1/nutanix_node_types.go index fee282f8b..93ebb095c 100644 --- a/api/v1alpha1/nutanix_node_types.go +++ b/api/v1alpha1/nutanix_node_types.go @@ -60,6 +60,10 @@ type NutanixMachineDetails struct { // The project must already be present in the Prism Central. // +kubebuilder:validation:Optional Project *NutanixResourceIdentifier `json:"project,omitempty"` + + // List of GPU devices that need to be added to the machines. + // +kubebuilder:validation:Optional + GPUs []capxv1.NutanixGPU `json:"gpus,omitempty"` } // NutanixIdentifierType is an enumeration of different resource identifier types. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 7b3d6e685..1be9c1104 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -8,6 +8,7 @@ package v1alpha1 import ( + "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" @@ -935,6 +936,13 @@ func (in *NutanixMachineDetails) DeepCopyInto(out *NutanixMachineDetails) { *out = new(NutanixResourceIdentifier) (*in).DeepCopyInto(*out) } + if in.GPUs != nil { + in, out := &in.GPUs, &out.GPUs + *out = make([]v1beta1.NutanixGPU, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixMachineDetails. diff --git a/docs/content/customization/nutanix/machine-details.md b/docs/content/customization/nutanix/machine-details.md index 49a21d372..f0f3c8889 100644 --- a/docs/content/customization/nutanix/machine-details.md +++ b/docs/content/customization/nutanix/machine-details.md @@ -228,3 +228,46 @@ spec: type: name name: project-name ``` + +### (Optional) Add a GPU to a machine deployment + +```yaml +apiVersion: cluster.x-k8s.io/v1beta1 +kind: Cluster +metadata: + name: +spec: + topology: + variables: + - name: workerConfig + value: + nutanix: + machineDetails: + gpus: + - type: name + name: "Ampere 40" + workers: + - class: nutanix-quick-start-worker + metadata: + annotations: + cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size: "1" + cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size: "1" + name: gpu-0 +``` + +Applying this configuration will result in the following value being set: + +- control-plane `NutanixMachineTemplate`: + +```yaml +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: NutanixMachineTemplate +metadata: + name: nutanix-quick-start-gpu-nmt +spec: + template: + spec: + gpus: + - type: name + name: "Ampere 40" +``` diff --git a/pkg/handlers/nutanix/mutation/machinedetails/inject.go b/pkg/handlers/nutanix/mutation/machinedetails/inject.go index d7b8dca7a..3fbd631de 100644 --- a/pkg/handlers/nutanix/mutation/machinedetails/inject.go +++ b/pkg/handlers/nutanix/mutation/machinedetails/inject.go @@ -122,7 +122,11 @@ func (h *nutanixMachineDetailsPatchHandler) Mutate( capxv1.NutanixResourceIdentifier(*nutanixMachineDetailsVar.Project), ) } - + spec.GPUs = make( + []capxv1.NutanixGPU, + len(nutanixMachineDetailsVar.GPUs), + ) + copy(spec.GPUs, nutanixMachineDetailsVar.GPUs) obj.Spec.Template.Spec = spec return nil }, diff --git a/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go b/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go index 060b1a73d..3aef9e70b 100644 --- a/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go +++ b/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go @@ -55,9 +55,33 @@ var ( Type: capxv1.NutanixIdentifierName, Name: ptr.To("fake-project"), }), + GPUs: []capxv1.NutanixGPU{ + { + Type: "name", + Name: ptr.To("gpu1"), + }, + { + Type: "deviceID", + DeviceID: ptr.To(int64(1)), + }, + }, } matchersForAllFieldsSet = []capitest.JSONPatchMatcher{ + { + Operation: "add", + Path: "/spec/template/spec/gpus", + ValueMatcher: gomega.ContainElements( + gomega.SatisfyAll( + gomega.HaveKeyWithValue("type", "name"), + gomega.HaveKeyWithValue("name", "gpu1"), + ), + gomega.SatisfyAll( + gomega.HaveKeyWithValue("type", "deviceID"), + gomega.HaveKeyWithValue("deviceID", gomega.BeNumerically("==", 1)), + ), + ), + }, { Operation: "add", Path: "/spec/template/spec/bootType",