Repository: metal3-io/baremetal-operator
Pull request #1494 (2023-12-18 13:00:31)

🌱 E2E: Have a common function to install BMO and Ironic
This PR refactors and uses a common function to install ironic and bmo. This will be useful later should we have to install other stuff with kustomize.

metal3-io-bot: Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with `/test all`
metal3-io-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please assign [zaneb](https://github.com/zaneb) for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

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

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

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

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":["zaneb"]} -->
mquhuy: /metal3-bmo-e2e-test
metal3-io-bot: @mquhuy: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
gofmt | 7b945908770d2912e302d05d59f8c92556a8fe53 | [link](https://prow.apps.test.metal3.io/view/s3/prow-logs/pr-logs/pull/metal3-io_baremetal-operator/1494/gofmt/1736734619501334528) | true | `/test gofmt`

[Full PR test history](https://prow.apps.test.metal3.io/pr-history?org=metal3-io&repo=baremetal-operator&pr=1494). [Your PR dashboard](https://prow.apps.test.metal3.io/pr?query=is:pr+state:open+author:mquhuy).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
metal3-io-bot: @mquhuy: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
gofmt | 7b945908770d2912e302d05d59f8c92556a8fe53 | [link](https://prow.apps.test.metal3.io/view/s3/prow-logs/pr-logs/pull/metal3-io_baremetal-operator/1494/gofmt/1736734619501334528) | true | `/test gofmt`
golint | 7b945908770d2912e302d05d59f8c92556a8fe53 | [link](https://prow.apps.test.metal3.io/view/s3/prow-logs/pr-logs/pull/metal3-io_baremetal-operator/1494/golint/1736734620117897216) | true | `/test golint`

[Full PR test history](https://prow.apps.test.metal3.io/pr-history?org=metal3-io&repo=baremetal-operator&pr=1494). [Your PR dashboard](https://prow.apps.test.metal3.io/pr?query=is:pr+state:open+author:mquhuy).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
mquhuy: /metal3-bmo-e2e-test
metal3-io-bot: @mquhuy: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
gofmt | 5252a21598b9060727e357d27c9a3f471d1d947f | [link](https://prow.apps.test.metal3.io/view/s3/prow-logs/pr-logs/pull/metal3-io_baremetal-operator/1494/gofmt/1737789999778107392) | true | `/test gofmt`

[Full PR test history](https://prow.apps.test.metal3.io/pr-history?org=metal3-io&repo=baremetal-operator&pr=1494). [Your PR dashboard](https://prow.apps.test.metal3.io/pr?query=is:pr+state:open+author:mquhuy).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
lentzi90: /metal3-bmo-e2e-test
metal3-io-bot: New changes are detected. LGTM label has been removed.
mquhuy: /metal3-bmo-e2e-test
mquhuy: /metal3-bmo-e2e-test
mquhuy: /cc @zaneb @kashifest @Rozzii 
mquhuy: /cc @tuminoid @smoshiur1237 
maxrantil: Nice, I like :)
mquhuy: /test-ubuntu-integration-main
/test-centos-e2e-integration-main 
metal3-io-bot: New changes are detected. LGTM label has been removed.

Patch:
diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml
index dedd4f2f..011a7b7d 100644
--- a/.github/workflows/dependabot.yml
+++ b/.github/workflows/dependabot.yml
@@ -23,7 +23,7 @@ jobs:
       id: vars
       run: echo "go_version=$(make go-version)" >> $GITHUB_OUTPUT
     - name: Set up Go
-      uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
+      uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
       with:
         go-version: ${{ steps.vars.outputs.go_version }}
     - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
diff --git a/.github/workflows/kubesec.yml b/.github/workflows/kubesec.yml
index bd354a10..e5213e8d 100644
--- a/.github/workflows/kubesec.yml
+++ b/.github/workflows/kubesec.yml
@@ -59,6 +59,6 @@ jobs:
 
       - name: Upload Kubesec scan results to GitHub Security tab
         if: ${{ steps.save_result.outputs.result != '[]' }}
-        uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
+        uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
         with:
           sarif_file: ${{ matrix.value }}.sarif
diff --git a/.github/workflows/pr-verifier.yaml b/.github/workflows/pr-verifier.yaml
index 8f1f100f..eaa1e9ec 100644
--- a/.github/workflows/pr-verifier.yaml
+++ b/.github/workflows/pr-verifier.yaml
@@ -14,6 +14,6 @@ jobs:
     steps:
     - name: Verifier action
       id: verifier
-      uses: kubernetes-sigs/kubebuilder-release-tools@012269a88fa4c034a0acf1ba84c26b195c0dbab4 # v0.4.3
+      uses: kubernetes-sigs/kubebuilder-release-tools@3c3411345eedc489d1022288aa844691e92a9c29 # v0.4.2
       with:
         github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index a2016d20..64186e5a 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -25,7 +25,7 @@ jobs:
         with:
           fetch-depth: 0
       - name: Install go
-        uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
+        uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
         with:
           go-version: '1.20'
       - name: Generate release notes
diff --git a/README.md b/README.md
index e20596fb..1a277a56 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
 # Bare Metal Operator
 
 [![CLOMonitor](https://img.shields.io/endpoint?url=https://clomonitor.io/api/projects/cncf/metal3-io/badge)](https://clomonitor.io/projects/cncf/metal3-io)
-[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/metal3-io/baremetal-operator/badge)](https://securityscorecards.dev/viewer/?uri=github.com/metal3-io/baremetal-operator)
 [![Ubuntu daily main build status](https://jenkins.nordix.org/buildStatus/icon?job=metal3_daily_main_integration_test_ubuntu&subject=Ubuntu%20daily%20main)](https://jenkins.nordix.org/view/Metal3/job/metal3_daily_main_integration_test_ubuntu/)
 [![CentOS daily main build status](https://jenkins.nordix.org/buildStatus/icon?job=metal3_daily_main_integration_test_centos&subject=CentOS%20daily%20main)](https://jenkins.nordix.org/view/Metal3/job/metal3_daily_main_integration_test_centos/)
 
diff --git a/apis/go.mod b/apis/go.mod
index 89383ba6..f90eaec1 100644
--- a/apis/go.mod
+++ b/apis/go.mod
@@ -3,7 +3,7 @@ module github.com/metal3-io/baremetal-operator/apis
 go 1.20
 
 require (
-	github.com/google/uuid v1.5.0
+	github.com/google/uuid v1.4.0
 	github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.4.0
 	github.com/stretchr/testify v1.8.4
 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
diff --git a/apis/go.sum b/apis/go.sum
index 8eb7b555..18c45998 100644
--- a/apis/go.sum
+++ b/apis/go.sum
@@ -58,8 +58,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
 github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
 github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
diff --git a/apis/metal3.io/v1alpha1/baremetalhost_types.go b/apis/metal3.io/v1alpha1/baremetalhost_types.go
index af629b64..15189eac 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;auto
+// +kubebuilder:validation:Enum=md5;sha256;sha512
 type ChecksumType string
 
 const (
@@ -462,9 +462,6 @@ const (
 
 	// SHA512 checksum type
 	SHA512 ChecksumType = "sha512"
-
-	// Automatically detect
-	AutoChecksum ChecksumType = "auto"
 )
 
 // Image holds the details of an image either to provisioned or that
@@ -476,9 +473,8 @@ 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 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 is the checksum algorithm for the image.
+	// e.g md5, sha256, sha512
 	ChecksumType ChecksumType `json:"checksumType,omitempty"`
 
 	// DiskFormat contains the format of the image (raw, qcow2, ...).
@@ -1100,8 +1096,6 @@ 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 5eac99d8..5394d89b 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", "auto":
+	case "", "md5", "sha256", "sha512":
 	default:
-		fmt.Fprintf(os.Stderr, "Invalid image checksum type %q, use \"md5\", \"sha256\", \"sha512\" or \"auto\"\n", *imageChecksumType)
+		fmt.Fprintf(os.Stderr, "Invalid image checksum type %q, use \"md5\", \"sha256\" or \"sha512\"\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 d2aa2121..77a57565 100644
--- a/config/base/crds/bases/metal3.io_baremetalhosts.yaml
+++ b/config/base/crds/bases/metal3.io_baremetalhosts.yaml
@@ -221,15 +221,12 @@ 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 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".
+                    description: ChecksumType is the checksum algorithm for the image.
+                      e.g md5, sha256, sha512
                     enum:
                     - md5
                     - sha256
                     - sha512
-                    - auto
                     type: string
                   format:
                     description: DiskFormat contains the format of the image (raw,
@@ -874,14 +871,11 @@ spec:
                         type: string
                       checksumType:
                         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".
+                          image. e.g md5, sha256, sha512
                         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 f013ce50..ba6d83f1 100644
--- a/config/render/capm3.yaml
+++ b/config/render/capm3.yaml
@@ -221,15 +221,12 @@ 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 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".
+                    description: ChecksumType is the checksum algorithm for the image.
+                      e.g md5, sha256, sha512
                     enum:
                     - md5
                     - sha256
                     - sha512
-                    - auto
                     type: string
                   format:
                     description: DiskFormat contains the format of the image (raw,
@@ -874,14 +871,11 @@ spec:
                         type: string
                       checksumType:
                         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".
+                          image. e.g md5, sha256, sha512
                         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 1f0ed8f1..5e9432b3 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. Use `auto` to auto-detect
-  the algorithm from the value. If nothing is specified, `md5` is assumed.
+  only `md5`, `sha256`, `sha512` are recognized. 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 5b84cffa..75e08da6 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.4.0
 	github.com/onsi/gomega v1.30.0
 	github.com/pkg/errors v0.9.1
-	github.com/prometheus/client_golang v1.18.0
+	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.uber.org/zap v1.26.0
@@ -43,26 +43,26 @@ require (
 	github.com/google/gnostic v0.5.7-v3refs // indirect
 	github.com/google/go-cmp v0.6.0 // indirect
 	github.com/google/gofuzz v1.1.0 // indirect
-	github.com/google/uuid v1.5.0 // indirect
+	github.com/google/uuid v1.4.0 // indirect
 	github.com/imdario/mergo v0.3.12 // indirect
 	github.com/inconshreveable/mousetrap v1.0.1 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
-	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
+	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_model v0.5.0 // indirect
-	github.com/prometheus/common v0.45.0 // indirect
-	github.com/prometheus/procfs v0.12.0 // indirect
+	github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
+	github.com/prometheus/common v0.44.0 // indirect
+	github.com/prometheus/procfs v0.11.1 // indirect
 	github.com/spf13/cobra v1.6.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	go.uber.org/multierr v1.10.0 // indirect
 	golang.org/x/net v0.17.0 // indirect
-	golang.org/x/oauth2 v0.12.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/oauth2 v0.8.0 // indirect
+	golang.org/x/sys v0.14.0 // indirect
 	golang.org/x/term v0.13.0 // indirect
 	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
diff --git a/go.sum b/go.sum
index 12cf8a14..7a348be2 100644
--- a/go.sum
+++ b/go.sum
@@ -71,8 +71,8 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
 github.com/google/safetext v0.0.0-20230106111101-7156a760e523 h1:i4NsbmB9pD5+Ggp5GZKyvYY6MkjvPE8CIMlkvXFF8gA=
 github.com/google/safetext v0.0.0-20230106111101-7156a760e523/go.mod h1:mJNEy0r5YPHC7ChQffpOszlGB4L1iqjXWpIEKcFpr9s=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gophercloud/gophercloud v1.5.1-0.20231117122435-08456f7fe42e h1:acHzJUXVfS+GImmi+yyM2+AOiaO94Z4KaTTFVU6Ov9U=
 github.com/gophercloud/gophercloud v1.5.1-0.20231117122435-08456f7fe42e/go.mod h1:ecnaHbFxBunc2UeAONDQbkQacv6WP1syeZ02TgAB7kA=
 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
@@ -96,8 +96,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
+github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
+github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -113,15 +113,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
+github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
+github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
-github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
-github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
+github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
@@ -180,10 +180,11 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
 golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
-golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
+golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
+golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -196,8 +197,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
diff --git a/pkg/provisioner/ironic/ironic.go b/pkg/provisioner/ironic/ironic.go
index 45b4d1b2..88ed19e0 100644
--- a/pkg/provisioner/ironic/ironic.go
+++ b/pkg/provisioner/ironic/ironic.go
@@ -965,21 +965,26 @@ 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,
-		"image_source":      imageData.URL,
-		"image_disk_format": imageData.DiskFormat,
-	}
+		"boot_iso": nil,
 
-	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
+		"image_source":        imageData.URL,
+		"image_os_hash_algo":  checksumType,
+		"image_os_hash_value": checksum,
+		"image_checksum":      legacyChecksum,
+		"image_disk_format":   imageData.DiskFormat,
 	}
 	updater.
 		SetInstanceInfoOpts(optValues, ironicNode)
@@ -1277,24 +1282,15 @@ func (p *ironicProvisioner) ironicHasSameImage(ironicNode *nodes.Node, image met
 			"provisionState", ironicNode.ProvisionState)
 	} else {
 		checksum, checksumType, _ := image.GetChecksum()
-		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)
-		}
+		sameImage = (ironicNode.InstanceInfo["image_source"] == image.URL &&
+			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"],
-			"checksumType", checksumType,
-			"checksum", checksum,
+			"image_os_hash_algo", checksumType,
+			"image_os_has_value", checksum,
 			"same", sameImage,
-			"provisionState", ironicNode.ProvisionState,
-			"iinfo", ironicNode.InstanceInfo)
+			"provisionState", ironicNode.ProvisionState)
 	}
 	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 815dccdc..5e1435a6 100644
--- a/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
+++ b/apis/metal3.io/v1alpha1/baremetalhost_types_test.go
@@ -317,10 +317,9 @@ func TestCredentialStatusMatch(t *testing.T) {
 
 func TestGetImageChecksum(t *testing.T) {
 	for _, tc := range []struct {
-		Scenario     string
-		Host         BareMetalHost
-		Expected     bool
-		ExpectedType string
+		Scenario string
+		Host     BareMetalHost
+		Expected bool
 	}{
 		{
 			Scenario: "both checksum value and type specified",
@@ -336,8 +335,7 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected:     true,
-			ExpectedType: "md5",
+			Expected: true,
 		},
 		{
 			Scenario: "checksum value specified but not type",
@@ -352,25 +350,7 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			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: "",
+			Expected: true,
 		},
 		{
 			Scenario: "sha256 checksum value and type specified",
@@ -386,8 +366,7 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected:     true,
-			ExpectedType: "sha256",
+			Expected: true,
 		},
 		{
 			Scenario: "sha512 checksum value and type specified",
@@ -403,8 +382,7 @@ func TestGetImageChecksum(t *testing.T) {
 					},
 				},
 			},
-			Expected:     true,
-			ExpectedType: "sha512",
+			Expected: true,
 		},
 		{
 			Scenario: "checksum value not specified",
@@ -465,10 +443,9 @@ func TestGetImageChecksum(t *testing.T) {
 		},
 	} {
 		t.Run(tc.Scenario, func(t *testing.T) {
-			_, checksumType, actual := tc.Host.Spec.Image.GetChecksum()
-			assert.Equal(t, tc.Expected, actual)
-			if tc.Expected {
-				assert.Equal(t, tc.ExpectedType, checksumType)
+			_, _, actual := tc.Host.Spec.Image.GetChecksum()
+			if actual != tc.Expected {
+				t.Errorf("expected %v but got %v", tc.Expected, actual)
 			}
 		})
 	}
diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh
index c7d67b88..5597c5b1 100755
--- a/hack/ci-e2e.sh
+++ b/hack/ci-e2e.sh
@@ -2,7 +2,7 @@
 
 # -----------------------------------------------------------------------------
 # Description: This script sets up the environment and runs E2E tests for the
-#              BMO project. It uses either vbmc or sushy-tools based on
+#              BMO project. It uses either vbmc or sushy-tools based on 
 #              the BMO_E2E_EMULATOR environment variable.
 # Usage:       export BMO_E2E_EMULATOR="vbmc"  # Or "sushy-tools"
 #              ./ci-e2e.sh
@@ -116,18 +116,17 @@ IMAGE_FILE="cirros-${CIRROS_VERSION}-x86_64-disk.img"
 export IMAGE_CHECKSUM="c8fc807773e5354afe61636071771906"
 export IMAGE_URL="http://${IP_ADDRESS}/${IMAGE_FILE}"
 IMAGE_DIR="${REPO_ROOT}/test/e2e/images"
-mkdir -p "${IMAGE_DIR}"
 
 ## Download and run image server
-wget --quiet -P "${IMAGE_DIR}"/ https://artifactory.nordix.org/artifactory/metal3/images/iso/"${IMAGE_FILE}"
+mkdir -p "${IMAGE_DIR}"
+pushd "${IMAGE_DIR}"
+wget --quiet https://artifactory.nordix.org/artifactory/metal3/images/iso/"${IMAGE_FILE}"
+popd
 
 docker run --name image-server-e2e -d \
   -p 80:8080 \
   -v "${IMAGE_DIR}:/usr/share/nginx/html" nginxinc/nginx-unprivileged
 
-# Generate the key pair
-ssh-keygen -t ed25519 -f "${IMAGE_DIR}/ssh_testkey" -q -N ""
-
 # Generate credentials
 BMO_OVERLAY="${REPO_ROOT}/config/overlays/e2e"
 IRONIC_OVERLAY="${REPO_ROOT}/ironic-deployment/overlays/e2e"
@@ -165,6 +164,6 @@ 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-e2e-${BMO_E2E_EMULATOR}.tar.gz" _artifacts
+tar --directory test/e2e/ -czf artifacts.tar.gz _artifacts
 
 exit "${test_status}"
diff --git a/pkg/provisioner/ironic/provision_test.go b/pkg/provisioner/ironic/provision_test.go
index a859a222..121b0d99 100644
--- a/pkg/provisioner/ironic/provision_test.go
+++ b/pkg/provisioner/ironic/provision_test.go
@@ -343,20 +343,6 @@ 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,
@@ -387,21 +373,6 @@ 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 072e58b5..eb1f99e6 100644
--- a/pkg/provisioner/ironic/validatemanagementaccess_test.go
+++ b/pkg/provisioner/ironic/validatemanagementaccess_test.go
@@ -153,7 +153,6 @@ 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
 
@@ -392,35 +391,14 @@ func TestValidateManagementAccessExistingSteadyStateNoUpdate(t *testing.T) {
 		},
 		{
 			Image: &metal3api.Image{
-				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",
+				URL:      "theimage",
+				Checksum: "thechecksum",
 			},
 			InstanceInfo: map[string]interface{}{
 				"image_source":        "theimage",
-				"image_os_hash_algo":  "sha256",
+				"image_os_hash_algo":  "md5",
 				"image_os_hash_value": "thechecksum",
+				"image_checksum":      "thechecksum",
 				"capabilities":        map[string]interface{}{},
 			},
 			DriverInfo: map[string]interface{}{
diff --git a/test/e2e/basic_ops_test.go b/test/e2e/basic_ops_test.go
index e06a9656..a967a908 100644
--- a/test/e2e/basic_ops_test.go
+++ b/test/e2e/basic_ops_test.go
@@ -48,11 +48,7 @@ var _ = Describe("basic", func() {
 
 	It("should control power cycle of BMH though annotations", func() {
 		By("creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("creating a BMH")
 		bmh := metal3api.BareMetalHost{
diff --git a/test/e2e/provisioning_and_annotation_test.go b/test/e2e/basic_provisioning_test.go
similarity index 78%
rename from test/e2e/provisioning_and_annotation_test.go
rename to test/e2e/basic_provisioning_test.go
index 2f829492..be3ae82b 100644
--- a/test/e2e/provisioning_and_annotation_test.go
+++ b/test/e2e/basic_provisioning_test.go
@@ -4,11 +4,8 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"os"
 	"time"
 
-	"golang.org/x/crypto/ssh"
-
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 	corev1 "k8s.io/api/core/v1"
@@ -20,8 +17,6 @@ import (
 	"sigs.k8s.io/cluster-api/util/patch"
 
 	metal3api "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
-
-	capm3_e2e "github.com/metal3-io/cluster-api-provider-metal3/test/e2e"
 )
 
 var _ = Describe("BMH Provisioning and Annotation Management", func() {
@@ -52,11 +47,7 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 
 	It("provisions a BMH, applies detached and status annotations, then deprovisions", func() {
 		By("Creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("Creating a BMH with inspection disabled and hardware details added")
 		bmh := metal3api.BareMetalHost{
@@ -74,9 +65,8 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 					Address:         bmcAddress,
 					CredentialsName: "bmc-credentials",
 				},
-				BootMode:              metal3api.Legacy,
-				BootMACAddress:        bootMacAddress,
-				AutomatedCleaningMode: "disabled",
+				BootMode:       metal3api.Legacy,
+				BootMACAddress: bootMacAddress,
 			},
 		}
 		err := clusterProxy.GetClient().Create(ctx, &bmh)
@@ -93,23 +83,12 @@ 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"),
-			ChecksumType: metal3api.AutoChecksum,
+			URL:      e2eConfig.GetVariable("IMAGE_URL"),
+			Checksum: e2eConfig.GetVariable("IMAGE_CHECKSUM"),
 		}
 		bmh.Spec.RootDeviceHints = &metal3api.RootDeviceHints{
 			DeviceName: "/dev/vda",
 		}
-		// The ssh check is not possible in all situations (e.g. fixture) so it can be skipped
-		if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" {
-			userDataSecretName := "user-data"
-			sshPubKeyPath := e2eConfig.GetVariable("SSH_PUB_KEY")
-			createCirrosInstanceAndHostnameUserdata(ctx, clusterProxy.GetClient(), namespace.Name, userDataSecretName, sshPubKeyPath)
-			bmh.Spec.UserData = &corev1.SecretReference{
-				Name:      userDataSecretName,
-				Namespace: namespace.Name,
-			}
-		}
 		Expect(helper.Patch(ctx, &bmh)).To(Succeed())
 
 		By("Waiting for the BMH to be in provisioning state")
@@ -126,22 +105,6 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 			State:  metal3api.StateProvisioned,
 		}, e2eConfig.GetIntervals(specName, "wait-provisioned")...)
 
-		// The ssh check is not possible in all situations (e.g. fixture) so it can be skipped
-		if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" {
-			By("Verifying the node booting from disk")
-			keyPath := e2eConfig.GetVariable("SSH_PRIV_KEY")
-			key, err := os.ReadFile(keyPath)
-			Expect(err).NotTo(HaveOccurred(), "unable to read private key")
-
-			signer, err := ssh.ParsePrivateKey(key)
-			Expect(err).NotTo(HaveOccurred(), "unable to parse private key")
-
-			auth := ssh.PublicKeys(signer)
-			PerformSSHBootCheck(e2eConfig, "disk", auth)
-		} else {
-			capm3_e2e.Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true")
-		}
-
 		By("Retrieving the latest BMH object")
 		err = clusterProxy.GetClient().Get(ctx, types.NamespacedName{
 			Name:      bmh.Name,
@@ -193,11 +156,7 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 		}, e2eConfig.GetIntervals(specName, "wait-secret-deletion")...).Should(BeTrue())
 
 		By("Creating a secret with BMH credentials")
-		bmcCredentialsData = map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("Recreating the BMH with the previously saved status in the status annotation")
 		bmh = metal3api.BareMetalHost{
@@ -214,9 +173,8 @@ var _ = Describe("BMH Provisioning and Annotation Management", func() {
 					Address:         bmcAddress,
 					CredentialsName: "bmc-credentials",
 				},
-				BootMode:              metal3api.Legacy,
-				BootMACAddress:        bootMacAddress,
-				AutomatedCleaningMode: "disabled",
+				BootMode:       metal3api.Legacy,
+				BootMACAddress: bootMacAddress,
 				Image: &metal3api.Image{
 					URL:      e2eConfig.GetVariable("IMAGE_URL"),
 					Checksum: e2eConfig.GetVariable("IMAGE_CHECKSUM"),
diff --git a/test/e2e/common.go b/test/e2e/common.go
index c559e538..fe8774a4 100644
--- a/test/e2e/common.go
+++ b/test/e2e/common.go
@@ -15,6 +15,7 @@ import (
 
 	. "github.com/onsi/gomega"
 
+	v1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -154,7 +155,7 @@ func (c *Config) GetVariable(varName string) string {
 	}
 
 	value, ok := c.Variables[varName]
-	Expect(ok).To(BeTrue(), fmt.Sprintf("Configuration variable '%s' not found", varName))
+	Expect(ok).To(BeTrue())
 	return value
 }
 
@@ -281,16 +282,24 @@ func buildKustomizeManifest(source string) ([]byte, error) {
 	return resources.AsYaml()
 }
 
-func CreateSecret(ctx context.Context, client client.Client, secretNamespace, secretName string, data map[string]string) {
-	secret := corev1.Secret{
+func CreateBMHCredentialsSecret(ctx context.Context, client client.Client, secretNamespace, secretName, username, password string) error {
+	bmcCredentials := corev1.Secret{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      secretName,
 			Namespace: secretNamespace,
 		},
-		StringData: data,
+		StringData: map[string]string{
+			"username": username,
+			"password": password,
+		},
 	}
 
-	Expect(client.Create(ctx, &secret)).NotTo(HaveOccurred(), fmt.Sprintf("Failed to create secret '%s/%s'", secretNamespace, secretName))
+	err := client.Create(ctx, &bmcCredentials)
+	if err != nil {
+		return fmt.Errorf("failed to create BMC credentials secret: %w", err)
+	}
+
+	return nil
 }
 
 func executeSSHCommand(client *ssh.Client, command string) (string, error) {
@@ -342,72 +351,105 @@ func IsBootedFromDisk(client *ssh.Client) (bool, error) {
 		return false, fmt.Errorf("error executing 'df -h': %w", err)
 	}
 
-	bootedFromDisk := HasRootOnDisk(output)
-	if bootedFromDisk {
+	isDisk := HasRootOnDisk(output)
+	if isDisk {
 		capm3_e2e.Logf("System is booted from a disk.")
 	} else {
 		capm3_e2e.Logf("System is booted from a live ISO.")
 	}
 
-	return bootedFromDisk, nil
+	return isDisk, nil
 }
 
-func EstablishSSHConnection(e2eConfig *Config, auth ssh.AuthMethod, user, address string) *ssh.Client {
-	config := &ssh.ClientConfig{
-		User:            user,
-		Auth:            []ssh.AuthMethod{auth},
-		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // #nosec G106
-	}
+// BuildAndApplyKustomizeInput provides input for BuildAndApplyKustomize().
+// If WaitForDeployment and/or WatchDeploymentLogs is set to true, then DeploymentName
+// and DeploymentNamespace are expected.
+type BuildAndApplyKustomizeInput struct {
+	// Path to the kustomization to build
+	Kustomization string
 
-	var client *ssh.Client
-	var err error
-	Eventually(func() error {
-		client, err = ssh.Dial("tcp", address, config)
-		return err
-	}, e2eConfig.GetIntervals("default", "wait-connect-ssh")...).Should(Succeed(), "Failed to establish SSH connection")
+	ClusterProxy framework.ClusterProxy
+
+	// If this is set to true. Perform a wait until the deployment specified by
+	// DeploymentName and DeploymentNamespace is available or WaitIntervals is timed out
+	WaitForDeployment bool
 
-	return client
+	// If this is set to true. Set up a log watcher for the deployment specified by
+	// DeploymentName and DeploymentNamespace
+	WatchDeploymentLogs bool
+
+	// DeploymentName and DeploymentNamespace specified a deployment that will be waited and/or logged
+	DeploymentName      string
+	DeploymentNamespace string
+
+	// Path to store the deployment logs
+	LogPath string
+
+	// Intervals to use in checking and waiting for the deployment
+	WaitIntervals []interface{}
 }
 
-// createCirrosInstanceAndHostnameUserdata creates a Kubernetes secret intended for cloud-init usage.
-// This userdata is utilized during BMH's initialization and setup.
-func createCirrosInstanceAndHostnameUserdata(ctx context.Context, client client.Client, namespace string, secretName string, sshPubKeyPath string) {
-	sshPubKeyData, err := os.ReadFile(sshPubKeyPath) // #nosec G304
-	Expect(err).NotTo(HaveOccurred(), "Failed to read SSH public key file")
-
-	userDataContent := fmt.Sprintf(`#!/bin/sh
-mkdir /root/.ssh
-mkdir /home/cirros/.ssh
-chmod 700 /root/.ssh
-chmod 700 /home/cirros/.ssh
-chown cirros /home/cirros/.ssh
-echo "%s" >> /home/cirros/.ssh/authorized_keys
-echo "%s" >> /root/.ssh/authorized_keys`, sshPubKeyData, sshPubKeyData)
-
-	CreateSecret(ctx, client, namespace, secretName, map[string]string{"userData": userDataContent})
+func (input *BuildAndApplyKustomizeInput) validate() error {
+	// If neither WaitForDeployment nor WatchDeploymentLogs is true, we don't need to validate the input
+	if !input.WaitForDeployment && !input.WatchDeploymentLogs {
+		return nil
+	}
+	if input.WaitForDeployment && input.WaitIntervals == nil {
+		return errors.Errorf("WaitIntervals is expected if WaitForDeployment is set to true")
+	}
+	if input.WatchDeploymentLogs && input.LogPath == "" {
+		return errors.Errorf("LogPath is expected if WatchDeploymentLogs is set to true")
+	}
+	if input.DeploymentName == "" || input.DeploymentNamespace == "" {
+		return errors.Errorf("DeploymentName and DeploymentNamespace are expected if WaitForDeployment or WatchDeploymentLogs is true")
+	}
+	return nil
 }
 
-// PerformSSHBootCheck performs an SSH check to verify the node's boot source.
-// The `expectedBootMode` parameter should be "disk" or "memory".
-// The `auth` parameter is an ssh.AuthMethod for authentication.
-func PerformSSHBootCheck(e2eConfig *Config, expectedBootMode string, auth ssh.AuthMethod) {
-	ip := e2eConfig.GetVariable("IP_BMO_E2E_0")
-	sshPort := e2eConfig.GetVariable("SSH_PORT")
-	address := fmt.Sprintf("%s:%s", ip, sshPort)
-	user := e2eConfig.GetVariable("CIRROS_USERNAME")
-
-	client := EstablishSSHConnection(e2eConfig, auth, user, address)
-	defer func() {
-		if client != nil {
-			client.Close()
-		}
-	}()
+// BuildAndApplyKustomize takes input from BuildAndApplyKustomizeInput. It builds the provided kustomization
+// and apply it to the cluster provided by clusterProxy
+func BuildAndApplyKustomize(ctx context.Context, input *BuildAndApplyKustomizeInput) error {
+	Expect(input.validate()).To(BeNil())
+	var err error
+	kustomization := input.Kustomization
+	clusterProxy := input.ClusterProxy
+	manifest, err := buildKustomizeManifest(kustomization)
+	if err != nil {
+		return err
+	}
+	err = clusterProxy.Apply(ctx, manifest)
+	if err != nil {
+		return err
+	}
 
-	bootedFromDisk, err := IsBootedFromDisk(client)
-	Expect(err).NotTo(HaveOccurred(), "Error in verifying boot mode")
+	if !input.WaitForDeployment && !input.WatchDeploymentLogs {
+		return nil
+	}
 
-	// Compare actual boot source with expected
-	isExpectedBootMode := (expectedBootMode == "disk" && bootedFromDisk) ||
-		(expectedBootMode == "memory" && !bootedFromDisk)
-	Expect(isExpectedBootMode).To(BeTrue(), fmt.Sprintf("Expected booting from %s, but found different mode", expectedBootMode))
+	deployment := &v1.Deployment{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      input.DeploymentName,
+			Namespace: input.DeploymentNamespace,
+		},
+	}
+
+	if input.WaitForDeployment {
+		// Wait for the deployment to become available
+		framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{
+			Getter:     clusterProxy.GetClient(),
+			Deployment: deployment,
+		}, input.WaitIntervals...)
+	}
+
+	if input.WatchDeploymentLogs {
+		// Set up log watcher
+		framework.WatchDeploymentLogsByName(ctx, framework.WatchDeploymentLogsByNameInput{
+			GetLister:  clusterProxy.GetClient(),
+			Cache:      clusterProxy.GetCache(ctx),
+			ClientSet:  clusterProxy.GetClientSet(),
+			Deployment: deployment,
+			LogPath:    input.LogPath,
+		})
+	}
+	return nil
 }
diff --git a/test/e2e/config/ironic.yaml b/test/e2e/config/ironic.yaml
index 9cc9e11c..b7d293a4 100644
--- a/test/e2e/config/ironic.yaml
+++ b/test/e2e/config/ironic.yaml
@@ -35,10 +35,6 @@ variables:
   SSH_CHECK_PROVISIONED: "true"
   IP_BMO_E2E_0: "192.168.222.122"
   SSH_PORT: "22"
-  CIRROS_USERNAME: "cirros"
-  CIRROS_PASSWORD: "gocubsgo"
-  SSH_PRIV_KEY: "./images/ssh_testkey"
-  SSH_PUB_KEY: "./images/ssh_testkey.pub"
 
 intervals:
   inspection/wait-unmanaged: ["1m", "5s"]
@@ -52,7 +48,7 @@ intervals:
   ironic/wait-deployment: ["10m", "2s"]
   default/wait-power-state: ["10m", "100ms"]
   default/wait-provisioning: ["20s", "1s"]
-  default/wait-provisioned: ["10m", "1s"]
+  default/wait-provisioned: ["5m", "1s"]
   default/wait-deprovisioning: ["1m", "10ms"]
   default/wait-deleted: ["20s", "10ms"]
   default/wait-secret-deletion: ["1m", "1s"]
diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go
index 60c7dcb0..4615944d 100644
--- a/test/e2e/e2e_suite_test.go
+++ b/test/e2e/e2e_suite_test.go
@@ -10,8 +10,6 @@ import (
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
-	v1 "k8s.io/api/apps/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/klog/v2"
 	"sigs.k8s.io/cluster-api/test/framework"
@@ -116,64 +114,39 @@ var _ = SynchronizedBeforeSuite(func() []byte {
 		}
 	}
 
+	bmoIronicNamespace := "baremetal-operator-system"
+
 	if e2eConfig.GetVariable("DEPLOY_IRONIC") != "false" {
 		// Install Ironic
 		By("Installing Ironic")
-		kustomization := e2eConfig.GetVariable("IRONIC_KUSTOMIZATION")
-		manifest, err := buildKustomizeManifest(kustomization)
-		Expect(err).NotTo(HaveOccurred())
-		err = clusterProxy.Apply(ctx, manifest)
+		err := BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{
+			Kustomization:       e2eConfig.GetVariable("IRONIC_KUSTOMIZATION"),
+			ClusterProxy:        clusterProxy,
+			WaitForDeployment:   true,
+			WatchDeploymentLogs: true,
+			DeploymentName:      "ironic",
+			DeploymentNamespace: bmoIronicNamespace,
+			LogPath:             filepath.Join(artifactFolder, "logs", bmoIronicNamespace),
+			WaitIntervals:       e2eConfig.GetIntervals("default", "wait-deployment"),
+		})
 		Expect(err).NotTo(HaveOccurred())
 
-		ironicDeployment := &v1.Deployment{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      "ironic",
-				Namespace: "baremetal-operator-system",
-			},
-		}
-		// Wait for it to become available
-		framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{
-			Getter:     clusterProxy.GetClient(),
-			Deployment: ironicDeployment,
-		}, e2eConfig.GetIntervals("ironic", "wait-deployment")...)
-		// Set up log watcher
-		framework.WatchDeploymentLogsByName(ctx, framework.WatchDeploymentLogsByNameInput{
-			GetLister:  clusterProxy.GetClient(),
-			Cache:      clusterProxy.GetCache(ctx),
-			ClientSet:  clusterProxy.GetClientSet(),
-			Deployment: ironicDeployment,
-			LogPath:    filepath.Join(artifactFolder, "logs", ironicDeployment.GetNamespace()),
-		})
 	}
 
 	if e2eConfig.GetVariable("DEPLOY_BMO") != "false" {
 		// Install BMO
 		By("Installing BMO")
-		kustomization := e2eConfig.GetVariable("BMO_KUSTOMIZATION")
-		manifest, err := buildKustomizeManifest(kustomization)
-		Expect(err).NotTo(HaveOccurred())
-		err = clusterProxy.Apply(ctx, manifest)
-		Expect(err).NotTo(HaveOccurred())
-
-		bmoDeployment := &v1.Deployment{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      "baremetal-operator-controller-manager",
-				Namespace: "baremetal-operator-system",
-			},
-		}
-		// Wait for it to become available
-		framework.WaitForDeploymentsAvailable(ctx, framework.WaitForDeploymentsAvailableInput{
-			Getter:     clusterProxy.GetClient(),
-			Deployment: bmoDeployment,
-		}, e2eConfig.GetIntervals("default", "wait-deployment")...)
-		// Set up log watcher
-		framework.WatchDeploymentLogsByName(ctx, framework.WatchDeploymentLogsByNameInput{
-			GetLister:  clusterProxy.GetClient(),
-			Cache:      clusterProxy.GetCache(ctx),
-			ClientSet:  clusterProxy.GetClientSet(),
-			Deployment: bmoDeployment,
-			LogPath:    filepath.Join(artifactFolder, "logs", bmoDeployment.GetNamespace()),
+		err := BuildAndApplyKustomize(ctx, &BuildAndApplyKustomizeInput{
+			Kustomization:       e2eConfig.GetVariable("BMO_KUSTOMIZATION"),
+			ClusterProxy:        clusterProxy,
+			WaitForDeployment:   true,
+			WatchDeploymentLogs: true,
+			DeploymentName:      "baremetal-operator-controller-manager",
+			DeploymentNamespace: bmoIronicNamespace,
+			LogPath:             filepath.Join(artifactFolder, "logs", bmoIronicNamespace),
+			WaitIntervals:       e2eConfig.GetIntervals("default", "wait-deployment"),
 		})
+		Expect(err).NotTo(HaveOccurred())
 	}
 
 	return []byte(strings.Join([]string{clusterProxy.GetKubeconfigPath()}, ","))
diff --git a/test/e2e/external_inspection_test.go b/test/e2e/external_inspection_test.go
index 03a494a5..5de4f24b 100644
--- a/test/e2e/external_inspection_test.go
+++ b/test/e2e/external_inspection_test.go
@@ -197,12 +197,8 @@ var _ = Describe("External Inspection", func() {
 	})
 
 	It("should skip inspection and become available when a BMH has annotations with hardware details and inspection disabled", func() {
-		By("Creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		By("creating a secret with BMH credentials")
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("creating a BMH with inspection disabled and hardware details added")
 		bmh := metal3api.BareMetalHost{
diff --git a/test/e2e/inspection_test.go b/test/e2e/inspection_test.go
index 552aabd7..9f1a6046 100644
--- a/test/e2e/inspection_test.go
+++ b/test/e2e/inspection_test.go
@@ -92,12 +92,8 @@ var _ = Describe("Inspection", func() {
 	})
 
 	It("should inspect a newly created BMH", func() {
-		By("Creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		By("creating a secret with BMH credentials")
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("creating a BMH")
 		bmh := metal3api.BareMetalHost{
diff --git a/test/e2e/live_iso_test.go b/test/e2e/live_iso_test.go
index fc8bb3a2..7a02e9ac 100644
--- a/test/e2e/live_iso_test.go
+++ b/test/e2e/live_iso_test.go
@@ -4,10 +4,9 @@ import (
 	"context"
 	"fmt"
 
-	"golang.org/x/crypto/ssh"
-
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
+	"golang.org/x/crypto/ssh"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
@@ -50,11 +49,7 @@ var _ = Describe("Live-ISO", func() {
 
 	It("should provision a BMH with live ISO and then deprovision it", func() {
 		By("Creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("Creating a BMH with inspection disabled and hardware details added")
 		bmh := metal3api.BareMetalHost{
@@ -76,8 +71,12 @@ var _ = Describe("Live-ISO", func() {
 					URL:        imageURL,
 					DiskFormat: pointer.String("live-iso"),
 				},
-				BootMode:       metal3api.Legacy,
-				BootMACAddress: bootMacAddress,
+				BootMode:              metal3api.Legacy,
+				BootMACAddress:        bootMacAddress,
+				AutomatedCleaningMode: "disabled",
+				RootDeviceHints: &metal3api.RootDeviceHints{
+					DeviceName: "/dev/vda",
+				},
 			},
 		}
 		err := clusterProxy.GetClient().Create(ctx, &bmh)
@@ -100,11 +99,39 @@ var _ = Describe("Live-ISO", func() {
 		// The ssh check is not possible in all situations (e.g. fixture) so it can be skipped
 		if e2eConfig.GetVariable("SSH_CHECK_PROVISIONED") == "true" {
 			By("Verifying the node booted from live ISO image")
-			password := e2eConfig.GetVariable("CIRROS_PASSWORD")
-			auth := ssh.Password(password)
-			PerformSSHBootCheck(e2eConfig, "memory", auth)
+
+			// Set up SSH client configuration
+			config := &ssh.ClientConfig{
+				User: "cirros",
+				Auth: []ssh.AuthMethod{
+					ssh.Password("gocubsgo"),
+				},
+				HostKeyCallback: ssh.InsecureIgnoreHostKey(), // #nosec G106
+			}
+
+			ip := e2eConfig.GetVariable("IP_BMO_E2E_0")
+			sshPort := e2eConfig.GetVariable("SSH_PORT")
+			address := fmt.Sprintf("%s:%s", ip, sshPort)
+
+			// Establish an SSH connection
+			var client *ssh.Client
+			var err error
+
+			Eventually(func() error {
+				client, err = ssh.Dial("tcp", address, config)
+				return err
+			}, e2eConfig.GetIntervals(specName, "wait-connect-ssh")...).Should(Succeed(), "Failed to establish SSH connection")
+
+			defer func() {
+				if client != nil {
+					client.Close()
+				}
+			}()
+			isDisk, err := IsBootedFromDisk(client)
+			Expect(err).NotTo(HaveOccurred(), "Error in verifying boot mode")
+			Expect(isDisk).To(Equal(false), "Error booting from disk when live ISO is expected")
 		} else {
-			capm3_e2e.Logf("WARNING: Skipping SSH check since SSH_CHECK_PROVISIONED != true")
+			capm3_e2e.Logf("WARNING: Skipping ssh check since SSH_CHECK_PROVISIONED != true")
 		}
 
 		By("Triggering the deprovisioning of the BMH")
diff --git a/test/e2e/re_inspection_test.go b/test/e2e/re_inspection_test.go
index 1b1f469c..d9b64986 100644
--- a/test/e2e/re_inspection_test.go
+++ b/test/e2e/re_inspection_test.go
@@ -50,12 +50,8 @@ var _ = Describe("Re-Inspection", func() {
 	})
 
 	It("should re-inspect the annotated BMH", func() {
-		By("Creating a secret with BMH credentials")
-		bmcCredentialsData := map[string]string{
-			"username": bmcUser,
-			"password": bmcPassword,
-		}
-		CreateSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcCredentialsData)
+		By("creating a secret with BMH credentials")
+		CreateBMHCredentialsSecret(ctx, clusterProxy.GetClient(), namespace.Name, secretName, bmcUser, bmcPassword)
 
 		By("creating a BMH with inspection disabled and hardware details added with wrong HostName")
 		newHardwareDetails := strings.Replace(hardwareDetails, "bmo-e2e-0", wrongHostName, 1)
diff --git a/test/go.mod b/test/go.mod
index d322a61d..3249f27d 100644
--- a/test/go.mod
+++ b/test/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/onsi/ginkgo/v2 v2.13.0
 	github.com/onsi/gomega v1.29.0
 	github.com/pkg/errors v0.9.1
-	golang.org/x/crypto v0.17.0
+	golang.org/x/crypto v0.14.0
 	gopkg.in/yaml.v2 v2.4.0
 	k8s.io/api v0.27.7
 	k8s.io/apimachinery v0.27.7
@@ -68,7 +68,7 @@ require (
 	github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
 	github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
-	github.com/google/uuid v1.5.0 // indirect
+	github.com/google/uuid v1.4.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/huandu/xstrings v1.4.0 // indirect
 	github.com/imdario/mergo v0.3.13 // indirect
@@ -113,9 +113,9 @@ require (
 	golang.org/x/mod v0.12.0 // indirect
 	golang.org/x/net v0.17.0 // indirect
 	golang.org/x/oauth2 v0.10.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
-	golang.org/x/term v0.15.0 // indirect
-	golang.org/x/text v0.14.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/term v0.13.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/tools v0.12.0 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
diff --git a/test/go.sum b/test/go.sum
index 70fbd8d8..41403b47 100644
--- a/test/go.sum
+++ b/test/go.sum
@@ -250,8 +250,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
+github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -513,8 +513,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -668,13 +668,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
-golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -685,8 +685,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=