diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index bd6e9a9ffc..149757a98e 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -20,6 +20,8 @@ jobs: contents: write steps: + - name: Install libvirt-dev + run: sudo apt-get install -y libvirt-dev - name: Check out code into the Go module directory uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Calculate go version diff --git a/.github/workflows/e2e-fixture-test.yml b/.github/workflows/e2e-fixture-test.yml index 4f87ad0892..af7ed535a2 100644 --- a/.github/workflows/e2e-fixture-test.yml +++ b/.github/workflows/e2e-fixture-test.yml @@ -11,6 +11,9 @@ jobs: runs-on: ubuntu-latest steps: + - name: Install libvirt-dev + run: sudo apt-get install -y libvirt-dev + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Calculate go version diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 31878ee4f7..93769005b6 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -31,7 +31,7 @@ jobs: - name: Install libvirt run: | sudo apt-get update - sudo apt-get install -y libvirt-daemon-system qemu-kvm virt-manager + sudo apt-get install -y libvirt-daemon-system qemu-kvm virt-manager libvirt-dev - name: Run BMO e2e Tests env: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index e7316269fc..cfc3fbb806 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -19,7 +19,10 @@ jobs: - apis - pkg/hardwareutils steps: + - name: Install libvirt-dev + run: sudo apt-get install -y libvirt-dev - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Calculate go version id: vars run: echo "go_version=$(make go-version)" >> $GITHUB_OUTPUT diff --git a/clean_bmcs.sh b/clean_bmcs.sh new file mode 100755 index 0000000000..5583a665f8 --- /dev/null +++ b/clean_bmcs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# +# This script reads BMC information in a config file and prepare VMs +# whose info match those config +# +set -eux + +REPO_ROOT=$(realpath "$(dirname "${BASH_SOURCE[0]}")") +cd "${REPO_ROOT}" + +CONFIG_FILE=$1 +NETWORK=${2:-"baremetal-e2e"} + +readarray -t BMCS < <(yq e -o=j -I=0 '.[]' "${CONFIG_FILE}") + +for bmc in "${BMCS[@]}"; do + bootMacAddress=$(echo "${bmc}" | jq -r '.bootMacAddress') + ipAddress=$(echo "${bmc}" | jq -r '.ipAddress') + virsh -c qemu:///system net-update "${NETWORK}" delete ip-dhcp-host "" --live --config +done +"${REPO_ROOT}/tools/bmh_test/clean_local_bmh_test_setup.sh" "^bmo-e2e-" +rm -rf /tmp/bmo-e2e-* diff --git a/hack/ci-e2e.sh b/hack/ci-e2e.sh index 55da95ff50..26ff2ffe31 100755 --- a/hack/ci-e2e.sh +++ b/hack/ci-e2e.sh @@ -105,7 +105,10 @@ else exit 1 fi -"${REPO_ROOT}/hack/create_bmcs.sh" "${E2E_BMCS_CONF_FILE}" baremetal-e2e +# "${REPO_ROOT}/hack/create_bmcs.sh" "${E2E_BMCS_CONF_FILE}" baremetal-e2e +pushd "${REPO_ROOT}/test/createVM" || exit 1 +go run main.go --yaml-source-file "${E2E_BMCS_CONF_FILE}" +popd # Image server variables CIRROS_VERSION="0.6.2" @@ -118,6 +121,7 @@ mkdir -p "${IMAGE_DIR}" ## Download disk images wget --quiet -P "${IMAGE_DIR}/" https://artifactory.nordix.org/artifactory/metal3/images/iso/"${IMAGE_FILE}" wget --quiet -P "${IMAGE_DIR}/" https://fastly-cdn.system-rescue.org/releases/11.00/systemrescue-11.00-amd64.iso +wget --quiet -P "${IMAGE_DIR}/" https://artifactory.nordix.org/artifactory/metal3/images/iso/minimal_linux_live-v2.iso ## Start the image server docker run --name image-server-e2e -d \ diff --git a/hack/clean-e2e.sh b/hack/clean-e2e.sh index 1a36c5f55c..b739186a40 100755 --- a/hack/clean-e2e.sh +++ b/hack/clean-e2e.sh @@ -13,3 +13,7 @@ docker rm -f sushy-tools rm -rf "${REPO_ROOT}/test/e2e/_artifacts" rm -rf "${REPO_ROOT}"/artifacts-* rm -rf "${REPO_ROOT}/test/e2e/images" + +# Clear network +virsh -c qemu:///system net-destroy baremetal-e2e +virsh -c qemu:///system net-undefine baremetal-e2e diff --git a/test/createVM/main.go b/test/createVM/main.go new file mode 100644 index 0000000000..779f5e4009 --- /dev/null +++ b/test/createVM/main.go @@ -0,0 +1,301 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "os" + "text/template" + + "github.com/dypflying/go-qcow2lib/qcow2" + "github.com/libvirt/libvirt-go" + bmoe2e "github.com/metal3-io/baremetal-operator/test/e2e" +) + +func CreateLibvirtVM(hostName, networkName, macAddress string) error { + opts := make(map[string]any) + opts[qcow2.OPT_SIZE] = 1 << 30 // qcow2 file's size is 1g + opts[qcow2.OPT_FMT] = "qcow2" // qcow2 format + opts[qcow2.OPT_SUBCLUSTER] = true // enable sub-cluster + + err := qcow2.Blk_Create("/tmp/"+hostName+".qcow2", opts) + + if err != nil { + fmt.Println("Failed to create qcow2 file") + fmt.Printf("Error occurred: %v\n", err) + return err + } + + conn, err := libvirt.NewConnect("qemu:///system") + if err != nil { + fmt.Println("Failed to connect to qemu:///system") + return err + } + defer conn.Close() + + domainDef := ` + + {{ .HostName }} + Virtualized BareMetalHost + + + + + + 4194304 + 2 + + hvm + + + + + + + + + /usr/bin/qemu-system-x86_64 + + + + +
+ + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + +
+ + + /dev/urandom +
+ + + ` + + xmlTpl, err := template.New("xml").Parse(domainDef) + + if err != nil { + fmt.Println("Failed to init the template") + fmt.Printf("Error occurred: %v\n", err) + return err + } + + data := struct { + HostName string + Network string + MacAddress string + }{ + HostName: hostName, + Network: networkName, + MacAddress: macAddress, + } + + var buf bytes.Buffer + + err = xmlTpl.Execute(&buf, data) + + if err != nil { + return err + } + + fmt.Println(buf.String()) + + dom, err := conn.DomainDefineXML(buf.String()) + + if err != nil { + fmt.Println("Failed to define domain") + fmt.Printf("Error occurred: %v\n", err) + return err + } + + if err := dom.Create(); err != nil { + fmt.Println("Failed to create domain") + fmt.Printf("Error occurred: %v\n", err) + return err + } + + fmt.Println("Domain created successfully") + return nil +} + +func CreateLibvirtBMC(macAddress, hostName, ipAddress, networkName string) error { + var err error + conn, err := libvirt.NewConnect("qemu:///system") + if err != nil { + return err + } + defer conn.Close() + + network, err := conn.LookupNetworkByName(networkName) + if err != nil { + return err + } + + xmlTpl, err := template.New("xml").Parse("") + + if err != nil { + return err + } + + data := struct { + MacAddress string + HostName string + IPAddress string + }{ + MacAddress: macAddress, + HostName: hostName, + IPAddress: ipAddress, + } + + var buf bytes.Buffer + + err = xmlTpl.Execute(&buf, data) + + if err != nil { + fmt.Printf("Error occurred: %v\n", err) + return err + } + + if err = network.Update( + libvirt.NETWORK_UPDATE_COMMAND_ADD_LAST, + libvirt.NETWORK_SECTION_IP_DHCP_HOST, + -1, + buf.String(), + libvirt.NETWORK_UPDATE_AFFECT_LIVE|libvirt.NETWORK_UPDATE_AFFECT_CONFIG, + ); err != nil { + fmt.Printf("Error occurred: %v\n", err) + return err + } + if err = CreateLibvirtVM(hostName, networkName, macAddress); err != nil { + fmt.Printf("Error occurred: %v\n", err) + return err + } + return nil +} + +func main() { + var vmName = flag.String( + "vm-name", "VM-1", "The name of the VM to create") + var networkName = flag.String( + "network-name", "baremetal-e2e", "The name of the network that the new VM should be attached to") + var macAddress = flag.String( + "mac-address", "00:60:2f:31:81:01", "Mac address of the VM on the network") + var ipAddress = flag.String( + "ip-address", "192.168.222.122", "IP address of the VM on the network") + var configFile = flag.String( + "yaml-source-file", "", "yaml file where BMCS are defined. If this is set, ignore all other options") + flag.Parse() + var err error + if *configFile == "" { + if err = CreateLibvirtBMC(*macAddress, *vmName, *ipAddress, *networkName); err != nil { + fmt.Printf("Error occurred: %v\n", err) + os.Exit(1) + } + } else { + bmcs, err := bmoe2e.LoadBMCConfig(*configFile) + if err != nil { + os.Exit(1) + } + for _, bmc := range *bmcs { + if err = CreateLibvirtBMC(bmc.BootMacAddress, bmc.HostName, bmc.IPAddress, "baremetal-e2e"); err != nil { + fmt.Printf("Error occurred: %v\n", err) + os.Exit(1) + } + } + } +} diff --git a/test/e2e/bmc.go b/test/e2e/bmc.go index 6bea16b5a4..6d67ad350c 100644 --- a/test/e2e/bmc.go +++ b/test/e2e/bmc.go @@ -3,7 +3,6 @@ package e2e import ( "os" - . "github.com/onsi/gomega" "gopkg.in/yaml.v2" ) @@ -28,10 +27,14 @@ type BMC struct { SSHPort string `yaml:"sshPort,omitempty"` } -func LoadBMCConfig(configPath string) *[]BMC { +func LoadBMCConfig(configPath string) (*[]BMC, error) { configData, err := os.ReadFile(configPath) //#nosec - Expect(err).ToNot(HaveOccurred(), "Failed to read the bmcs config file") var bmcs []BMC - Expect(yaml.Unmarshal(configData, &bmcs)).To(Succeed()) - return &bmcs + if err != nil { + return nil, err + } + if err := yaml.Unmarshal(configData, &bmcs); err != nil { + return nil, err + } + return &bmcs, nil } diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index eb9d31ce3d..a4edf7a73a 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -170,7 +170,8 @@ var _ = SynchronizedBeforeSuite(func() []byte { err := metal3api.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) e2eConfig = LoadE2EConfig(configPath) - bmcs = LoadBMCConfig(bmcConfigPath) + bmcs, err := LoadBMCConfig(bmcConfigPath) + Expect(err).ToNot(HaveOccurred(), "Failed to read the bmcs config file") bmc = (*bmcs)[GinkgoParallelProcess()-1] clusterProxy = framework.NewClusterProxy("bmo-e2e", kubeconfigPath, scheme) }) diff --git a/test/go.mod b/test/go.mod index d6c5f876b8..efe450db4d 100644 --- a/test/go.mod +++ b/test/go.mod @@ -4,6 +4,8 @@ go 1.22 require ( github.com/cert-manager/cert-manager v1.10.0 + github.com/dypflying/go-qcow2lib v1.0.0 + github.com/libvirt/libvirt-go v7.4.0+incompatible github.com/metal3-io/baremetal-operator/apis v0.5.1 github.com/metal3-io/baremetal-operator/pkg/hardwareutils v0.5.1 github.com/onsi/ginkgo/v2 v2.17.1 diff --git a/test/go.sum b/test/go.sum index 159e7d2cd3..b43c4c15d4 100644 --- a/test/go.sum +++ b/test/go.sum @@ -70,6 +70,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= +github.com/dypflying/go-qcow2lib v1.0.0 h1:TYWEEwrBj0e7WM+t89VbbIgp3fxdEonrdv/CcJ+cqFo= +github.com/dypflying/go-qcow2lib v1.0.0/go.mod h1:pQW9aFBFRaz24xpODWDjI7j2gR16RUsV+dG1E0YgBfI= github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -183,6 +185,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/libvirt/libvirt-go v7.4.0+incompatible h1:crnSLkwPqCdXtg6jib/FxBG/hweAc/3Wxth1AehCXL4= +github.com/libvirt/libvirt-go v7.4.0+incompatible/go.mod h1:34zsnB4iGeOv7Byj6qotuW8Ya4v4Tr43ttjz/F0wjLE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= diff --git a/tools/bmh_test/clean_local_bmh_test_setup.sh b/tools/bmh_test/clean_local_bmh_test_setup.sh index 641d0083e4..6ae0c3b049 100755 --- a/tools/bmh_test/clean_local_bmh_test_setup.sh +++ b/tools/bmh_test/clean_local_bmh_test_setup.sh @@ -18,8 +18,8 @@ else fi # Clear vbmc -docker rm -f vbmc +# docker rm -f vbmc # Clear network -virsh -c qemu:///system net-destroy baremetal-e2e -virsh -c qemu:///system net-undefine baremetal-e2e +# virsh -c qemu:///system net-destroy baremetal-e2e +# virsh -c qemu:///system net-undefine baremetal-e2e diff --git a/tools/deploy.sh b/tools/deploy.sh index 3cb749a0b6..cf763062ae 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -148,7 +148,7 @@ if [[ "${DEPLOY_BASIC_AUTH}" == "true" ]]; then fi if [[ "${DEPLOY_IRONIC}" == "true" ]]; then - echo "IRONIC_HTPASSWD=$(htpasswd -n -b -B "${IRONIC_USERNAME}" "${IRONIC_PASSWORD}")" > \ + htpasswd -n -b -B "${IRONIC_USERNAME}" "${IRONIC_PASSWORD}" > \ "${TEMP_IRONIC_OVERLAY}/ironic-htpasswd" fi fi