Skip to content

Commit 8126b0a

Browse files
committed
introduce preprovisioningKernelParams to BMH
This commit: - Implements a new spec field of the BMH resource and implements related reconciliation logic in the bare metal host controller - Extends Ironic node update to servicing and preparing states too - Renames getInstanceUpdateOpts to getProvisioningInstanceUpdateOptsForNode to provide a more explicit name for the function and make it consistent with other UpdateOptsForNode type functions - Adds support to provide kernel arguments to for the PreProvisioningImage CR Notes: - The new spec field is optional and not using it should provide the same UX as older BMO versions - Kernel pre provisioning arguments can't be changed when a node transitions from inspected (available) state to provisioning state if Ironic is configured to fast-track deployments. Signed-off-by: Adam Rozman <adam.rozman@est.tech> combine extra kernel params from different sources This commit: - Combines the extra kernel params from both BMH and the PreprovisioningImage CRs. Signed-off-by: Adam Rozman <adam.rozman@est.tech>
1 parent 5fe4a63 commit 8126b0a

20 files changed

Lines changed: 281 additions & 190 deletions

apis/metal3.io/v1alpha1/baremetalhost_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,11 @@ type BareMetalHostSpec struct {
484484
// without hardware profiles.
485485
HardwareProfile string `json:"hardwareProfile,omitempty"`
486486

487+
// The value of the kernel commandline argument list that will be passed
488+
// to the pre provisioning agent's kernel during boot.
489+
// +optional
490+
PreprovisioningExtraKernelParams string `json:"preprovisioningExtraKernelParams,omitempty"`
491+
487492
// Provide guidance about how to choose the device for the image
488493
// being provisioned. The default is currently to use /dev/sda as
489494
// the root device.

config/base/crds/bases/metal3.io_baremetalhosts.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,11 @@ spec:
344344
state (e.g. provisioned), its power state will be forced to match
345345
this value.
346346
type: boolean
347+
preprovisioningExtraKernelParams:
348+
description: |-
349+
The value of the kernel commandline argument list that will be passed
350+
to the pre provisioning agent's kernel during boot.
351+
type: string
347352
preprovisioningNetworkDataName:
348353
description: |-
349354
PreprovisioningNetworkDataName is the name of the Secret in the

config/render/capm3.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,11 @@ spec:
344344
state (e.g. provisioned), its power state will be forced to match
345345
this value.
346346
type: boolean
347+
preprovisioningExtraKernelParams:
348+
description: |-
349+
The value of the kernel commandline argument list that will be passed
350+
to the pre provisioning agent's kernel during boot.
351+
type: string
347352
preprovisioningNetworkDataName:
348353
description: |-
349354
PreprovisioningNetworkDataName is the name of the Secret in the

internal/controller/metal3.io/baremetalhost_controller.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,33 @@ func (info *reconcileInfo) publishEvent(reason, message string) {
8484
info.events = append(info.events, info.host.NewEvent(reason, message))
8585
}
8686

87+
// return the PreprovisioningExtraKernelParams from the reconciliation info.
88+
func (r *BareMetalHostReconciler) retrievePreprovisioningExtraKernelParamsSpec(ctx context.Context, info *reconcileInfo, prov provisioner.Provisioner) string {
89+
if info == nil || info.host == nil {
90+
return ""
91+
}
92+
kernelExtraPreprovParams := info.host.Spec.PreprovisioningExtraKernelParams
93+
preprovImgFormats, err := prov.PreprovisioningImageFormats()
94+
if err != nil {
95+
return kernelExtraPreprovParams
96+
}
97+
preprovImg, err := r.getPreprovImage(ctx, info, preprovImgFormats)
98+
if err != nil {
99+
return kernelExtraPreprovParams
100+
}
101+
// Make sure kernel extra params coming from dynamically generater preprov
102+
// Image are also represented in every life cycle operation
103+
if preprovImg != nil {
104+
trimmedParams := strings.TrimSpace(kernelExtraPreprovParams)
105+
if trimmedParams == "" {
106+
kernelExtraPreprovParams = preprovImg.GeneratedImage.ExtraKernelParams
107+
} else {
108+
kernelExtraPreprovParams += " " + preprovImg.GeneratedImage.ExtraKernelParams
109+
}
110+
}
111+
return kernelExtraPreprovParams
112+
}
113+
87114
// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts,verbs=get;list;watch;create;update;patch;delete
88115
// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts/status,verbs=get;update;patch
89116
// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts/finalizers,verbs=update
@@ -871,16 +898,17 @@ func (r *BareMetalHostReconciler) registerHost(ctx context.Context, prov provisi
871898
provResult, provID, err := prov.Register(
872899
ctx,
873900
provisioner.ManagementAccessData{
874-
BootMode: info.host.Status.Provisioning.BootMode,
875-
AutomatedCleaningMode: info.host.Spec.AutomatedCleaningMode,
876-
State: info.host.Status.Provisioning.State,
877-
OperationalStatus: info.host.Status.OperationalStatus,
878-
CurrentImage: getCurrentImage(info.host),
879-
PreprovisioningImage: preprovImg,
880-
PreprovisioningNetworkData: preprovisioningNetworkData,
881-
HasCustomDeploy: hasCustomDeploy(info.host),
882-
DisablePowerOff: info.host.Spec.DisablePowerOff,
883-
CPUArchitecture: getHostArchitecture(info.host),
901+
BootMode: info.host.Status.Provisioning.BootMode,
902+
AutomatedCleaningMode: info.host.Spec.AutomatedCleaningMode,
903+
State: info.host.Status.Provisioning.State,
904+
OperationalStatus: info.host.Status.OperationalStatus,
905+
CurrentImage: getCurrentImage(info.host),
906+
PreprovisioningImage: preprovImg,
907+
PreprovisioningNetworkData: preprovisioningNetworkData,
908+
PreprovisioningExtraKernelParams: r.retrievePreprovisioningExtraKernelParamsSpec(ctx, info, prov),
909+
HasCustomDeploy: hasCustomDeploy(info.host),
910+
DisablePowerOff: info.host.Spec.DisablePowerOff,
911+
CPUArchitecture: getHostArchitecture(info.host),
884912
},
885913
credsChanged,
886914
info.host.Status.ErrorType == metal3api.RegistrationError)

pkg/hardwareutils/bmc/access.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ type AccessDetails interface {
6868
// pre-populated with the access information, and the caller is
6969
// expected to add any other information that might be needed
7070
// (such as the kernel and ramdisk locations).
71-
DriverInfo(bmcCreds Credentials) map[string]interface{}
71+
DriverInfo(bmcCreds Credentials, preprovExtraKernelArgs string) map[string]interface{}
7272

7373
BIOSInterface() string
7474

pkg/hardwareutils/bmc/access_test.go

Lines changed: 95 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -464,189 +464,205 @@ func TestDriverInfo(t *testing.T) {
464464
Scenario: "ipmi default port",
465465
input: "ipmi://192.168.122.1",
466466
expects: map[string]interface{}{
467-
"ipmi_port": ipmiDefaultPort,
468-
"ipmi_password": "",
469-
"ipmi_username": "",
470-
"ipmi_address": "192.168.122.1",
471-
"ipmi_verify_ca": false,
472-
"ipmi_priv_level": "ADMINISTRATOR",
467+
"ipmi_port": ipmiDefaultPort,
468+
"ipmi_password": "",
469+
"ipmi_username": "",
470+
"ipmi_address": "192.168.122.1",
471+
"ipmi_verify_ca": false,
472+
"ipmi_priv_level": "ADMINISTRATOR",
473+
"kernel_append_params": "",
473474
},
474475
},
475476

476477
{
477478
Scenario: "ipmi setting privilege level",
478479
input: "ipmi://192.168.122.1?privilegelevel=OPERATOR",
479480
expects: map[string]interface{}{
480-
"ipmi_port": ipmiDefaultPort,
481-
"ipmi_password": "",
482-
"ipmi_username": "",
483-
"ipmi_address": "192.168.122.1",
484-
"ipmi_verify_ca": false,
485-
"ipmi_priv_level": "OPERATOR",
481+
"ipmi_port": ipmiDefaultPort,
482+
"ipmi_password": "",
483+
"ipmi_username": "",
484+
"ipmi_address": "192.168.122.1",
485+
"ipmi_verify_ca": false,
486+
"ipmi_priv_level": "OPERATOR",
487+
"kernel_append_params": "",
486488
},
487489
},
488490

489491
{
490492
Scenario: "Redfish",
491493
input: "redfish://192.168.122.1/redfish/v1/foo/bar",
492494
expects: map[string]interface{}{
493-
"redfish_address": "https://192.168.122.1",
494-
"redfish_system_id": "/redfish/v1/foo/bar",
495-
"redfish_password": "",
496-
"redfish_username": "",
497-
"redfish_verify_ca": false,
495+
"redfish_address": "https://192.168.122.1",
496+
"redfish_system_id": "/redfish/v1/foo/bar",
497+
"redfish_password": "",
498+
"redfish_username": "",
499+
"redfish_verify_ca": false,
500+
"kernel_append_params": "",
498501
},
499502
},
500503

501504
{
502505
Scenario: "Redfish http",
503506
input: "redfish+http://192.168.122.1/foo/bar",
504507
expects: map[string]interface{}{
505-
"redfish_address": "http://192.168.122.1",
506-
"redfish_system_id": "/foo/bar",
507-
"redfish_password": "",
508-
"redfish_username": "",
509-
"redfish_verify_ca": false,
508+
"redfish_address": "http://192.168.122.1",
509+
"redfish_system_id": "/foo/bar",
510+
"redfish_password": "",
511+
"redfish_username": "",
512+
"redfish_verify_ca": false,
513+
"kernel_append_params": "",
510514
},
511515
},
512516

513517
{
514518
Scenario: "Redfish https",
515519
input: "redfish+https://192.168.122.1/foo/bar",
516520
expects: map[string]interface{}{
517-
"redfish_address": "https://192.168.122.1",
518-
"redfish_system_id": "/foo/bar",
519-
"redfish_password": "",
520-
"redfish_username": "",
521-
"redfish_verify_ca": false,
521+
"redfish_address": "https://192.168.122.1",
522+
"redfish_system_id": "/foo/bar",
523+
"redfish_password": "",
524+
"redfish_username": "",
525+
"redfish_verify_ca": false,
526+
"kernel_append_params": "",
522527
},
523528
},
524529

525530
{
526531
Scenario: "Redfish port",
527532
input: "redfish://192.168.122.1:8080/foo/bar",
528533
expects: map[string]interface{}{
529-
"redfish_address": "https://192.168.122.1:8080",
530-
"redfish_system_id": "/foo/bar",
531-
"redfish_password": "",
532-
"redfish_username": "",
533-
"redfish_verify_ca": false,
534+
"redfish_address": "https://192.168.122.1:8080",
535+
"redfish_system_id": "/foo/bar",
536+
"redfish_password": "",
537+
"redfish_username": "",
538+
"redfish_verify_ca": false,
539+
"kernel_append_params": "",
534540
},
535541
},
536542

537543
{
538544
Scenario: "Redfish ipv6",
539545
input: "redfish://[fe80::fc33:62ff:fe83:8a76]/foo/bar",
540546
expects: map[string]interface{}{
541-
"redfish_address": "https://[fe80::fc33:62ff:fe83:8a76]",
542-
"redfish_system_id": "/foo/bar",
543-
"redfish_password": "",
544-
"redfish_username": "",
545-
"redfish_verify_ca": false,
547+
"redfish_address": "https://[fe80::fc33:62ff:fe83:8a76]",
548+
"redfish_system_id": "/foo/bar",
549+
"redfish_password": "",
550+
"redfish_username": "",
551+
"redfish_verify_ca": false,
552+
"kernel_append_params": "",
546553
},
547554
},
548555

549556
{
550557
Scenario: "Redfish ipv6 port",
551558
input: "redfish://[fe80::fc33:62ff:fe83:8a76]:8080/foo",
552559
expects: map[string]interface{}{
553-
"redfish_address": "https://[fe80::fc33:62ff:fe83:8a76]:8080",
554-
"redfish_system_id": "/foo",
555-
"redfish_password": "",
556-
"redfish_username": "",
557-
"redfish_verify_ca": false,
560+
"redfish_address": "https://[fe80::fc33:62ff:fe83:8a76]:8080",
561+
"redfish_system_id": "/foo",
562+
"redfish_password": "",
563+
"redfish_username": "",
564+
"redfish_verify_ca": false,
565+
"kernel_append_params": "",
558566
},
559567
},
560568

561569
{
562570
Scenario: "Redfish no system ID",
563571
input: "redfish+https://192.168.122.1/",
564572
expects: map[string]interface{}{
565-
"redfish_address": "https://192.168.122.1",
566-
"redfish_password": "",
567-
"redfish_username": "",
568-
"redfish_verify_ca": false,
573+
"redfish_address": "https://192.168.122.1",
574+
"redfish_password": "",
575+
"redfish_username": "",
576+
"redfish_verify_ca": false,
577+
"kernel_append_params": "",
569578
},
570579
},
571580

572581
{
573582
Scenario: "Redfish wrong system ID",
574583
input: "redfish+https://192.168.122.1/redfish/v1/",
575584
expects: map[string]interface{}{
576-
"redfish_address": "https://192.168.122.1",
577-
"redfish_password": "",
578-
"redfish_username": "",
579-
"redfish_verify_ca": false,
585+
"redfish_address": "https://192.168.122.1",
586+
"redfish_password": "",
587+
"redfish_username": "",
588+
"redfish_verify_ca": false,
589+
"kernel_append_params": "",
580590
},
581591
},
582592

583593
{
584594
Scenario: "Redfish virtual media",
585595
input: "redfish-virtualmedia://192.168.122.1/redfish/v1/foo/bar",
586596
expects: map[string]interface{}{
587-
"redfish_address": "https://192.168.122.1",
588-
"redfish_system_id": "/redfish/v1/foo/bar",
589-
"redfish_password": "",
590-
"redfish_username": "",
591-
"redfish_verify_ca": false,
597+
"redfish_address": "https://192.168.122.1",
598+
"redfish_system_id": "/redfish/v1/foo/bar",
599+
"redfish_password": "",
600+
"redfish_username": "",
601+
"redfish_verify_ca": false,
602+
"kernel_append_params": "",
592603
},
593604
},
594605

595606
{
596607
Scenario: "Redfish virtual media wrong system ID",
597608
input: "redfish-virtualmedia://192.168.122.1/redfish/v1/",
598609
expects: map[string]interface{}{
599-
"redfish_address": "https://192.168.122.1",
600-
"redfish_password": "",
601-
"redfish_username": "",
602-
"redfish_verify_ca": false,
610+
"redfish_address": "https://192.168.122.1",
611+
"redfish_password": "",
612+
"redfish_username": "",
613+
"redfish_verify_ca": false,
614+
"kernel_append_params": "",
603615
},
604616
},
605617

606618
{
607619
Scenario: "ilo5 virtual media",
608620
input: "ilo5-virtualmedia://192.168.122.1/foo/bar",
609621
expects: map[string]interface{}{
610-
"redfish_address": "https://192.168.122.1",
611-
"redfish_system_id": "/foo/bar",
612-
"redfish_password": "",
613-
"redfish_username": "",
614-
"redfish_verify_ca": false,
622+
"redfish_address": "https://192.168.122.1",
623+
"redfish_system_id": "/foo/bar",
624+
"redfish_password": "",
625+
"redfish_username": "",
626+
"redfish_verify_ca": false,
627+
"kernel_append_params": "",
615628
},
616629
},
617630

618631
{
619632
Scenario: "idrac redfish",
620633
input: "idrac-redfish://192.168.122.1/foo/bar",
621634
expects: map[string]interface{}{
622-
"redfish_address": "https://192.168.122.1",
623-
"redfish_system_id": "/foo/bar",
624-
"redfish_password": "",
625-
"redfish_username": "",
626-
"redfish_verify_ca": false,
635+
"redfish_address": "https://192.168.122.1",
636+
"redfish_system_id": "/foo/bar",
637+
"redfish_password": "",
638+
"redfish_username": "",
639+
"redfish_verify_ca": false,
640+
"kernel_append_params": "",
627641
},
628642
},
629643

630644
{
631645
Scenario: "idrac virtual media",
632646
input: "idrac-virtualmedia://192.168.122.1/redfish/v1/foo/bar",
633647
expects: map[string]interface{}{
634-
"redfish_address": "https://192.168.122.1",
635-
"redfish_system_id": "/redfish/v1/foo/bar",
636-
"redfish_password": "",
637-
"redfish_username": "",
638-
"redfish_verify_ca": false,
648+
"redfish_address": "https://192.168.122.1",
649+
"redfish_system_id": "/redfish/v1/foo/bar",
650+
"redfish_password": "",
651+
"redfish_username": "",
652+
"redfish_verify_ca": false,
653+
"kernel_append_params": "",
639654
},
640655
},
641656

642657
{
643658
Scenario: "idrac virtual media wrong system ID",
644659
input: "idrac-virtualmedia://192.168.122.1/redfish/v1/",
645660
expects: map[string]interface{}{
646-
"redfish_address": "https://192.168.122.1",
647-
"redfish_password": "",
648-
"redfish_username": "",
649-
"redfish_verify_ca": false,
661+
"redfish_address": "https://192.168.122.1",
662+
"redfish_password": "",
663+
"redfish_username": "",
664+
"redfish_verify_ca": false,
665+
"kernel_append_params": "",
650666
},
651667
},
652668
} {
@@ -655,7 +671,7 @@ func TestDriverInfo(t *testing.T) {
655671
if err != nil {
656672
t.Fatalf("unexpected parse error: %v", err)
657673
}
658-
di := acc.DriverInfo(Credentials{})
674+
di := acc.DriverInfo(Credentials{}, "")
659675
// If a key is present when it should not, this will catch it
660676
if len(di) != len(tc.expects) {
661677
t.Fatalf("Number of items do not match: %v and %v, %#v", len(di),

0 commit comments

Comments
 (0)