diff --git a/.github/workflows/image-pr.yaml b/.github/workflows/image-pr.yaml index 377b5208f..241be6470 100644 --- a/.github/workflows/image-pr.yaml +++ b/.github/workflows/image-pr.yaml @@ -187,6 +187,20 @@ jobs: # needs: # - core-alpine + custom-partitioning: + uses: ./.github/workflows/reusable-custom-partitioning-test.yaml + with: + flavor: ${{ matrix.flavor }} + flavor_release: ${{ matrix.flavorRelease }} + needs: + - core + strategy: + fail-fast: true + matrix: + flavor: + - "ubuntu" + flavorRelease: + - "23.10" encryption: uses: ./.github/workflows/reusable-encryption-test.yaml with: diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index 7860418d2..45178553a 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -229,6 +229,20 @@ jobs: - flavor: opensuse flavorRelease: leap-15.5 family: opensuse + custom-partitioning: + uses: ./.github/workflows/reusable-custom-partitioning-test.yaml + with: + flavor: ${{ matrix.flavor }} + flavor_release: ${{ matrix.flavorRelease }} + needs: + - core + strategy: + fail-fast: true + matrix: + flavor: + - "opensuse" + flavorRelease: + - "leap-15.5" encryption: uses: ./.github/workflows/reusable-encryption-test.yaml with: diff --git a/.github/workflows/reusable-custom-partitioning-test.yaml b/.github/workflows/reusable-custom-partitioning-test.yaml new file mode 100644 index 000000000..df0d75f4b --- /dev/null +++ b/.github/workflows/reusable-custom-partitioning-test.yaml @@ -0,0 +1,67 @@ +name: Reusable workflow that runs the custom partitioning tests + +on: + workflow_call: + inputs: + flavor: + required: true + type: string + flavor_release: + required: true + type: string + +jobs: + test: + runs-on: fast + permissions: + id-token: write # OIDC support + contents: write + actions: read + security-events: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version-file: tests/go.mod + cache-dependency-path: tests/go.sum + - name: Block all traffic to metadata ip # For cloud runners, the metadata ip can interact with our test machines + run: | + sudo iptables -I INPUT -s 169.254.169.254 -j DROP + sudo iptables -I OUTPUT -d 169.254.169.254 -j DROP + - name: Enable KVM group perms + run: | + sudo apt-get update + sudo apt-get install -y libvirt-clients libvirt-daemon-system libvirt-daemon virtinst bridge-utils qemu qemu-system-x86 qemu-system-x86 qemu-utils qemu-kvm acl udev + sudo setfacl -m u:runner:rwx /dev/kvm + - name: Install earthly + uses: Luet-lab/luet-install-action@v1.1 + with: + repository: quay.io/kairos/packages + packages: utils/earthly + - name: Download artifacts + uses: actions/download-artifact@v4.1.4 + with: + name: kairos-${{ inputs.flavor }}-${{ inputs.flavor_release}}.iso.zip + - name: Run tests + env: + USE_QEMU: true + KVM: true + MEMORY: 4000 + CPUS: 2 + CONTAINER_IMAGE: ttl.sh/kairos-${{ inputs.flavor }}-${{ inputs.flavor_release }}-${{ github.sha }}:24h + run: | + ls *.iso + export ISO=$PWD/$(ls *.iso) + echo "ISO is: $ISO" + cp tests/go.* . + go run github.com/onsi/ginkgo/v2/ginkgo -v --label-filter "custom-partitioning" --fail-fast -r ./tests/ + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: ${{ inputs.flavor }}-${{ inputs.flavor_release }}-${{ inputs.label }}-test.logs.zip + path: tests/**/logs/* + if-no-files-found: warn diff --git a/tests/custom_partitioning_test.go b/tests/custom_partitioning_test.go new file mode 100644 index 000000000..5918f3bb6 --- /dev/null +++ b/tests/custom_partitioning_test.go @@ -0,0 +1,143 @@ +// nolint +package mos_test + +import ( + "context" + "fmt" + "os" + "path/filepath" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/spectrocloud/peg/matcher" + "github.com/spectrocloud/peg/pkg/machine" + "github.com/spectrocloud/peg/pkg/machine/types" +) + +var _ = Describe("kairos custom partitioning install", Label("custom-partitioning"), func() { + var vm VM + + BeforeEach(func() { + stateDir, err := os.MkdirTemp("", "") + Expect(err).ToNot(HaveOccurred()) + fmt.Printf("State dir: %s\n", stateDir) + + opts := defaultVMOptsNoDrives(stateDir) + opts = append(opts, types.WithDriveSize("40000")) + opts = append(opts, types.WithDriveSize("30000")) + + m, err := machine.New(opts...) + Expect(err).ToNot(HaveOccurred()) + vm = NewVM(m, stateDir) + _, err = vm.Start(context.Background()) + Expect(err).ToNot(HaveOccurred()) + + DeferCleanup(func() { + vm.Destroy(nil) + }) + + By("waiting for VM to be up for the first time") + vm.EventuallyConnects(1200) + + By("creating a configuration for custom partitioning") + configFile, err := os.CreateTemp("", "") + Expect(err).ToNot(HaveOccurred()) + defer os.Remove(configFile.Name()) + + err = os.WriteFile(configFile.Name(), []byte(customPartitionConfig()), 0744) + Expect(err).ToNot(HaveOccurred()) + + By("copying the configuration to the vm") + err = vm.Scp(configFile.Name(), "/tmp/config.yaml", "0744") + Expect(err).ToNot(HaveOccurred()) + + By("manually installing") + installationOutput, installError = vm.Sudo("kairos-agent --strict-validation --debug manual-install /tmp/config.yaml") + }) + + AfterEach(func() { + if CurrentSpecReport().Failed() { + gatherLogs(vm) + serial, _ := os.ReadFile(filepath.Join(vm.StateDir, "serial.log")) + _ = os.MkdirAll("logs", os.ModePerm|os.ModeDir) + _ = os.WriteFile(filepath.Join("logs", "serial.log"), serial, os.ModePerm) + fmt.Println(string(serial)) + } + }) + + It("installs on the pre-configured disks", func() { + Expect(installError).ToNot(HaveOccurred(), installationOutput) + By("Rebooting into live CD again") + // In qemu it's tricky to boot the second disk. In multiple disk scenarios, + // setting "-boot=cd" will make qemu try to boot from the first disk and + // then from the cdrom. + // We want to make sure that kairos-agent selected the second disk so we + // simply let it boot from the cdrom again. Hopefully if the installation + // failed, we would see the error from the manual-install command. + vm.Reboot() + vm.EventuallyConnects(1200) + + By("Checking the partition") + out, err := vm.Sudo("blkid") + Expect(err).ToNot(HaveOccurred(), out) + Expect(out).To(MatchRegexp("/dev/vdb2.*LABEL=\"COS_OEM\""), out) + Expect(out).To(MatchRegexp("/dev/vdb3.*LABEL=\"COS_RECOVERY\""), out) + Expect(out).To(MatchRegexp("/dev/vdb4.*LABEL=\"COS_STATE\""), out) + Expect(out).To(MatchRegexp("/dev/vdb5.*LABEL=\"COS_PERSISTENT\""), out) + + // Sanity check that the default disk is not touched + Expect(out).ToNot(MatchRegexp("/dev/vda.*LABEL=\"COS_PERSISTENT\""), out) + }) +}) + +func customPartitionConfig() string { + return `#cloud-config + +strict: true +debug: true + +install: + no-format: true + auto: false + poweroff: false + reboot: false + grub_options: + extra_cmdline: "rd.immucore.debug" + +users: + - name: "kairos" + passwd: "kairos" + +stages: + kairos-install.pre.before: + - if: '[ -e "/dev/vdb" ]' + name: "Create partitions" + commands: + - | + parted --script --machine -- "/dev/vdb" mklabel gpt + # Legacy bios + sgdisk --new=1:2048:+1M --change-name=1:'bios' --typecode=1:EF02 /dev/vdb + layout: + device: + path: "/dev/vdb" + add_partitions: + # For efi (comment out the legacy bios partition above) + #- fsLabel: COS_GRUB + # size: 64 + # pLabel: efi + # filesystem: "fat" + - fsLabel: COS_OEM + size: 64 + pLabel: oem + - fsLabel: COS_RECOVERY + size: 8500 + pLabel: recovery + - fsLabel: COS_STATE + size: 18000 + pLabel: state + - fsLabel: COS_PERSISTENT + pLabel: persistent + size: 0 + filesystem: "ext4" +` +} diff --git a/tests/go.mod b/tests/go.mod index 49e26447e..e82a3ab30 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -8,12 +8,10 @@ require ( github.com/lmittmann/ppm v1.0.2 github.com/makiuchi-d/gozxing v0.1.1 github.com/mudler/edgevpn v0.23.1 - github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d github.com/onsi/ginkgo/v2 v2.9.5 github.com/onsi/gomega v1.27.7 - github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac - golang.org/x/mod v0.10.0 + github.com/spectrocloud/peg v0.0.0-20240405075800-c5da7125e30f gopkg.in/yaml.v3 v3.0.1 ) @@ -25,11 +23,9 @@ require ( github.com/cavaliergopher/grab/v3 v3.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 // indirect github.com/codingsince1985/checksum v1.2.6 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/creachadair/otp v0.4.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -125,11 +121,9 @@ require ( github.com/quic-go/quic-go v0.34.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/urfave/cli v1.22.10 // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect @@ -144,6 +138,7 @@ require ( golang.org/x/crypto v0.8.0 // indirect golang.org/x/exp v0.0.0-20230420155640-133eef4313cb // indirect golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect + golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.8.0 // indirect diff --git a/tests/go.sum b/tests/go.sum index 13a599125..b49568837 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -29,8 +29,6 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 h1:xz6Nv3zcwO2Lila35hcb0QloCQsc38Al13RNEzWRpX4= -github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9/go.mod h1:2wSM9zJkl1UQEFZgSd68NfCgRz1VL1jzy/RjCg+ULrs= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -45,8 +43,6 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/otp v0.4.0 h1:3PBnESxegU3hQ0D447D75lSnTtTVfw6Eny8GviOXcqM= github.com/creachadair/otp v0.4.0/go.mod h1:mDkCUSoWN8zqxFoDMw20Boe6xeDd1jJuy6pNQQ4lCy4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -336,8 +332,6 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mudler/edgevpn v0.23.1 h1:I94vkbGoJ9NsmAt7hgoN9BPAPOvnhYI6PwqwZWixwOc= github.com/mudler/edgevpn v0.23.1/go.mod h1:A0ZECL1xTmntXUDz17KZmf3h5KsgnwzBNNSNSVpy2JM= -github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 h1:FaZD86+A9mVt7lh9glAryzQblMsbJYU2VnrdZ8yHlTs= -github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5/go.mod h1:WmKcT8ONmhDQIqQ+HxU+tkGWjzBEyY/KFO8LTGCu4AI= github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d h1:/lAg9vPAAU+s35cDMCx1IyeMn+4OYfCBPqi08Q8vXDg= github.com/mudler/go-processmanager v0.0.0-20220724164624-c45b5c61312d/go.mod h1:HGGAOJhipApckwNV8ZTliRJqxctUv3xRY+zbQEwuytc= github.com/mudler/water v0.0.0-20221010214108-8c7313014ce0 h1:Qh6ghkMgTu6siFbTf7L3IszJmshMhXxNL4V+t7IIA6w= @@ -375,14 +369,12 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= @@ -432,11 +424,8 @@ github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtB github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -474,10 +463,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spectrocloud/peg v0.0.0-20230825092931-25d89833e022 h1:/dw2RhgT412X7iXzGBrUNdwfV914VjGsakISm2Ual5Q= -github.com/spectrocloud/peg v0.0.0-20230825092931-25d89833e022/go.mod h1:L2fIdtZqbQEagjOOXwkwH3t7MjJUd7fbt52cLSQGDBg= -github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac h1:2AQBW7nOjdTy11UvomVwltuYPQyviEw+zOQ3IOO8P1g= -github.com/spectrocloud/peg v0.0.0-20231002135825-d1dc260381ac/go.mod h1:L2fIdtZqbQEagjOOXwkwH3t7MjJUd7fbt52cLSQGDBg= +github.com/spectrocloud/peg v0.0.0-20240405075800-c5da7125e30f h1:0HvH/0MSCifBcS9YzZ+XJ9PeAdlrAvi3E1iipIZmqas= +github.com/spectrocloud/peg v0.0.0-20240405075800-c5da7125e30f/go.mod h1:L2fIdtZqbQEagjOOXwkwH3t7MjJUd7fbt52cLSQGDBg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -497,7 +484,6 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= @@ -588,7 +574,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -630,7 +615,6 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/tests/tests_suite_test.go b/tests/tests_suite_test.go index 6856502b7..3dd21aa8e 100644 --- a/tests/tests_suite_test.go +++ b/tests/tests_suite_test.go @@ -113,149 +113,12 @@ func gatherLogs(vm VM) { } func startVM() (context.Context, VM) { - if os.Getenv("ISO") == "" && os.Getenv("CREATE_VM") == "true" { - fmt.Println("ISO missing") - os.Exit(1) - } - - var sshPort, spicePort int - - vmName := uuid.New().String() - stateDir, err := os.MkdirTemp("", "") Expect(err).ToNot(HaveOccurred()) fmt.Printf("State dir: %s\n", stateDir) - if os.Getenv("EMULATE_TPM") != "" { - emulateTPM(stateDir) - } - - sshPort, err = getFreePort() - Expect(err).ToNot(HaveOccurred()) - fmt.Printf("Using ssh port: %d\n", sshPort) - - memory := os.Getenv("MEMORY") - if memory == "" { - memory = "2096" - } - cpus := os.Getenv("CPUS") - if cpus == "" { - cpus = "2" - } - - driveSize := os.Getenv("DRIVE_SIZE") - if driveSize == "" { - driveSize = "25000" - } - - opts := []types.MachineOption{ - types.QEMUEngine, - types.WithISO(os.Getenv("ISO")), - types.WithMemory(memory), - types.WithCPU(cpus), - types.WithDriveSize(driveSize), - types.WithSSHPort(strconv.Itoa(sshPort)), - types.WithID(vmName), - types.WithSSHUser(user()), - types.WithSSHPass(pass()), - types.OnFailure(func(p *process.Process) { - var serial string - - out, _ := os.ReadFile(p.StdoutPath()) - err, _ := os.ReadFile(p.StderrPath()) - status, _ := p.ExitCode() - - if serialBytes, err := os.ReadFile(path.Join(p.StateDir(), "serial.log")); err != nil { - serial = fmt.Sprintf("Error reading serial log file: %s\n", err) - } else { - serial = string(serialBytes) - } - - // We are explicitly killing the qemu process. We don't treat that as an error, - // but we just print the output just in case. - fmt.Printf("\nVM Aborted.\nstdout: %s\nstderr: %s\nserial: %s\nExit status: %s\n", out, err, serial, status) - Fail(fmt.Sprintf("\nVM Aborted.\nstdout: %s\nstderr: %s\nserial: %s\nExit status: %s\n", - out, err, serial, status)) - }), - types.WithStateDir(stateDir), - // Serial output to file: https://superuser.com/a/1412150 - func(m *types.MachineConfig) error { - m.Args = append(m.Args, - "-chardev", fmt.Sprintf("stdio,mux=on,id=char0,logfile=%s,signal=off", path.Join(stateDir, "serial.log")), - "-serial", "chardev:char0", - "-mon", "chardev=char0", - ) - if os.Getenv("EMULATE_TPM") != "" { - m.Args = append(m.Args, - "-chardev", fmt.Sprintf("socket,id=chrtpm,path=%s/swtpm-sock", path.Join(stateDir, "tpm")), - "-tpmdev", "emulator,id=tpm0,chardev=chrtpm", "-device", "tpm-tis,tpmdev=tpm0", - ) - } - return nil - }, - // Firmware - func(m *types.MachineConfig) error { - FW := os.Getenv("FIRMWARE") - if FW != "" { - getwd, err := os.Getwd() - if err != nil { - return err - } - m.Args = append(m.Args, "-drive", - fmt.Sprintf("file=%s,if=pflash,format=raw,readonly=on", FW), - ) - - // Set custom vars file for efi config so we boot first from disk then from DVD with secureboot on - UKI := os.Getenv("UKI_TEST") - if UKI != "" { - // On uki use an empty efivars.fd so we can test the autoenrollment - m.Args = append(m.Args, "-drive", - fmt.Sprintf("file=%s,if=pflash,format=raw", filepath.Join(getwd, "assets/efivars.empty.fd")), - ) - } else { - m.Args = append(m.Args, "-drive", - fmt.Sprintf("file=%s,if=pflash,format=raw", filepath.Join(getwd, "assets/efivars.fd")), - ) - } - // Needed to be set for secureboot! - m.Args = append(m.Args, "-machine", "q35,smm=on") - } + opts := defaultVMOpts(stateDir) - return nil - }, - types.WithDataSource(os.Getenv("DATASOURCE")), - } - if os.Getenv("KVM") != "" { - opts = append(opts, func(m *types.MachineConfig) error { - m.Args = append(m.Args, - "-enable-kvm", - ) - return nil - }) - } - - if os.Getenv("USE_QEMU") == "true" { - opts = append(opts, types.QEMUEngine) - - // You can connect to it with "spicy" or other tool. - // DISPLAY is already taken on Linux X sessions - if os.Getenv("MACHINE_SPICY") != "" { - spicePort, _ = getFreePort() - for spicePort == sshPort { // avoid collision - spicePort, _ = getFreePort() - } - display := fmt.Sprintf("-spice port=%d,addr=127.0.0.1,disable-ticketing=yes", spicePort) - opts = append(opts, types.WithDisplay(display)) - - cmd := exec.Command("spicy", - "-h", "127.0.0.1", - "-p", strconv.Itoa(spicePort)) - err = cmd.Start() - Expect(err).ToNot(HaveOccurred()) - } - } else { - opts = append(opts, types.VBoxEngine) - } m, err := machine.New(opts...) Expect(err).ToNot(HaveOccurred()) @@ -413,3 +276,156 @@ func isReadable(fileName string) bool { file.Close() return true } + +func defaultVMOpts(stateDir string) []types.MachineOption { + opts := defaultVMOptsNoDrives(stateDir) + + driveSize := os.Getenv("DRIVE_SIZE") + if driveSize == "" { + driveSize = "25000" + } + + opts = append(opts, types.WithDriveSize(driveSize)) + + return opts +} + +func defaultVMOptsNoDrives(stateDir string) []types.MachineOption { + var err error + + if os.Getenv("ISO") == "" && os.Getenv("CREATE_VM") == "true" { + fmt.Println("ISO missing") + os.Exit(1) + } + + var sshPort, spicePort int + + vmName := uuid.New().String() + + if os.Getenv("EMULATE_TPM") != "" { + emulateTPM(stateDir) + } + + sshPort, err = getFreePort() + Expect(err).ToNot(HaveOccurred()) + fmt.Printf("Using ssh port: %d\n", sshPort) + + memory := os.Getenv("MEMORY") + if memory == "" { + memory = "2096" + } + cpus := os.Getenv("CPUS") + if cpus == "" { + cpus = "2" + } + + opts := []types.MachineOption{ + types.QEMUEngine, + types.WithISO(os.Getenv("ISO")), + types.WithMemory(memory), + types.WithCPU(cpus), + types.WithSSHPort(strconv.Itoa(sshPort)), + types.WithID(vmName), + types.WithSSHUser(user()), + types.WithSSHPass(pass()), + types.OnFailure(func(p *process.Process) { + var serial string + + out, _ := os.ReadFile(p.StdoutPath()) + err, _ := os.ReadFile(p.StderrPath()) + status, _ := p.ExitCode() + + if serialBytes, err := os.ReadFile(path.Join(p.StateDir(), "serial.log")); err != nil { + serial = fmt.Sprintf("Error reading serial log file: %s\n", err) + } else { + serial = string(serialBytes) + } + + // We are explicitly killing the qemu process. We don't treat that as an error, + // but we just print the output just in case. + fmt.Printf("\nVM Aborted.\nstdout: %s\nstderr: %s\nserial: %s\nExit status: %s\n", out, err, serial, status) + Fail(fmt.Sprintf("\nVM Aborted.\nstdout: %s\nstderr: %s\nserial: %s\nExit status: %s\n", + out, err, serial, status)) + }), + types.WithStateDir(stateDir), + // Serial output to file: https://superuser.com/a/1412150 + func(m *types.MachineConfig) error { + m.Args = append(m.Args, + "-chardev", fmt.Sprintf("stdio,mux=on,id=char0,logfile=%s,signal=off", path.Join(stateDir, "serial.log")), + "-serial", "chardev:char0", + "-mon", "chardev=char0", + ) + if os.Getenv("EMULATE_TPM") != "" { + m.Args = append(m.Args, + "-chardev", fmt.Sprintf("socket,id=chrtpm,path=%s/swtpm-sock", path.Join(stateDir, "tpm")), + "-tpmdev", "emulator,id=tpm0,chardev=chrtpm", "-device", "tpm-tis,tpmdev=tpm0", + ) + } + return nil + }, + // Firmware + func(m *types.MachineConfig) error { + FW := os.Getenv("FIRMWARE") + if FW != "" { + getwd, err := os.Getwd() + if err != nil { + return err + } + m.Args = append(m.Args, "-drive", + fmt.Sprintf("file=%s,if=pflash,format=raw,readonly=on", FW), + ) + + // Set custom vars file for efi config so we boot first from disk then from DVD with secureboot on + UKI := os.Getenv("UKI_TEST") + if UKI != "" { + // On uki use an empty efivars.fd so we can test the autoenrollment + m.Args = append(m.Args, "-drive", + fmt.Sprintf("file=%s,if=pflash,format=raw", filepath.Join(getwd, "assets/efivars.empty.fd")), + ) + } else { + m.Args = append(m.Args, "-drive", + fmt.Sprintf("file=%s,if=pflash,format=raw", filepath.Join(getwd, "assets/efivars.fd")), + ) + } + // Needed to be set for secureboot! + m.Args = append(m.Args, "-machine", "q35,smm=on") + } + + return nil + }, + types.WithDataSource(os.Getenv("DATASOURCE")), + } + if os.Getenv("KVM") != "" { + opts = append(opts, func(m *types.MachineConfig) error { + m.Args = append(m.Args, + "-enable-kvm", + ) + return nil + }) + } + + if os.Getenv("USE_QEMU") == "true" { + opts = append(opts, types.QEMUEngine) + + // You can connect to it with "spicy" or other tool. + // DISPLAY is already taken on Linux X sessions + if os.Getenv("MACHINE_SPICY") != "" { + spicePort, _ = getFreePort() + for spicePort == sshPort { // avoid collision + spicePort, _ = getFreePort() + } + display := fmt.Sprintf("-spice port=%d,addr=127.0.0.1,disable-ticketing=yes", spicePort) + opts = append(opts, types.WithDisplay(display)) + + cmd := exec.Command("spicy", + "-h", "127.0.0.1", + "-p", strconv.Itoa(spicePort)) + err = cmd.Start() + Expect(err).ToNot(HaveOccurred()) + } + } else { + opts = append(opts, types.VBoxEngine) + } + + return opts +}