Skip to content

Commit d27a160

Browse files
committed
Validate device path in baremetal IPI rootDeviceHints
When a deviceName is provided in the root device hints in the install-config, check that it is one that could actually match, just as we do in the Metal³ webhook since metal3-io/baremetal-operator#1264.
1 parent a95ac5a commit d27a160

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

pkg/types/baremetal/validation/platform.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,38 @@ func validateBootMode(hosts []*baremetal.Host, fldPath *field.Path) (errors fiel
366366
return
367367
}
368368

369+
// ValidateHostRootDeviceHints checks that a rootDeviceHints field contains no
370+
// invalid values.
371+
func ValidateHostRootDeviceHints(rdh *baremetal.RootDeviceHints, fldPath *field.Path) (errors field.ErrorList) {
372+
if rdh == nil || rdh.DeviceName == "" {
373+
return
374+
}
375+
devField := fldPath.Child("deviceName")
376+
subpath := strings.TrimPrefix(rdh.DeviceName, "/dev/")
377+
if rdh.DeviceName == subpath {
378+
errors = append(errors, field.Invalid(devField, rdh.DeviceName,
379+
"Device Name of root device hint must be a /dev/ path"))
380+
}
381+
382+
subpath = strings.TrimPrefix(subpath, "disk/by-path/")
383+
if strings.Contains(subpath, "/") {
384+
errors = append(errors, field.Invalid(devField, rdh.DeviceName,
385+
"Device Name of root device hint must be path in /dev/ or /dev/disk/by-path/"))
386+
}
387+
return
388+
}
389+
390+
// ensure that none of the rootDeviceHints fields contain invalid values.
391+
func validateRootDeviceHints(hosts []*baremetal.Host, fldPath *field.Path) (errors field.ErrorList) {
392+
for idx, host := range hosts {
393+
if host == nil || host.RootDeviceHints == nil {
394+
continue
395+
}
396+
errors = append(errors, ValidateHostRootDeviceHints(host.RootDeviceHints, fldPath.Index(idx).Child("rootDeviceHints"))...)
397+
}
398+
return
399+
}
400+
369401
// validateProvisioningNetworkDisabledSupported validates hosts bmc address support provisioning network is disabled
370402
func validateProvisioningNetworkDisabledSupported(hosts []*baremetal.Host, fldPath *field.Path) (errors field.ErrorList) {
371403
for idx, host := range hosts {
@@ -419,6 +451,7 @@ func ValidatePlatform(p *baremetal.Platform, agentBasedInstallation bool, n *typ
419451
}
420452
allErrs = append(allErrs, validateHostsWithoutBMC(p.Hosts, fldPath)...)
421453
allErrs = append(allErrs, validateBootMode(p.Hosts, fldPath.Child("Hosts"))...)
454+
allErrs = append(allErrs, validateRootDeviceHints(p.Hosts, fldPath.Child("Hosts"))...)
422455
allErrs = append(allErrs, validateNetworkConfig(p.Hosts, fldPath.Child("Hosts"))...)
423456

424457
allErrs = append(allErrs, validateHostsName(p.Hosts, fldPath.Child("Hosts"))...)

pkg/types/baremetal/validation/platform_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,62 @@ interfaces:
359359
}
360360
}
361361

362+
func TestValidateHostRootDeviceHints(t *testing.T) {
363+
cases := []struct {
364+
name string
365+
rootDeviceHints *baremetal.RootDeviceHints
366+
expectedSuccess bool
367+
}{
368+
{
369+
name: "nil hints",
370+
expectedSuccess: true,
371+
},
372+
{
373+
name: "no hints",
374+
rootDeviceHints: &baremetal.RootDeviceHints{},
375+
expectedSuccess: true,
376+
},
377+
{
378+
name: "non /dev path",
379+
rootDeviceHints: &baremetal.RootDeviceHints{
380+
DeviceName: "sda",
381+
},
382+
},
383+
{
384+
name: "/dev path",
385+
rootDeviceHints: &baremetal.RootDeviceHints{
386+
DeviceName: "/dev/sda",
387+
},
388+
expectedSuccess: true,
389+
},
390+
{
391+
name: "by-path path",
392+
rootDeviceHints: &baremetal.RootDeviceHints{
393+
DeviceName: "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0",
394+
},
395+
expectedSuccess: true,
396+
},
397+
{
398+
name: "by-id path",
399+
rootDeviceHints: &baremetal.RootDeviceHints{
400+
DeviceName: "/dev/disk/by-id/wwn-0x600508e000000000ce506dc50ab0ad05",
401+
},
402+
},
403+
}
404+
405+
for _, tc := range cases {
406+
t.Run(tc.name, func(t *testing.T) {
407+
errs := ValidateHostRootDeviceHints(tc.rootDeviceHints, field.NewPath("rootDeviceHints"))
408+
409+
if tc.expectedSuccess {
410+
assert.Empty(t, errs)
411+
} else {
412+
assert.NotEmpty(t, errs)
413+
}
414+
})
415+
}
416+
}
417+
362418
func TestValidateProvisioning(t *testing.T) {
363419
//Used for url validations
364420
imagesServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

0 commit comments

Comments
 (0)