Skip to content

Commit

Permalink
Merge pull request metal3-io#1019 from zaneb/preprov-image-accept-for…
Browse files Browse the repository at this point in the history
…mats

Use PreprovisioningImage to build PXE images
  • Loading branch information
metal3-io-bot authored Nov 16, 2021
2 parents deaf07b + 94942dd commit c22cb7b
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 28 deletions.
4 changes: 4 additions & 0 deletions apis/metal3.io/v1alpha1/preprovisioningimage_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type PreprovisioningImageSpec struct {
// architecture is the processor architecture for which to build the image.
// +optional
Architecture string `json:"architecture,omitempty"`

// acceptFormats is a list of acceptable image formats.
// +optional
AcceptFormats []ImageFormat `json:"acceptFormats,omitempty"`
}

type SecretStatus struct {
Expand Down
7 changes: 6 additions & 1 deletion apis/metal3.io/v1alpha1/zz_generated.deepcopy.go

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

9 changes: 9 additions & 0 deletions config/crd/bases/metal3.io_preprovisioningimages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ spec:
spec:
description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage
properties:
acceptFormats:
description: acceptFormats is a list of acceptable image formats.
items:
description: ImageFormat enumerates the allowed image formats
enum:
- iso
- initrd
type: string
type: array
architecture:
description: architecture is the processor architecture for which
to build the image.
Expand Down
9 changes: 9 additions & 0 deletions config/render/capm3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,15 @@ spec:
spec:
description: PreprovisioningImageSpec defines the desired state of PreprovisioningImage
properties:
acceptFormats:
description: acceptFormats is a list of acceptable image formats.
items:
description: ImageFormat enumerates the allowed image formats
enum:
- iso
- initrd
type: string
type: array
architecture:
description: architecture is the processor architecture for which
to build the image.
Expand Down
14 changes: 14 additions & 0 deletions controllers/metal3.io/baremetalhost_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,19 @@ func (r *BareMetalHostReconciler) preprovImageAvailable(info *reconcileInfo, ima
return false, nil
}

validFormat := false
for _, f := range image.Spec.AcceptFormats {
if image.Status.Format == f {
validFormat = true
break
}
}
if !validFormat {
info.log.Info("pre-provisioning image format not accepted",
"format", image.Status.Format)
return false, nil
}

if image.Spec.NetworkDataName != "" {
secretKey := client.ObjectKey{
Name: image.Spec.NetworkDataName,
Expand Down Expand Up @@ -688,6 +701,7 @@ func (r *BareMetalHostReconciler) getPreprovImage(info *reconcileInfo, formats [
expectedSpec := metal3v1alpha1.PreprovisioningImageSpec{
NetworkDataName: info.host.Spec.PreprovisioningNetworkDataName,
Architecture: getHostArchitecture(info.host),
AcceptFormats: formats,
}

preprovImage := metal3v1alpha1.PreprovisioningImage{}
Expand Down
97 changes: 91 additions & 6 deletions controllers/metal3.io/baremetalhost_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2126,13 +2126,15 @@ func TestGetPreprovImageCreateUpdate(t *testing.T) {
func TestGetPreprovImage(t *testing.T) {
host := newDefaultHost(t)
imageURL := "http://example.test/image.iso"
acceptFormats := []metal3v1alpha1.ImageFormat{metal3v1alpha1.ImageFormatISO, metal3v1alpha1.ImageFormatInitRD}
image := &metal3v1alpha1.PreprovisioningImage{
ObjectMeta: metav1.ObjectMeta{
Name: host.Name,
Namespace: namespace,
},
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
Architecture: "x86_64",
AcceptFormats: acceptFormats,
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Expand All @@ -2153,7 +2155,7 @@ func TestGetPreprovImage(t *testing.T) {
r := newTestReconciler(host, image)
i := makeReconcileInfo(host)

imgData, err := r.getPreprovImage(i, []metal3v1alpha1.ImageFormat{metal3v1alpha1.ImageFormatISO})
imgData, err := r.getPreprovImage(i, acceptFormats)
assert.NoError(t, err)
assert.NotNil(t, imgData)
assert.Equal(t, imageURL, imgData.ImageURL)
Expand Down Expand Up @@ -2209,7 +2211,8 @@ func TestPreprovImageAvailable(t *testing.T) {
{
Scenario: "ready no netdata",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Expand All @@ -2231,6 +2234,7 @@ func TestPreprovImageAvailable(t *testing.T) {
Scenario: "ready",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
NetworkDataName: "network_secret_1",
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Expand All @@ -2253,10 +2257,65 @@ func TestPreprovImageAvailable(t *testing.T) {
},
Available: true,
},
{
Scenario: "ready initrd",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"initrd"},
NetworkDataName: "network_secret_1",
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Format: "initrd",
NetworkData: metal3v1alpha1.SecretStatus{
Name: "network_secret_1",
Version: "1000",
},
Conditions: []metav1.Condition{
{
Type: string(metal3v1alpha1.ConditionImageReady),
Status: metav1.ConditionTrue,
},
{
Type: string(metal3v1alpha1.ConditionImageError),
Status: metav1.ConditionFalse,
},
},
},
Available: true,
},
{
Scenario: "ready initrd fallback",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
NetworkDataName: "network_secret_1",
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Format: "initrd",
NetworkData: metal3v1alpha1.SecretStatus{
Name: "network_secret_1",
Version: "1000",
},
Conditions: []metav1.Condition{
{
Type: string(metal3v1alpha1.ConditionImageReady),
Status: metav1.ConditionTrue,
},
{
Type: string(metal3v1alpha1.ConditionImageError),
Status: metav1.ConditionFalse,
},
},
},
Available: true,
},
{
Scenario: "ready secret outdated",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
NetworkDataName: "network_secret_1",
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Expand All @@ -2283,6 +2342,7 @@ func TestPreprovImageAvailable(t *testing.T) {
Scenario: "ready secret mismatch",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
NetworkDataName: "network_secret_1",
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Expand All @@ -2308,7 +2368,8 @@ func TestPreprovImageAvailable(t *testing.T) {
{
Scenario: "ready arch mismatch",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "aarch64",
Architecture: "aarch64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Expand All @@ -2327,9 +2388,32 @@ func TestPreprovImageAvailable(t *testing.T) {
Available: false,
},
{
Scenario: "not ready",
Scenario: "ready format mismatch",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"initrd"},
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Format: "iso",
Conditions: []metav1.Condition{
{
Type: string(metal3v1alpha1.ConditionImageReady),
Status: metav1.ConditionTrue,
},
{
Type: string(metal3v1alpha1.ConditionImageError),
Status: metav1.ConditionFalse,
},
},
},
Available: false,
},
{
Scenario: "not ready",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Expand All @@ -2350,7 +2434,8 @@ func TestPreprovImageAvailable(t *testing.T) {
{
Scenario: "failed",
Spec: metal3v1alpha1.PreprovisioningImageSpec{
Architecture: "x86_64",
Architecture: "x86_64",
AcceptFormats: []metal3v1alpha1.ImageFormat{"iso", "initrd"},
},
Status: metal3v1alpha1.PreprovisioningImageStatus{
Architecture: "x86_64",
Expand Down
37 changes: 28 additions & 9 deletions controllers/metal3.io/preprovisioningimage_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (r *PreprovisioningImageReconciler) Reconcile(ctx context.Context, req ctrl
func (r *PreprovisioningImageReconciler) update(img *metal3.PreprovisioningImage, log logr.Logger) (bool, error) {
generation := img.GetGeneration()

url, format, errorMessage := getImageURL()
url, format, errorMessage := getImageURL(img.Spec.AcceptFormats)
if errorMessage != "" {
log.Info("no suitable image URL available", "preferredFormat", format)
return setError(generation, &img.Status, reasonImageConfigurationError, errorMessage), nil
Expand All @@ -116,12 +116,26 @@ func (r *PreprovisioningImageReconciler) update(img *metal3.PreprovisioningImage
return false, err
}

func getImageURL() (url string, format metal3.ImageFormat, errorMessage string) {
format = metal3.ImageFormatISO
if iso := os.Getenv("DEPLOY_ISO_URL"); iso != "" {
url = iso
} else {
errorMessage = "No DEPLOY_ISO_URL specified"
func getImageURL(acceptFormats []metal3.ImageFormat) (url string, format metal3.ImageFormat, errorMessage string) {
for _, fmt := range acceptFormats {
switch fmt {
case metal3.ImageFormatISO:
if iso := os.Getenv("DEPLOY_ISO_URL"); iso != "" {
return iso, fmt, ""
}
if errorMessage == "" {
format = fmt
errorMessage = "No DEPLOY_ISO_URL specified"
}
case metal3.ImageFormatInitRD:
if initrd := os.Getenv("DEPLOY_RAMDISK_URL"); initrd != "" {
return initrd, fmt, ""
}
if errorMessage == "" {
format = fmt
errorMessage = "No DEPLOY_RAMDISK_URL specified"
}
}
}
return
}
Expand Down Expand Up @@ -218,11 +232,16 @@ func setError(generation int64, status *metal3.PreprovisioningImageStatus, reaso
}

func (r *PreprovisioningImageReconciler) CanStart() bool {
deployKernelURL := os.Getenv("DEPLOY_KERNEL_URL")
deployRamdiskURL := os.Getenv("DEPLOY_RAMDISK_URL")
deployISOURL := os.Getenv("DEPLOY_ISO_URL")
hasCfg := deployISOURL != ""
hasCfg := (deployISOURL != "" ||
(deployKernelURL != "" && deployRamdiskURL != ""))
if hasCfg {
r.Log.Info("have deploy image data",
"iso_url", deployISOURL)
"iso_url", deployISOURL,
"ramdisk_url", deployRamdiskURL,
"kernel_url", deployKernelURL)
} else {
r.Log.Info("not starting preprovisioning image controller; no image data available")
}
Expand Down
10 changes: 0 additions & 10 deletions pkg/provisioner/ironic/ironic.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,14 +554,6 @@ func (p *ironicProvisioner) PreprovisioningImageFormats() ([]metal3v1alpha1.Imag
var formats []metal3v1alpha1.ImageFormat
if accessDetails.SupportsISOPreprovisioningImage() {
formats = append(formats, metal3v1alpha1.ImageFormatISO)
} else {
if p.config.deployKernelURL != "" && p.config.deployRamdiskURL != "" {
// This is a PXE driver (no ISO support) so it shouldn't require any
// network customisation to boot the image, and we have sufficient
// data available to configure. Therefore, do not request an image
// build.
return nil, nil
}
}
if p.config.deployKernelURL != "" {
formats = append(formats, metal3v1alpha1.ImageFormatInitRD)
Expand Down Expand Up @@ -611,8 +603,6 @@ func setDeployImage(driverInfo map[string]interface{}, config ironicConfig, acce
deployImageInfo[deployISOKey] = config.deployISOURL
return deployImageInfo
}
}
if !config.havePreprovImgBuilder || !allowISO {
if allowInitRD && config.deployRamdiskURL != "" {
deployImageInfo[deployKernelKey] = config.deployKernelURL
deployImageInfo[deployRamdiskKey] = config.deployRamdiskURL
Expand Down
4 changes: 2 additions & 2 deletions pkg/provisioner/ironic/validatemanagementaccess_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ func TestPreprovisioningImageFormats(t *testing.T) {
Name: "enabled ipmi",
Address: "ipmi://example.test",
PreprovImgEnabled: true,
Expected: nil,
Expected: []metal3v1alpha1.ImageFormat{"initrd"},
},
{
Name: "enabled virtualmedia",
Expand Down Expand Up @@ -978,7 +978,7 @@ func TestSetDeployImage(t *testing.T) {
},
ExpectBuild: false,
ExpectISO: false,
ExpectPXE: true,
ExpectPXE: false,
},
{
Scenario: "pxe build no kernel",
Expand Down

0 comments on commit c22cb7b

Please sign in to comment.