Repository: metal3-io/baremetal-operator
Pull request #1480 (2023-12-05 13:52:58)

✨ Add an explicit way to auto-detect ChecksumType
In preparation for the eventual removal of MD5 checksums, add a new
ChecksumType "auto" that instructs IPA to detect the type

Requires IPA from the 2023.2 release series. Users with older IPA
should provide the algorithm explicitly.

Signed-off-by: Dmitry Tantsur <dtantsur@protonmail.com>

dtantsur: /test-centos-e2e-integration-main 
/test-ubuntu-integration-main 
metal3-io-bot: New changes are detected. LGTM label has been removed.
zaneb: I think I disagree with this change.

This is not about removing MD5, since it's still possible to specify MD5 explicitly.

The is about changing the type field from required to optional for SHA sums. That means that the same v1alpha1 CR may fail to work on older versions of Metal³ - or, as you acknowledge in the description, on the _same_ version of Metal³ with different versions of IPA. Essentially this is starting to leak Ironic API changes through into the BMH.

If we want to remove the type field in v1beta1 (which I'm fine with) we can still translate back to v1alpha1 when required in the webhook by using the same logic that Ironic does (checking the length of the sum) to determine the algorithm. As far as I can see, this change is not required to do that.
dtantsur: > we can still translate back to v1alpha1 when required in the webhook by using the same logic that Ironic does (checking the length of the sum)

We cannot, this logic is not trivial, and I don't want to replicate it there (it's not just length, there are many formats of downloadable checksums).

@zaneb would you be more okay with an explicit `auto` type as I initially planned? Otherwise, we'll have nothing to translate v1beta1 into.
dtantsur: Okay, this should no longer break the backward compatibility with older IPA.
dtantsur: /test-centos-e2e-integration-main
/test-ubuntu-integration-main
metal3-io-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/metal3-io/baremetal-operator/pull/1480#pullrequestreview-1767735163" title="LGTM">Rozzii</a>*, *<a href="https://github.com/metal3-io/baremetal-operator/pull/1480#pullrequestreview-1774113517" title="Approved">zaneb</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=metal3-io%2Fbaremetal-operator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/metal3-io/baremetal-operator/blob/main/OWNERS)~~ [zaneb]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_types.go b/apis/metal3.io/v1alpha1/baremetalhost_types.go
index 15189eac..af629b64 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_types.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_types.go
@@ -450,7 +450,7 @@ const (
 )
 
 // ChecksumType holds the algorithm name for the checksum
-// +kubebuilder:validation:Enum=md5;sha256;sha512
+// +kubebuilder:validation:Enum=md5;sha256;sha512;auto
 type ChecksumType string
 
 const (
@@ -462,6 +462,9 @@ const (
 
 	// SHA512 checksum type
 	SHA512 ChecksumType = "sha512"
+
+	// Automatically detect
+	AutoChecksum ChecksumType = "auto"
 )
 
 // Image holds the details of an image either to provisioned or that
@@ -473,8 +476,9 @@ type Image struct {
 	// Checksum is the checksum for the image.
 	Checksum string `json:"checksum,omitempty"`
 
-	// ChecksumType is the checksum algorithm for the image.
-	// e.g md5, sha256, sha512
+	// ChecksumType is the checksum algorithm for the image, e.g md5, sha256 or sha512.
+	// The special value "auto" can be used to detect the algorithm from the checksum.
+	// If missing, MD5 is used. If in doubt, use "auto".
 	ChecksumType ChecksumType `json:"checksumType,omitempty"`
 
 	// DiskFormat contains the format of the image (raw, qcow2, ...).
@@ -1096,6 +1100,8 @@ func (image *Image) GetChecksum() (checksum, checksumType string, ok bool) {
 		checksumType = string(MD5)
 	case MD5, SHA256, SHA512:
 		checksumType = string(image.ChecksumType)
+	case AutoChecksum:
+		// No type, let Ironic detect
 	default:
 		return
 	}
diff --git a/cmd/make-bm-worker/main.go b/cmd/make-bm-worker/main.go
index 5394d89b..5eac99d8 100644
--- a/cmd/make-bm-worker/main.go
+++ b/cmd/make-bm-worker/main.go
@@ -62,9 +62,9 @@ func main() {
 	}
 
 	switch *imageChecksumType {
-	case "", "md5", "sha256", "sha512":
+	case "", "md5", "sha256", "sha512", "auto":
 	default:
-		fmt.Fprintf(os.Stderr, "Invalid image checksum type %q, use \"md5\", \"sha256\" or \"sha512\"\n", *imageChecksumType)
+		fmt.Fprintf(os.Stderr, "Invalid image checksum type %q, use \"md5\", \"sha256\", \"sha512\" or \"auto\"\n", *imageChecksumType)
 		os.Exit(1)
 	}
 
diff --git a/config/base/crds/bases/metal3.io_baremetalhosts.yaml b/config/base/crds/bases/metal3.io_baremetalhosts.yaml
index 77a57565..d2aa2121 100644
--- a/config/base/crds/bases/metal3.io_baremetalhosts.yaml
+++ b/config/base/crds/bases/metal3.io_baremetalhosts.yaml
@@ -221,12 +221,15 @@ spec:
                     description: Checksum is the checksum for the image.
                     type: string
                   checksumType:
-                    description: ChecksumType is the checksum algorithm for the image.
-                      e.g md5, sha256, sha512
+                    description: ChecksumType is the checksum algorithm for the image,
+                      e.g md5, sha256 or sha512. The special value "auto" can be used
+                      to detect the algorithm from the checksum. If missing, MD5 is
+                      used. If in doubt, use "auto".
                     enum:
                     - md5
                     - sha256
                     - sha512
+                    - auto
                     type: string
                   format:
                     description: DiskFormat contains the format of the image (raw,
@@ -871,11 +874,14 @@ spec:
                         type: string
                       checksumType:
                         description: ChecksumType is the checksum algorithm for the
-                          image. e.g md5, sha256, sha512
+                          image, e.g md5, sha256 or sha512. The special value "auto"
+                          can be used to detect the algorithm from the checksum. If
+                          missing, MD5 is used. If in doubt, use "auto".
                         enum:
                         - md5
                         - sha256
                         - sha512
+                        - auto
                         type: string
                       format:
                         description: DiskFormat contains the format of the image (raw,
diff --git a/config/render/capm3.yaml b/config/render/capm3.yaml
index ba6d83f1..f013ce50 100644
--- a/config/render/capm3.yaml
+++ b/config/render/capm3.yaml
@@ -221,12 +221,15 @@ spec:
                     description: Checksum is the checksum for the image.
                     type: string
                   checksumType:
-                    description: ChecksumType is the checksum algorithm for the image.
-                      e.g md5, sha256, sha512
+                    description: ChecksumType is the checksum algorithm for the image,
+                      e.g md5, sha256 or sha512. The special value "auto" can be used
+                      to detect the algorithm from the checksum. If missing, MD5 is
+                      used. If in doubt, use "auto".
                     enum:
                     - md5
                     - sha256
                     - sha512
+                    - auto
                     type: string
                   format:
                     description: DiskFormat contains the format of the image (raw,
@@ -871,11 +874,14 @@ spec:
                         type: string
                       checksumType:
                         description: ChecksumType is the checksum algorithm for the
-                          image. e.g md5, sha256, sha512
+                          image, e.g md5, sha256 or sha512. The special value "auto"
+                          can be used to detect the algorithm from the checksum. If
+                          missing, MD5 is used. If in doubt, use "auto".
                         enum:
                         - md5
                         - sha256
                         - sha512
+                        - auto
                         type: string
                       format:
                         description: DiskFormat contains the format of the image (raw,
diff --git a/docs/api.md b/docs/api.md
index 5e9432b3..1f0ed8f1 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -91,8 +91,8 @@ The sub-fields are
 * *checksum* -- The actual checksum or a URL to a file containing
   the checksum for the image at *image.url*.
 * *checksumType* -- Checksum algorithms can be specified. Currently
-  only `md5`, `sha256`, `sha512` are recognized. If nothing is specified
-  `md5` is assumed.
+  only `md5`, `sha256`, `sha512` are recognized. Use `auto` to auto-detect
+  the algorithm from the value. If nothing is specified, `md5` is assumed.
 * *format* -- This is the disk format of the image. It can be one of `raw`,
   `qcow2`, `vdi`, `vmdk`, `live-iso` or be left unset.
   Setting it to raw enables raw image streaming in Ironic agent for that image.
diff --git a/go.mod b/go.mod
index 75e08da6..104858c6 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.17.0
 	github.com/stretchr/testify v1.8.4
-	go.etcd.io/etcd/client/pkg/v3 v3.5.11
+	go.etcd.io/etcd/client/pkg/v3 v3.5.10
 	go.uber.org/zap v1.26.0
 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
 	k8s.io/api v0.27.7
diff --git a/go.sum b/go.sum
index 7a348be2..c470351e 100644
--- a/go.sum
+++ b/go.sum
@@ -143,8 +143,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A=
-go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
+go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0=
+go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index 88ed19e0..45b4d1b2 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -965,26 +965,21 @@ func (p *ironicProvisioner) setDirectDeployUpdateOptsForNode(ironicNode *nodes.N
 		return
 	}
 
-	// FIXME: For older versions of ironic that do not have
-	// https://review.opendev.org/#/c/711816/ failing to include the
-	// 'image_checksum' causes ironic to refuse to provision the
-	// image, even if the other hash value parameters are given. We
-	// only want to do that for MD5, however, because those versions
-	// of ironic only support MD5 checksums.
-	var legacyChecksum *string
-	if checksumType == string(metal3api.MD5) {
-		legacyChecksum = &checksum
-	}
-
 	optValues := optionsData{
 		// Remove any boot_iso field
-		"boot_iso": nil,
+		"boot_iso":          nil,
+		"image_source":      imageData.URL,
+		"image_disk_format": imageData.DiskFormat,
+	}
 
-		"image_source":        imageData.URL,
-		"image_os_hash_algo":  checksumType,
-		"image_os_hash_value": checksum,
-		"image_checksum":      legacyChecksum,
-		"image_disk_format":   imageData.DiskFormat,
+	if checksumType == "" {
+		optValues["image_checksum"] = checksum
+		optValues["image_os_hash_algo"] = nil
+		optValues["image_os_hash_value"] = nil
+	} else {
+		optValues["image_checksum"] = nil
+		optValues["image_os_hash_algo"] = checksumType
+		optValues["image_os_hash_value"] = checksum
 	}
 	updater.
 		SetInstanceInfoOpts(optValues, ironicNode)
@@ -1282,15 +1277,24 @@ func (p *ironicProvisioner) ironicHasSameImage(ironicNode *nodes.Node, image met
 			"provisionState", ironicNode.ProvisionState)
 	} else {
 		checksum, checksumType, _ := image.GetChecksum()
-		sameImage = (ironicNode.InstanceInfo["image_source"] == image.URL &&
-			ironicNode.InstanceInfo["image_os_hash_algo"] == checksumType &&
-			ironicNode.InstanceInfo["image_os_hash_value"] == checksum)
+		if checksumType == "" {
+			sameImage = (ironicNode.InstanceInfo["image_source"] == image.URL &&
+				ironicNode.InstanceInfo["image_checksum"] == checksum &&
+				ironicNode.InstanceInfo["image_os_hash_algo"] == nil &&
+				ironicNode.InstanceInfo["image_os_hash_value"] == nil)
+		} else {
+			sameImage = (ironicNode.InstanceInfo["image_source"] == image.URL &&
+				ironicNode.InstanceInfo["image_checksum"] == nil &&
+				ironicNode.InstanceInfo["image_os_hash_algo"] == checksumType &&
+				ironicNode.InstanceInfo["image_os_hash_value"] == checksum)
+		}
 		p.log.Info("checking image settings",
 			"source", ironicNode.InstanceInfo["image_source"],
-			"image_os_hash_algo", checksumType,
-			"image_os_has_value", checksum,
+			"checksumType", checksumType,
+			"checksum", checksum,
 			"same", sameImage,
-			"provisionState", ironicNode.ProvisionState)
+			"provisionState", ironicNode.ProvisionState,
+			"iinfo", ironicNode.InstanceInfo)
 	}
 	return sameImage
 }


Test patch:
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_types_test.go b/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
index 5e1435a6..815dccdc 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
@@ -317,9 +317,10 @@ func TestCredentialStatusMatch(t *testing.T) {
 
 func TestGetImageChecksum(t *testing.T) {
 	for _, tc := range []struct {
-		Scenario string
-		Host     BareMetalHost
-		Expected bool
+		Scenario     string
+		Host         BareMetalHost
+		Expected     bool
+		ExpectedType string
 	}{
 		{
 			Scenario: "both checksum value and type specified",
@@ -335,7 +336,8 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected: true,
+			Expected:     true,
+			ExpectedType: "md5",
 		},
 		{
 			Scenario: "checksum value specified but not type",
@@ -350,7 +352,25 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected: true,
+			Expected:     true,
+			ExpectedType: "md5",
+		},
+		{
+			Scenario: "checksum value specified, auto type",
+			Host: BareMetalHost{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "myhost",
+					Namespace: "myns",
+				},
+				Spec: BareMetalHostSpec{
+					Image: &Image{
+						Checksum:     "md5hash",
+						ChecksumType: AutoChecksum,
+					},
+				},
+			},
+			Expected:     true,
+			ExpectedType: "",
 		},
 		{
 			Scenario: "sha256 checksum value and type specified",
@@ -366,7 +386,8 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected: true,
+			Expected:     true,
+			ExpectedType: "sha256",
 		},
 		{
 			Scenario: "sha512 checksum value and type specified",
@@ -382,7 +403,8 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected: true,
+			Expected:     true,
+			ExpectedType: "sha512",
 		},
 		{
 			Scenario: "checksum value not specified",
@@ -443,9 +465,10 @@ func TestGetImageChecksum(t *testing.T) {
 		},
 	} {
 		t.Run(tc.Scenario, func(t *testing.T) {
-			_, _, actual := tc.Host.Spec.Image.GetChecksum()
-			if actual != tc.Expected {
-				t.Errorf("expected %v but got %v", tc.Expected, actual)
+			_, checksumType, actual := tc.Host.Spec.Image.GetChecksum()
+			assert.Equal(t, tc.Expected, actual)
+			if tc.Expected {
+				assert.Equal(t, tc.ExpectedType, checksumType)
 			}
 		})
 	}
diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh
index 5597c5b1..1288f377 100755
--- a/hack/ci-e2e.sh
+++ b/hack/ci-e2e.sh
@@ -21,7 +21,6 @@ BMO_E2E_EMULATOR=${BMO_E2E_EMULATOR:-"sushy-tools"}
 "${REPO_ROOT}/hack/e2e/ensure_go.sh"
 export PATH="${PATH}:/usr/local/go/bin"
 "${REPO_ROOT}/hack/e2e/ensure_minikube.sh"
-"${REPO_ROOT}/hack/e2e/ensure_htpasswd.sh"
 # CAPI test framework uses kubectl in the background
 "${REPO_ROOT}/hack/e2e/ensure_kubectl.sh"
 
@@ -48,7 +47,6 @@ minikube image load quay.io/metal3-io/baremetal-operator:e2e
 # Create libvirt domain
 VM_NAME="bmo-e2e-0"
 export BOOT_MAC_ADDRESS="00:60:2f:31:81:01"
-SERIAL_LOG_PATH="/var/log/libvirt/qemu/${VM_NAME}-serial0.log"
 
 virt-install \
   --connect qemu:///system \
@@ -59,11 +57,8 @@ virt-install \
   --vcpus=2 \
   --disk size=20 \
   --graphics=none \
-  --console pty,target_type=serial \
-  --serial file,path="${SERIAL_LOG_PATH}" \
-  --xml "./devices/serial/@type=pty" \
-  --xml "./devices/serial/log/@file=${SERIAL_LOG_PATH}" \
-  --xml "./devices/serial/log/@append=on" \
+  --console pty \
+  --serial pty \
   --pxe \
   --network network=baremetal-e2e,mac="${BOOT_MAC_ADDRESS}" \
   --noautoconsole
@@ -158,11 +153,6 @@ set +e
 make test-e2e
 test_status="$?"
 
-LOGS_DIR="${REPO_ROOT}/test/e2e/_artifacts/logs"
-mkdir -p "${LOGS_DIR}/qemu"
-sudo sh -c "cp -r /var/log/libvirt/qemu/* ${LOGS_DIR}/qemu/"
-sudo chown -R "${USER}:${USER}" "${LOGS_DIR}/qemu"
-
 # Collect all artifacts
 tar --directory test/e2e/ -czf artifacts.tar.gz _artifacts
 
diff --git a/hack/e2e/ensure_htpasswd.sh b/hack/e2e/ensure_htpasswd.sh
deleted file mode 100755
index f37b2599..00000000
--- a/hack/e2e/ensure_htpasswd.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -eux
-
-# Check if htpasswd is installed and install it if not
-verify_htpasswd()
-{
-    if ! [ -x "$(command -v htpasswd)" ]; then
-        echo "htpasswd could not be found, installing..."
-        sudo apt-get update
-        sudo apt-get install -y apache2-utils
-    fi
-}
-
-verify_htpasswd
diff --git a/pkg/provisioner/ironic/provision_test.go b/pkg/provisioner/ironic/provision_test.go
index 121b0d99..a859a222 100644
--- a/pkg/provisioner/ironic/provision_test.go
+++ b/pkg/provisioner/ironic/provision_test.go
@@ -343,6 +343,20 @@ func TestIronicHasSameImage(t *testing.T) {
 			hostChecksum:     "thechecksum",
 			hostChecksumType: v1alpha1.MD5,
 		},
+		{
+			name:      "image same - auto checksum",
+			expected:  true,
+			liveImage: false,
+			node: nodes.Node{
+				InstanceInfo: map[string]interface{}{
+					"image_source":   "theimage",
+					"image_checksum": "thechecksum",
+				},
+			},
+			hostImage:        "theimage",
+			hostChecksum:     "thechecksum",
+			hostChecksumType: "auto",
+		},
 		{
 			name:      "image different",
 			expected:  false,
@@ -373,6 +387,21 @@ func TestIronicHasSameImage(t *testing.T) {
 			hostChecksum:     "different",
 			hostChecksumType: v1alpha1.MD5,
 		},
+		{
+			name:      "image checksum changed to auto",
+			expected:  false,
+			liveImage: false,
+			node: nodes.Node{
+				InstanceInfo: map[string]interface{}{
+					"image_source":        "theimage",
+					"image_os_hash_value": "thechecksum",
+					"image_os_hash_algo":  "md5",
+				},
+			},
+			hostImage:        "theimage",
+			hostChecksum:     "thechecksum",
+			hostChecksumType: "auto",
+		},
 		{
 			name:      "image checksum type different",
 			expected:  false,
diff --git a/pkg/provisioner/ironic/validatemanagementaccess_test.go b/pkg/provisioner/ironic/validatemanagementaccess_test.go
index eb1f99e6..072e58b5 100644
--- a/pkg/provisioner/ironic/validatemanagementaccess_test.go
+++ b/pkg/provisioner/ironic/validatemanagementaccess_test.go
@@ -153,6 +153,7 @@ func TestValidateManagementAccessCreateWithImage(t *testing.T) {
 	host.Status.Provisioning.ID = "" // so we don't lookup by uuid
 	host.Spec.Image.URL = "theimagefoo"
 	host.Spec.Image.Checksum = "thechecksumxyz"
+	host.Spec.Image.ChecksumType = "auto"
 
 	var createdNode *nodes.Node
 
@@ -391,14 +392,35 @@ func TestValidateManagementAccessExistingSteadyStateNoUpdate(t *testing.T) {
 		},
 		{
 			Image: &metal3api.Image{
-				URL:      "theimage",
-				Checksum: "thechecksum",
+				URL:          "theimage",
+				Checksum:     "thechecksum",
+				ChecksumType: "auto",
+			},
+			InstanceInfo: map[string]interface{}{
+				"image_source":   "theimage",
+				"image_checksum": "thechecksum",
+				"capabilities":   map[string]interface{}{},
+			},
+			DriverInfo: map[string]interface{}{
+				"force_persistent_boot_device": "Default",
+				"deploy_kernel":                "http://deploy.test/ipa.kernel",
+				"deploy_ramdisk":               "http://deploy.test/ipa.initramfs",
+				"test_address":                 "test.bmc",
+				"test_username":                "",
+				"test_password":                "******", // ironic returns a placeholder
+				"test_port":                    "42",
+			},
+		},
+		{
+			Image: &metal3api.Image{
+				URL:          "theimage",
+				Checksum:     "thechecksum",
+				ChecksumType: "sha256",
 			},
 			InstanceInfo: map[string]interface{}{
 				"image_source":        "theimage",
-				"image_os_hash_algo":  "md5",
+				"image_os_hash_algo":  "sha256",
 				"image_os_hash_value": "thechecksum",
-				"image_checksum":      "thechecksum",
 				"capabilities":        map[string]interface{}{},
 			},
 			DriverInfo: map[string]interface{}{
diff --git a/test/e2e/basic_provisioning_test.go b/test/e2e/basic_provisioning_test.go
index be3ae82b..86a88b9f 100644
--- a/test/e2e/basic_provisioning_test.go
+++ b/test/e2e/basic_provisioning_test.go
@@ -83,8 +83,9 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 		helper, err := patch.NewHelper(&bmh, clusterProxy.GetClient())
 		Expect(err).NotTo(HaveOccurred())
 		bmh.Spec.Image = &metal3api.Image{
-			URL:      e2eConfig.GetVariable("IMAGE_URL"),
-			Checksum: e2eConfig.GetVariable("IMAGE_CHECKSUM"),
+			URL:          e2eConfig.GetVariable("IMAGE_URL"),
+			Checksum:     e2eConfig.GetVariable("IMAGE_CHECKSUM"),
+			ChecksumType: metal3api.AutoChecksum,
 		}
 		bmh.Spec.RootDeviceHints = &metal3api.RootDeviceHints{
 			DeviceName: "/dev/vda",