Skip to content

Commit a637856

Browse files
Feat: Adding bootType for NutanixMachineTemplate (#9714)
* adding boottype to machineconfig nutanix * Adding bootyType for NutanixMachine VMs * bootype in cp-template * bootype in cp-template * adding unit-test for bootType * adding unit-test for bootType * addressing comments by shivendra * addressing commnets by Ilya * adding unit tests * Update pkg/providers/nutanix/validator_test.go Co-authored-by: Copilot <[email protected]> * adddressing comments by Rahul' --------- Co-authored-by: Copilot <[email protected]>
1 parent 9830a75 commit a637856

21 files changed

+951
-0
lines changed

config/crd/bases/anywhere.eks.amazonaws.com_nutanixmachineconfigs.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ spec:
6060
- value
6161
type: object
6262
type: array
63+
bootType:
64+
description: BootType defines the boot type of the VM. Allowed values legacy, uefi
65+
enum:
66+
- legacy
67+
- uefi
68+
type: string
6369
cluster:
6470
description: |-
6571
cluster is to identify the cluster (the Prism Element under management

config/manifest/eksa-components.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5924,6 +5924,14 @@ spec:
59245924
- value
59255925
type: object
59265926
type: array
5927+
bootType:
5928+
description: |-
5929+
bootType is the type of the VM boot device. The default value is
5930+
"legacy". The other option is "uefi".
5931+
enum:
5932+
- legacy
5933+
- uefi
5934+
type: string
59275935
cluster:
59285936
description: |-
59295937
cluster is to identify the cluster (the Prism Element under management

docs/content/en/docs/getting-started/nutanix/nutanix-spec.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ metadata:
113113
name: mgmt-cp-machine
114114
namespace: default
115115
spec:
116+
bootType: legacy
116117
cluster:
117118
name: nx-cluster-01
118119
type: name
@@ -144,6 +145,7 @@ metadata:
144145
name: mgmt-etcd
145146
namespace: default
146147
spec:
148+
bootType: legacy
147149
cluster:
148150
name: nx-cluster-01
149151
type: name
@@ -172,6 +174,7 @@ metadata:
172174
name: mgmt-machine
173175
namespace: default
174176
spec:
177+
bootType: legacy
175178
cluster:
176179
name: nx-cluster-01
177180
type: name
@@ -335,6 +338,9 @@ Optional list of valid and properly formatted IP addresses and IP address ranges
335338

336339
## NutanixMachineConfig Fields
337340

341+
### bootType (optional)
342+
BootType defines the boot type of the VM. Allowed values legacy, uefi
343+
338344
### cluster (required)
339345
Reference to the Prism Element cluster.
340346

internal/pkg/api/nutanix.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,25 @@ func WithNutanixMachineVCPUsPerSocket(value int32) NutanixFiller {
120120
}
121121
}
122122

123+
// WithNutanixMachineBootType returns a NutanixFiller that sets the boot type for the Nutanix machine.
124+
func WithNutanixMachineBootType(value anywherev1.NutanixBootType) NutanixFiller {
125+
return func(config *NutanixConfig) {
126+
if config == nil || config.machineConfigs == nil {
127+
return
128+
}
129+
if value != anywherev1.NutanixBootTypeLegacy && value != anywherev1.NutanixBootTypeUEFI {
130+
logger.Info("Warning: Invalid BootType value. BootType must be either 'legacy' or 'uefi'")
131+
return
132+
}
133+
for _, m := range config.machineConfigs {
134+
if m == nil {
135+
continue
136+
}
137+
m.Spec.BootType = value
138+
}
139+
}
140+
}
141+
123142
// WithNutanixMachineVCPUSocket returns a NutanixFiller that sets the vCPU sockets for the Nutanix machine.
124143
func WithNutanixMachineVCPUSocket(value int32) NutanixFiller {
125144
return func(config *NutanixConfig) {

internal/pkg/api/nutanix_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func TestNutanixMachineConfigFillers(t *testing.T) {
3333
WithNutanixMachineMemorySize("4Gi")(conf)
3434
WithNutanixMachineVCPUSocket(2)(conf)
3535
WithNutanixMachineVCPUsPerSocket(2)(conf)
36+
WithNutanixMachineBootType(anywherev1.NutanixBootTypeLegacy)(conf)
3637
WithNutanixMachineSystemDiskSize("20Gi")(conf)
3738
WithNutanixSubnetName("testSubnet")(conf)
3839
WithNutanixPrismElementClusterName("testCluster")(conf)
@@ -53,6 +54,7 @@ func TestNutanixMachineConfigFillers(t *testing.T) {
5354
g.Expect(*machineConfig.Spec.Image.Name).To(Equal("testImage"))
5455
g.Expect(machineConfig.Spec.Users[0].SshAuthorizedKeys[0]).To(Equal("testKey"))
5556
g.Expect(machineConfig.Spec.OSFamily).To(Equal(anywherev1.Ubuntu))
57+
g.Expect(machineConfig.Spec.BootType).To(Equal(anywherev1.NutanixBootTypeLegacy))
5658
}
5759

5860
WithNutanixSubnetUUID("90ad37a4-6dc0-4ae7-bcb3-a121dfb3fffa")(conf)

pkg/api/v1alpha1/nutanixmachineconfig.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ type NutanixIdentifierType string
1313
// NutanixGPUIdentifierType is an enumeration of different GPU identifier types.
1414
type NutanixGPUIdentifierType string
1515

16+
// NutanixBootType is an enumeration of different boot types.
17+
type NutanixBootType string
18+
1619
func (c NutanixIdentifierType) String() string {
1720
return string(c)
1821
}
@@ -35,6 +38,12 @@ const (
3538
// NutanixGPUIdentifierName is a GPU identifier identifying the object by Name.
3639
NutanixGPUIdentifierName NutanixGPUIdentifierType = "name"
3740

41+
// NutanixBootTypeLegacy is a resource identifier identifying the legacy boot type for virtual machines.
42+
NutanixBootTypeLegacy NutanixBootType = "legacy"
43+
44+
// NutanixBootTypeUEFI is a resource identifier identifying the UEFI boot type for virtual machines.
45+
NutanixBootTypeUEFI NutanixBootType = "uefi"
46+
3847
defaultNutanixOSFamily = Ubuntu
3948
defaultNutanixSystemDiskSizeGi = "40Gi"
4049
defaultNutanixMemorySizeGi = "4Gi"
@@ -123,6 +132,7 @@ func NewNutanixMachineConfigGenerate(name string, opts ...NutanixMachineConfigGe
123132
Cluster: NutanixResourceIdentifier{Type: NutanixIdentifierName, Name: func() *string { s := fmt.Sprintf(enterNameString, "Prism Element cluster"); return &s }()},
124133
Subnet: NutanixResourceIdentifier{Type: NutanixIdentifierName, Name: func() *string { s := fmt.Sprintf(enterNameString, "subnet"); return &s }()},
125134
SystemDiskSize: resource.MustParse(defaultNutanixSystemDiskSizeGi),
135+
BootType: NutanixBootTypeLegacy,
126136
},
127137
}
128138

@@ -190,6 +200,10 @@ func validateNutanixMachineConfig(c *NutanixMachineConfig) error {
190200
)
191201
}
192202

203+
if c.Spec.BootType != "" && c.Spec.BootType != NutanixBootTypeLegacy && c.Spec.BootType != NutanixBootTypeUEFI {
204+
return fmt.Errorf("NutanixMachineConfig: unsupported boot type (%v); Please use one of the following: %s, %s", c.Spec.BootType, NutanixBootTypeLegacy, NutanixBootTypeUEFI)
205+
}
206+
193207
if err := validateMachineConfigUsers(c.Name, NutanixMachineConfigKind, c.Spec.Users); err != nil {
194208
return err
195209
}

pkg/api/v1alpha1/nutanixmachineconfig_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func TestGetNutanixMachineConfigsValidConfig(t *testing.T) {
2626
Namespace: "default",
2727
},
2828
Spec: v1alpha1.NutanixMachineConfigSpec{
29+
BootType: v1alpha1.NutanixBootTypeLegacy,
2930
SystemDiskSize: resource.MustParse("40Gi"),
3031
MemorySize: resource.MustParse("8Gi"),
3132
VCPUSockets: 4,

pkg/api/v1alpha1/nutanixmachineconfig_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ type NutanixMachineConfigSpec struct {
6363
// List of GPU devices that should be added to the VMs.
6464
// +kubebuilder:validation:Optional
6565
GPUs []NutanixGPUIdentifier `json:"gpus,omitempty"`
66+
67+
// BootType defines the boot type of the VM. Allowed values: legacy, uefi
68+
// +kubebuilder:validation:Optional
69+
// +kubebuilder:validation:Enum=legacy;uefi
70+
BootType NutanixBootType `json:"bootType,omitempty"`
6671
}
6772

6873
// SetDefaults sets defaults to NutanixMachineConfig if user has not provided.

pkg/api/v1alpha1/nutanixmachineconfig_webhook.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ func (in *NutanixMachineConfig) ValidateDelete() (admission.Warnings, error) {
9191
func validateImmutableFieldsNutantixMachineConfig(new, old *NutanixMachineConfig) field.ErrorList {
9292
var allErrs field.ErrorList
9393
specPath := field.NewPath("spec")
94+
if !reflect.DeepEqual(new.Spec.BootType, old.Spec.BootType) {
95+
allErrs = append(allErrs, field.Forbidden(specPath.Child("bootType"), "field is immutable"))
96+
}
97+
9498
if new.Spec.OSFamily != old.Spec.OSFamily {
9599
allErrs = append(allErrs, field.Forbidden(specPath.Child("OSFamily"), "field is immutable"))
96100
}
@@ -125,6 +129,10 @@ func validateImmutableFieldsNutantixMachineConfig(new, old *NutanixMachineConfig
125129
func validateImmutableFieldsControlPlane(new, old *NutanixMachineConfig) field.ErrorList {
126130
var allErrs field.ErrorList
127131
specPath := field.NewPath("spec")
132+
if !reflect.DeepEqual(new.Spec.BootType, old.Spec.BootType) {
133+
allErrs = append(allErrs, field.Forbidden(specPath.Child("bootType"), "field is immutable"))
134+
}
135+
128136
if !reflect.DeepEqual(new.Spec.VCPUSockets, old.Spec.VCPUSockets) {
129137
allErrs = append(allErrs, field.Forbidden(specPath.Child("vCPUSockets"), "field is immutable"))
130138
}

pkg/api/v1alpha1/nutanixmachineconfig_webhook_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func nutanixMachineConfig() *v1alpha1.NutanixMachineConfig {
2020
OSFamily: v1alpha1.Ubuntu,
2121
VCPUsPerSocket: 2,
2222
VCPUSockets: 4,
23+
BootType: v1alpha1.NutanixBootTypeLegacy,
2324
MemorySize: resource.MustParse("8Gi"),
2425
Image: v1alpha1.NutanixResourceIdentifier{
2526
Type: v1alpha1.NutanixIdentifierName,
@@ -70,6 +71,12 @@ func TestValidateCreate_Invalid(t *testing.T) {
7071
name string
7172
fn func(*v1alpha1.NutanixMachineConfig)
7273
}{
74+
{
75+
name: "invalid bootType",
76+
fn: func(config *v1alpha1.NutanixMachineConfig) {
77+
config.Spec.BootType = "invalid"
78+
},
79+
},
7380
{
7481
name: "invalid name",
7582
fn: func(config *v1alpha1.NutanixMachineConfig) {
@@ -230,6 +237,13 @@ func TestValidateUpdate_Invalid(t *testing.T) {
230237
new.Spec.OSFamily = v1alpha1.Bottlerocket
231238
},
232239
},
240+
{
241+
name: "different bootType",
242+
fn: func(newConfig *v1alpha1.NutanixMachineConfig, oldConfig *v1alpha1.NutanixMachineConfig) {
243+
oldConfig.SetControlPlane()
244+
newConfig.Spec.BootType = v1alpha1.NutanixBootTypeUEFI
245+
},
246+
},
233247
{
234248
name: "different cluster",
235249
fn: func(new *v1alpha1.NutanixMachineConfig, old *v1alpha1.NutanixMachineConfig) {
@@ -292,6 +306,13 @@ func TestValidateUpdate_Invalid(t *testing.T) {
292306
})
293307
},
294308
},
309+
{
310+
name: "invalid bootType for control plane cluster",
311+
fn: func(newConfig *v1alpha1.NutanixMachineConfig, oldConfig *v1alpha1.NutanixMachineConfig) {
312+
oldConfig.SetControlPlane()
313+
newConfig.Spec.BootType = "invalid"
314+
},
315+
},
295316
{
296317
name: "invalid vcpus per socket",
297318
fn: func(new *v1alpha1.NutanixMachineConfig, old *v1alpha1.NutanixMachineConfig) {

0 commit comments

Comments
 (0)