diff --git a/mantle/kola/tests/coretest/core.go b/mantle/kola/tests/coretest/core.go index 8aaa02c073d73106f27bebd8603417f2a70d7031..8df07f2615c120497bf5d8bac7ff68e5d6c3d69a 100644 --- a/mantle/kola/tests/coretest/core.go +++ b/mantle/kola/tests/coretest/core.go @@ -11,6 +11,7 @@ import ( "github.com/pborman/uuid" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/register" "github.com/coreos/coreos-assembler/mantle/util" ) @@ -23,9 +24,6 @@ const ( // RHCOS services we expect disabled/inactive var offServices = []string{ "dnsmasq.service", - "iscsid.service", - "iscsid.socket", - "iscsiuio.service", "nfs-blkmap.service", "nfs-idmapd.service", "nfs-mountd.service", @@ -42,6 +40,7 @@ var offServices = []string{ func init() { register.RegisterTest(®ister.Test{ Name: "basic", + Description: "Verify basic functionalities like SSH, systemd services, useradd, etc.", Run: LocalTests, ClusterSize: 1, NativeFuncs: map[string]register.NativeFuncWrap{ @@ -60,9 +59,10 @@ func init() { // https://github.com/coreos/mantle/issues/1132 register.RegisterTest(®ister.Test{ Name: "nestos.internet", + Description: "Verify that docker echo and get head work.", Run: InternetTests, ClusterSize: 1, - Flags: []register.Flag{register.RequiresInternetAccess}, + Tags: []string{kola.NeedsInternetTag}, NativeFuncs: map[string]register.NativeFuncWrap{ "DockerEcho": register.CreateNativeFuncWrap(TestDockerEcho), "DockerWgetHead": register.CreateNativeFuncWrap(TestDockerWgetHead), @@ -71,6 +71,7 @@ func init() { }) register.RegisterTest(®ister.Test{ Name: "rootfs.uuid", + Description: "Verify that the root disk's GUID was set to a random one on first boot.", Run: LocalTests, ClusterSize: 1, NativeFuncs: map[string]register.NativeFuncWrap{ @@ -81,6 +82,7 @@ func init() { }) register.RegisterTest(®ister.Test{ Name: "nestos.services-disabled", + Description: "Verify the specific services are disabled/inactive", Run: LocalTests, ClusterSize: 1, NativeFuncs: map[string]register.NativeFuncWrap{ @@ -337,8 +339,13 @@ func checkService(unit string) error { // https://github.com/systemd/systemd/blob/master/src/systemd/sd-messages.h // For oneshot type services that remain after exit, STARTED being "done" // should imply that the service ran and exited successfully. - c := exec.Command("journalctl", "-o", "json", "MESSAGE_ID=39f53479d3a045ac8e11786248231fbf", - "UNIT="+unit) + // + // We add `--directory=/var/log/journal` here because we were seeing a race + // condition starting on systemd 254 on s390x/ppc64le where we would get + // two duplicate entries (one each from {/var,/run}log/journal/) returned + // and it would break the json.Unmarshal below. + c := exec.Command("journalctl", "-o", "json", "--directory=/var/log/journal", + "MESSAGE_ID=39f53479d3a045ac8e11786248231fbf", "UNIT="+unit) out, err := c.Output() if err != nil { return fmt.Errorf("journalctl: %s", err) diff --git a/mantle/kola/tests/crio/crio.go b/mantle/kola/tests/crio/crio.go index e6535c03c377cca0bfbfa753076774112456edfc..d1507efd5a267746eabc2d5fc640bb119b366890 100644 --- a/mantle/kola/tests/crio/crio.go +++ b/mantle/kola/tests/crio/crio.go @@ -25,6 +25,7 @@ import ( "golang.org/x/crypto/ssh" "golang.org/x/net/context" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/cluster" "github.com/coreos/coreos-assembler/mantle/kola/register" "github.com/coreos/coreos-assembler/mantle/kola/tests/util" @@ -189,20 +190,23 @@ func init() { Run: crioBaseTests, ClusterSize: 1, Name: `crio.base`, - // crio pods require fetching a kubernetes pause image - Flags: []register.Flag{register.RequiresInternetAccess}, + Description: "Verify cri-o basic funcions work, include storage driver is overlay, storage root is /varlib/containers/storage, cgroup driver is systemd, and cri-o containers have reliable networking", Distros: []string{"rhcos", "nestos"}, UserData: enableCrioIgn, RequiredTag: "crio", + // crio pods require fetching a kubernetes pause image + Tags: []string{"crio", kola.NeedsInternetTag}, }) register.RegisterTest(®ister.Test{ Run: crioNetwork, ClusterSize: 2, Name: "crio.network", - Flags: []register.Flag{register.RequiresInternetAccess}, + Description: "Verify crio containers can make network connections outside of the host.", Distros: []string{"rhcos", "nestos"}, UserData: enableCrioIgn, RequiredTag: "crio", + // this test requires net connections outside the host + Tags: []string{"crio", kola.NeedsInternetTag}, // qemu machines cannot communicate between each other ExcludePlatforms: []string{"qemu"}, }) @@ -367,12 +371,7 @@ func crioNetwork(c cluster.TestCluster) { // crioNetworksReliably verifies that crio containers have a reliable network func crioNetworksReliably(c cluster.TestCluster) { m := c.Machines()[0] - - // Figure out the host IP address on the crio default bridge. This is - // required as the default subnet was changed in 1.18 to avoid a conflict - // with the default podman bridge. - subnet := c.MustSSH(m, "jq --raw-output '.ipam.ranges[0][0].subnet' /usr/etc/cni/net.d/100-crio-bridge.conf") - hostIP := fmt.Sprintf("%s.1", strings.TrimSuffix(string(subnet), ".0/16")) + hostIP := "127.0.0.1" // Here we generate 10 pods, each will run a container responsible for // pinging to host diff --git a/mantle/kola/tests/etcd/rhcos.go b/mantle/kola/tests/etcd/rhcos.go index c0973e82c6f14dca1bffa68d0939146ff9b7c050..3a85fb7d42de00f713a90ee967bd0381e15385c4 100644 --- a/mantle/kola/tests/etcd/rhcos.go +++ b/mantle/kola/tests/etcd/rhcos.go @@ -22,6 +22,7 @@ import ( "github.com/coreos/pkg/capnslog" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/cluster" "github.com/coreos/coreos-assembler/mantle/kola/register" "github.com/coreos/coreos-assembler/mantle/platform/conf" @@ -35,6 +36,7 @@ func init() { Run: rhcosClusterInsecure, ClusterSize: 3, Name: "rhcos.etcd.cluster.insecure", + Description: "Verify that an etcd cluster in podman without TLS or external discovery services works.", UserData: conf.Ignition(`{ "ignition": { "version": "3.0.0" }, "systemd": { @@ -51,7 +53,7 @@ func init() { ] } }`), - Flags: []register.Flag{register.RequiresInternetAccess}, // fetching etcd requires networking + Tags: []string{kola.NeedsInternetTag}, // fetching etcd requires networking Distros: []string{"rhcos"}, // qemu machines cannot communicate between each other ExcludePlatforms: []string{"qemu"}, @@ -60,6 +62,7 @@ func init() { Run: rhcosClusterTLS, ClusterSize: 3, Name: "rhcos.etcd.cluster.tls", + Description: "Verify that an etcd cluster in podman with TLS without discovery services works.", UserData: conf.Ignition(`{ "ignition": { "version": "3.0.0" }, "systemd": { @@ -85,7 +88,7 @@ func init() { ] } }`), - Flags: []register.Flag{register.RequiresInternetAccess}, // fetching etcd requires networking + Tags: []string{kola.NeedsInternetTag}, // fetching etcd requires networking Distros: []string{"rhcos"}, // qemu machines cannot communicate between each other ExcludePlatforms: []string{"qemu"}, diff --git a/mantle/kola/tests/fips/fips.go b/mantle/kola/tests/fips/fips.go index d7e5489f197dfec4e47e6234f90d845b5bd75d60..bc6ebff0e3ae80f85ca8c13b138bfbbd4eac8977 100644 --- a/mantle/kola/tests/fips/fips.go +++ b/mantle/kola/tests/fips/fips.go @@ -12,6 +12,7 @@ func init() { Run: fipsEnableTest, ClusterSize: 1, Name: `fips.enable`, + Description: "Verify that fips enabled works.", Flags: []register.Flag{}, Distros: []string{"rhcos"}, UserData: conf.Ignition(`{ @@ -59,6 +60,7 @@ func init() { Run: fipsEnableTest, ClusterSize: 1, Name: `fips.enable.partitions`, + Description: "Verify that fips enabled works if custom partitions are present.", Flags: []register.Flag{}, Distros: []string{"rhcos"}, Platforms: []string{"qemu"}, diff --git a/mantle/kola/tests/ignition/empty.go b/mantle/kola/tests/ignition/empty.go index 775fc080ba569b3de31680595f09e85fa5bea5d3..b8d9cd5a1329d9c61f1d25c5d5062423a00cddd8 100644 --- a/mantle/kola/tests/ignition/empty.go +++ b/mantle/kola/tests/ignition/empty.go @@ -26,6 +26,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.misc.empty", + Description: "Verify that not inject SSH key into Ignition works on NestOS.", Run: noIgnitionSSHKey, ClusterSize: 1, ExcludePlatforms: []string{"qemu", "esx"}, @@ -35,6 +36,7 @@ func init() { }) register.RegisterTest(®ister.Test{ Name: "nestos.ignition.v3.noop", + Description: "Verify that not inject SSH key into Ignition with v3.0.0 works on NestOS.", Run: noIgnitionSSHKey, ClusterSize: 1, ExcludePlatforms: []string{"qemu", "esx"}, diff --git a/mantle/kola/tests/ignition/execution.go b/mantle/kola/tests/ignition/execution.go index aee4184607ee8bd15542882a268818652a087039..c1dba2601d82d7465413fa899643eff9dec46e3c 100644 --- a/mantle/kola/tests/ignition/execution.go +++ b/mantle/kola/tests/ignition/execution.go @@ -23,6 +23,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.once", + Description: "Verify Ignition only runs once.", Run: runsOnce, ClusterSize: 1, Tags: []string{"ignition"}, diff --git a/mantle/kola/tests/ignition/journaldEntry.go b/mantle/kola/tests/ignition/journaldEntry.go deleted file mode 100644 index 841df71360a5cb8bf9acdf27af054d3522106710..0000000000000000000000000000000000000000 --- a/mantle/kola/tests/ignition/journaldEntry.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Red Hat -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package ignition - -import ( - "fmt" - "strconv" - - "github.com/coreos/coreos-assembler/mantle/kola/cluster" - "github.com/coreos/coreos-assembler/mantle/kola/register" -) - -const ignitionJournalMsgId = "57124006b5c94805b77ce473e92a8aeb" - -func init() { - register.RegisterTest(®ister.Test{ - Name: "nestos.ignition.journald-log", - Run: sendJournaldLog, - ClusterSize: 1, - // Since RHCOS uses the 2x spec and not 3x. - ExcludeDistros: []string{"rhcos"}, - }) -} - -func sendJournaldLog(c cluster.TestCluster) { - m := c.Machines()[0] - // See https://github.com/coreos/ignition/pull/958 - // for the MESSAGE_ID source. It will track the - // journal messages related to an ignition config - // provided by the user. - out := c.MustSSH(m, fmt.Sprintf("journalctl -o json-pretty MESSAGE_ID=%s | jq -s '.[] | select(.IGNITION_CONFIG_TYPE == \"user\")' | wc -l", ignitionJournalMsgId)) - num, _ := strconv.Atoi(string(out)) - if num == 0 { - c.Fatalf("Ignition didn't write %s", ignitionJournalMsgId) - } -} diff --git a/mantle/kola/tests/ignition/luks.go b/mantle/kola/tests/ignition/luks.go index 5a5b3b75d00dbe8d261b7d9ec32f20bad36d9898..74978caa745a96cee2e035d7319fa8b3c7dad539 100644 --- a/mantle/kola/tests/ignition/luks.go +++ b/mantle/kola/tests/ignition/luks.go @@ -164,9 +164,9 @@ func runTest(c cluster.TestCluster, tpm2 bool, threshold int, killTangAfterFirst opts := platform.MachineOptions{ MinMemory: 4096, } - // ppc64le and aarch64 use 64K pages + // ppc64le uses 64K pages; see similar logic in harness.go and boot-mirror.go switch coreosarch.CurrentRpmArch() { - case "ppc64le", "aarch64": + case "ppc64le": opts.MinMemory = 8192 } m, err := c.NewMachineWithOptions(ignition, opts) diff --git a/mantle/kola/tests/ignition/mount.go b/mantle/kola/tests/ignition/mount.go index 46527b5b8caea108519b9a6066efbb5a1b832d9d..e10656af37226a5611cfe6cffbd105d44eecd8e9 100644 --- a/mantle/kola/tests/ignition/mount.go +++ b/mantle/kola/tests/ignition/mount.go @@ -31,6 +31,7 @@ func init() { // mount disks to `/var/log` and `/var/lib/containers` register.RegisterTest(®ister.Test{ Name: "nestos.ignition.mount.disks", + Description: "Verify that we can mount two disks through Ignition and write to the mountpoints.", Run: testMountDisks, ClusterSize: 0, Platforms: []string{"qemu"}, @@ -39,6 +40,7 @@ func init() { // create new partiitons with disk `vda` register.RegisterTest(®ister.Test{ Name: "nestos.ignition.mount.partitions", + Description: "Verify that we can create new partitions through Ignition.", Run: testMountPartitions, ClusterSize: 0, Platforms: []string{"qemu"}, @@ -52,7 +54,7 @@ func testMountDisks(c cluster.TestCluster) { config := setupIgnitionConfig() options := platform.MachineOptions{ - AdditionalDisks: []string{"1024M", "1024M"}, + AdditionalDisks: []string{"1G", "1G"}, } ignDisks := []types.Disk{ diff --git a/mantle/kola/tests/ignition/passwd.go b/mantle/kola/tests/ignition/passwd.go index 2c784a0e4dc5016a1a1a39bf8261f7019cef8f91..3f7f2aba67f35cd1c5bf14d9ec044c9883ebf42a 100644 --- a/mantle/kola/tests/ignition/passwd.go +++ b/mantle/kola/tests/ignition/passwd.go @@ -27,6 +27,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.groups", + Description: "Verify that we can create user groups through Ignition.", Run: groups, ClusterSize: 1, Tags: []string{"ignition"}, @@ -55,6 +56,7 @@ func init() { }) register.RegisterTest(®ister.Test{ Name: "nestos.ignition.v2.users", + Description: "Verify that we can create users through Ignition.", Run: users, ClusterSize: 1, Tags: []string{"ignition"}, diff --git a/mantle/kola/tests/ignition/resource.go b/mantle/kola/tests/ignition/resource.go index 7f3c342b83ef52a0d183c225d29846e7df90349e..903cd4376050e4bc28475bbb4b45e57a8067f2c5 100644 --- a/mantle/kola/tests/ignition/resource.go +++ b/mantle/kola/tests/ignition/resource.go @@ -76,102 +76,6 @@ func init() { ExcludePlatforms: []string{"qemu"}, Timeout: 20 * time.Minute, }) - register.RegisterTest(®ister.Test{ - Name: "nestos.ignition.resource.remote", - Run: resourceRemote, - ClusterSize: 1, - Flags: []register.Flag{register.RequiresInternetAccess}, - Tags: []string{"ignition"}, - // https://github.com/coreos/bugs/issues/2205 for DO - ExcludePlatforms: []string{"do"}, - UserData: conf.Ignition(`{ - "ignition": { - "version": "3.0.0" - }, - "storage": { - "files": [ - { - "path": "/var/resource/http", - "contents": { - "source": "http://nestos.org.cn/kola/anonymous" - }, - "mode": 420 - }, - { - "path": "/var/resource/https", - "contents": { - "source": "https://nestos.org.cn/kola/anonymous" - }, - "mode": 420 - } - ] - } - }`), - }) - register.RegisterTest(®ister.Test{ - Name: "nestos.ignition.resource.s3", - Run: resourceS3, - ClusterSize: 1, - Platforms: []string{"aws"}, - Tags: []string{"ignition"}, - UserData: conf.Ignition(`{ - "ignition": { - "version": "3.0.0", - "config": { - "merge": [{ - "source": "s3://rh-kola-fixtures/resources/authenticated-var-v3.ign" - }] - } - }, - "storage": { - "files": [ - { - "path": "/var/resource/s3-auth", - "contents": { - "source": "s3://rh-kola-fixtures/resources/authenticated" - }, - "mode": 420 - } - ] - } - }`), - }) - // TODO: once Ignition supports this on all channels/distros - // this test should be rolled into coreos.ignition.resources.remote - // Test specifically for versioned s3 objects - register.RegisterTest(®ister.Test{ - Name: "nestos.ignition.resource.s3.versioned", - Run: resourceS3Versioned, - ClusterSize: 1, - Flags: []register.Flag{register.RequiresInternetAccess}, - Tags: []string{"ignition"}, - // https://github.com/coreos/bugs/issues/2205 for DO - ExcludePlatforms: []string{"do"}, - UserData: conf.Ignition(`{ - "ignition": { - "version": "3.0.0" - }, - "storage": { - "files": [ - { - "path": "/var/resource/original", - "contents": { - "source": "https://rh-kola-fixtures.s3.amazonaws.com/resources/versioned?versionId=Ym98GTx0npVaJznSAd0I1eUjFoZMP8Zo" - }, - "mode": 420 - }, - { - "path": "/var/resource/latest", - "contents": { - "source": "https://rh-kola-fixtures.s3.amazonaws.com/resources/versioned" - }, - "mode": 420 - } - ] - } - }`), - Distros: []string{"rhcos"}, - }) } func resourceLocal(c cluster.TestCluster) { @@ -198,48 +102,6 @@ func resourceLocal(c cluster.TestCluster) { }) } -func resourceRemote(c cluster.TestCluster) { - m := c.Machines()[0] - - checkResources(c, m, map[string]string{ - "http": "kola-anonymous", - "https": "kola-anonymous", - }) -} - -func resourceS3(c cluster.TestCluster) { - m := c.Machines()[0] - - checkResources(c, m, map[string]string{ - // object accessible by any authenticated S3 user, such as - // the IAM role associated with the instance - "s3-auth": "kola-authenticated", - // object created by configuration accessible by any authenticated - // S3 user, such as the IAM role associated with the instance - "s3-config": "kola-config", - }) - - // verify that the objects are inaccessible anonymously - for _, objectName := range []string{"authenticated", "authenticated.ign"} { - _, _, err := m.SSH("curl -sf https://rh-kola-fixtures.s3.amazonaws.com/resources/" + objectName) - if err == nil { - c.Fatal("anonymously fetching authenticated resource should have failed, but did not") - } - } - - // ...but that the anonymous object is accessible - c.RunCmdSync(m, "curl -sf https://rh-kola-fixtures.s3.amazonaws.com/resources/anonymous") -} - -func resourceS3Versioned(c cluster.TestCluster) { - m := c.Machines()[0] - - checkResources(c, m, map[string]string{ - "original": "original", - "latest": "updated", - }) -} - func checkResources(c cluster.TestCluster, m platform.Machine, resources map[string]string) { for filename, expectedContents := range resources { contents := c.MustSSH(m, fmt.Sprintf("sudo cat /var/resource/%s", filename)) diff --git a/mantle/kola/tests/ignition/sethostname.go b/mantle/kola/tests/ignition/sethostname.go index 096edf9ad3883d4c40bee7924fbabeb3fb689ebc..7eb28f9ceb3d22470ef86a026935e88ce1701280 100644 --- a/mantle/kola/tests/ignition/sethostname.go +++ b/mantle/kola/tests/ignition/sethostname.go @@ -45,6 +45,7 @@ func init() { // after the machine has booted. register.RegisterTest(®ister.Test{ Name: "nestos.ignition.sethostname", + Description: "Verify that Ignition supports setting hostname.", Run: setHostname, ClusterSize: 1, UserData: config, diff --git a/mantle/kola/tests/ignition/symlink.go b/mantle/kola/tests/ignition/symlink.go index 588127146d9f4d2a89f80624d38ee1d36a8f8230..e13a20bb053ede864f43a5764ec12b6387386f48 100644 --- a/mantle/kola/tests/ignition/symlink.go +++ b/mantle/kola/tests/ignition/symlink.go @@ -23,6 +23,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.symlink", + Description: "Verify that Ignition supports the creation of absolute symlink.", Run: writeAbsoluteSymlink, ClusterSize: 1, Platforms: []string{"qemu"}, diff --git a/mantle/kola/tests/ignition/systemd.go b/mantle/kola/tests/ignition/systemd.go index b7bafa47a557b8b69e4b8807317a9779cba7208c..3a97c2c87b9be375eac16a4b7e8ef1b02bb022c9 100644 --- a/mantle/kola/tests/ignition/systemd.go +++ b/mantle/kola/tests/ignition/systemd.go @@ -23,6 +23,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.systemd.enable-service", + Description: "Verify that Ignition supports enabling an existing service.", Run: enableSystemdService, ClusterSize: 1, Tags: []string{"ignition"}, diff --git a/mantle/kola/tests/ignition/units.go b/mantle/kola/tests/ignition/units.go index 07077e03b0342057c8051f235e45e23bd2a5110f..da1d8134ec4c6fe24dd84b9afe40ca21b848d726 100644 --- a/mantle/kola/tests/ignition/units.go +++ b/mantle/kola/tests/ignition/units.go @@ -23,6 +23,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "nestos.ignition.instantiated.enable-unit", + Description: "Verify that Ignition supports enabling systemd instantiated services.", Run: enableSystemdInstantiatedService, ClusterSize: 1, Tags: []string{"ignition"}, diff --git a/mantle/kola/tests/metadata/contents.go b/mantle/kola/tests/metadata/contents.go index 3854a41501f6a09bd6ad88e426409d2721a7b160..eab7c4a089039295343b4a5f606fdedf36700b88 100644 --- a/mantle/kola/tests/metadata/contents.go +++ b/mantle/kola/tests/metadata/contents.go @@ -39,6 +39,7 @@ func init() { register.RegisterTest(®ister.Test{ Name: "nestos.metadata.aws", + Description: "Verify the metadata on AWS.", Run: verifyAWS, ClusterSize: 1, Platforms: []string{"aws"}, @@ -48,6 +49,7 @@ func init() { register.RegisterTest(®ister.Test{ Name: "nestos.metadata.azure", + Description: "Verify the metadata on Azure.", Run: verifyAzure, ClusterSize: 1, Platforms: []string{"azure"}, @@ -57,6 +59,7 @@ func init() { register.RegisterTest(®ister.Test{ Name: "nestos.metadata.packet", + Description: "Verify the metadata on Packet.", Run: verifyPacket, ClusterSize: 1, Platforms: []string{"packet"}, diff --git a/mantle/kola/tests/misc/auth.go b/mantle/kola/tests/misc/auth.go index de7719d1d8518b26a5e690cd74fd640f5eb4fb18..9f827ae42040b504139d8968d285ec4822cabee5 100644 --- a/mantle/kola/tests/misc/auth.go +++ b/mantle/kola/tests/misc/auth.go @@ -24,6 +24,7 @@ func init() { Run: AuthVerify, ClusterSize: 1, Name: "nestos.auth.verify", + Description: "Verify that invalid password prevents access to the host.", }) } diff --git a/mantle/kola/tests/misc/aws.go b/mantle/kola/tests/misc/aws.go index 7e70053ab633ff09eb31470408c4c0177e1833d2..9acf723e88f6a55a09e9089a27d2cc8c8dbb7638 100644 --- a/mantle/kola/tests/misc/aws.go +++ b/mantle/kola/tests/misc/aws.go @@ -22,6 +22,7 @@ import ( func init() { register.RegisterTest(®ister.Test{ Name: "coreos.misc.aws.diskfriendlyname", + Description: "Verify invariants on AWS instances.", Platforms: []string{"aws"}, Run: awsVerifyDiskFriendlyName, ClusterSize: 1, diff --git a/mantle/kola/tests/misc/boot-mirror.go b/mantle/kola/tests/misc/boot-mirror.go index adab4305dc83614b2b63f743b0d14c8e052fc033..d885491a8e163ec04bd7d9740c9f984fdd19499d 100644 --- a/mantle/kola/tests/misc/boot-mirror.go +++ b/mantle/kola/tests/misc/boot-mirror.go @@ -98,10 +98,15 @@ func runBootMirrorTest(c cluster.TestCluster) { var err error options := platform.QemuMachineOptions{ MachineOptions: platform.MachineOptions{ - AdditionalDisks: []string{"5120M", "5120M"}, + AdditionalDisks: []string{"5G", "5G"}, MinMemory: 4096, }, } + // ppc64le uses 64K pages; see similar logic in harness.go and luks.go + switch coreosarch.CurrentRpmArch() { + case "ppc64le": + options.MinMemory = 8192 + } // FIXME: for QEMU tests kola currently assumes the host CPU architecture // matches the one under test userdata := bootmirror.Subst("LAYOUT", coreosarch.CurrentRpmArch()) @@ -145,10 +150,15 @@ func runBootMirrorLUKSTest(c cluster.TestCluster) { var err error options := platform.QemuMachineOptions{ MachineOptions: platform.MachineOptions{ - AdditionalDisks: []string{"5120M"}, + AdditionalDisks: []string{"5G"}, MinMemory: 4096, }, } + // ppc64le uses 64K pages; see similar logic in harness.go and luks.go + switch coreosarch.CurrentRpmArch() { + case "ppc64le": + options.MinMemory = 8192 + } // FIXME: for QEMU tests kola currently assumes the host CPU architecture // matches the one under test userdata := bootmirrorluks.Subst("LAYOUT", coreosarch.CurrentRpmArch()) @@ -232,6 +242,15 @@ func detachPrimaryBlockDevice(c cluster.TestCluster, m platform.Machine) { }); err != nil { c.Fatalf("Failed to retrieve boot ID: %v", err) } + + // Give some time to the host before doing the reboot. Without it, we've noticed + // that rebooting too quickly after ripping out the primary device can trigger + // a kernel panic on ppc64le. This may be memory-related since the same panic + // happens more easily if memory is lowered to 4G. + if coreosarch.CurrentRpmArch() == "ppc64le" { + time.Sleep(60 * time.Second) + } + err := m.Reboot() if err != nil { c.Fatalf("Failed to reboot the machine: %v", err) diff --git a/mantle/kola/tests/misc/files.go b/mantle/kola/tests/misc/files.go index 407898d983f75da0b2b1c9efbba08f0ad3356471..4740f65bc7a920ed5ab6c0a05bc15d72fd2535f0 100644 --- a/mantle/kola/tests/misc/files.go +++ b/mantle/kola/tests/misc/files.go @@ -28,6 +28,7 @@ func init() { Run: Filesystem, ClusterSize: 1, Name: "nestos.filesystem", + Description: "Verify the permissions are correct on the filesystem.", Distros: []string{"fcos", "nestos"}, }) } @@ -78,7 +79,6 @@ func StickyDirs(c cluster.TestCluster) { "/tmp", "/var/tmp", "/run/user/1000/libpod", - "/run/ephemeral/var/tmp", } output := c.MustSSH(m, fmt.Sprintf("sudo find / -ignore_readdir_race -path %s -prune -o -type d -perm /1000 -print", strings.Join(ignore, " -prune -o -path "))) diff --git a/mantle/kola/tests/misc/multipath.go b/mantle/kola/tests/misc/multipath.go index 48ba45930f1153e72f2e98f17f1b6e0a5b9442f9..f8d199e73d78220fe42275e86fd1d3fbcaa00323 100644 --- a/mantle/kola/tests/misc/multipath.go +++ b/mantle/kola/tests/misc/multipath.go @@ -96,24 +96,27 @@ systemd: func init() { register.RegisterTest(®ister.Test{ - Name: "multipath.day1", - Run: runMultipathDay1, - ClusterSize: 1, + Name: "multipath.day1", + Description: "Verify that multipath can be configured day 1 through Ignition.", + Run: runMultipathDay1, + ClusterSize: 1, Platforms: []string{"qemu"}, ExcludeDistros: []string{"nestos"}, - UserData: mpath_on_boot_day1, - MultiPathDisk: true, + UserData: mpath_on_boot_day1, + MultiPathDisk: true, }) register.RegisterTest(®ister.Test{ - Name: "multipath.day2", - Run: runMultipathDay2, - ClusterSize: 1, + Name: "multipath.day2", + Description: "Verify that multipath can be configured day 2 through Ignition.", + Run: runMultipathDay2, + ClusterSize: 1, Platforms: []string{"qemu"}, ExcludeDistros: []string{"nestos"}, - MultiPathDisk: true, + MultiPathDisk: true, }) register.RegisterTest(®ister.Test{ Name: "multipath.partition", + Description: "Verify that multipath can be configured for a partition.", Run: runMultipathPartition, ClusterSize: 1, Platforms: []string{"qemu"}, diff --git a/mantle/kola/tests/misc/network.go b/mantle/kola/tests/misc/network.go index 3805e6fef2db4cdd8a548a81069c6eac9bf60ae9..104c96e3729a63048bdfad41111339606748f10d 100644 --- a/mantle/kola/tests/misc/network.go +++ b/mantle/kola/tests/misc/network.go @@ -60,24 +60,14 @@ func init() { Platforms: []string{"qemu"}, }) // This test follows the same network configuration used on https://github.com/RHsyseng/rhcos-slb - // with a slight change, where the MCO script is run from ignition: https://github.com/RHsyseng/rhcos-slb/blob/main/setup-ovs.sh. - // and we're using veth pairs instead of real nic when setting the bond + // with a slight change, where the script originally run by MCO is run from + // ignition: https://github.com/RHsyseng/rhcos-slb/blob/161a421f8fdcdb4b08fb6366daa8fe1b75cbe095/init-interfaces.sh. register.RegisterTest(®ister.Test{ - Run: NetworkBondWithDhcp, + Run: InitInterfacesTest, ClusterSize: 0, - Name: "rhcos.network.bond-with-dhcp", - Timeout: 20 * time.Minute, - Distros: []string{"rhcos"}, - Platforms: []string{"qemu"}, - }) - // This test follows the same network configuration used on https://github.com/RHsyseng/rhcos-slb - // with a slight change, where the MCO script is run from ignition: https://github.com/RHsyseng/rhcos-slb/blob/main/setup-ovs.sh. - // and we're using veth pairs instead of real nic when setting the bond - register.RegisterTest(®ister.Test{ - Run: NetworkBondWithRestart, - ClusterSize: 0, - Name: "rhcos.network.bond-with-restart", - Timeout: 20 * time.Minute, + Name: "rhcos.network.init-interfaces-test", + Description: "Verify init-interfaces script works in both fresh setup and reboot.", + Timeout: 40 * time.Minute, Distros: []string{"rhcos"}, Platforms: []string{"qemu"}, }) @@ -143,9 +133,6 @@ NextProcess: protocol: proto, port: port, } - if process == "rpcbind" { - continue - } if expectedListenersMap[thisListener] { // matches expected process @@ -174,7 +161,6 @@ func NetworkListeners(c cluster.TestCluster) { // DHCPv6 from NetworkManager (when IPv6 network available) // https://github.com/coreos/fedora-coreos-tracker/issues/1216 {"udp", "546", "NetworkManager"}, - {"udp", "68", "dhclient"}, } checkList := func() error { return checkListeners(c, expectedListeners) @@ -216,310 +202,320 @@ func NetworkInitramfsSecondBoot(c cluster.TestCluster) { } var ( - dhcpClientConfig = `[main] - dhcp=dhclient -` - + // copied from https://github.com/RHsyseng/rhcos-slb/blob/31788956cc663d8375d7b8c09df015e623c7afb3/capture-macs.sh captureMacsScript = `#!/usr/bin/env bash - set -ex - echo "Processing MAC addresses" - cmdline=( $( /boot/mac_addresses + set -ex + echo "Processing MAC addresses" + cmdline=( $( /boot/mac_addresses ` - setupVethPairsTemplate = `#!/usr/bin/env bash - set -ex - - create_veth_pair() { - veth_host_side_end_name=$1 - veth_netns_side_end_name=$2 - host_side_mac_address=$3 - netns_side_ip=$4 - network_namespace=$5 - - # Create veth pair and assign a namespace to veth-netns - ip link add ${veth_host_side_end_name} type veth peer name ${veth_netns_side_end_name} - ip link set ${veth_netns_side_end_name} netns ${network_namespace} - - # Assign an MAC address to the host-side veth end - ip link set dev ${veth_host_side_end_name} address ${host_side_mac_address} - - # Assign an IP address to netns-side veth end and bring it up - ip netns exec ${network_namespace} ip address add ${netns_side_ip} dev ${veth_netns_side_end_name} - ip netns exec ${network_namespace} ip link set ${veth_netns_side_end_name} up - } - - activate_veth_end() { - veth_end_name=$1 - - nmcli dev set ${veth_end_name} managed yes - ip link set ${veth_end_name} up - - poll_dhcp_success ${veth_end_name} - } - - poll_dhcp_success() { - veth_end_name=$1 - for attempt in {1..5}; do - cidr=$(nmcli -g IP4.ADDRESS dev show ${veth_end_name}) - if [[ ! -z "${cidr}" ]]; then - return - fi - sleep 1 - done - - echo "failed to get ip for ${veth_end_name}" - exit 1 - } - - primary_mac=%s - secondary_mac=%s - primary_ip=%s - secondary_ip=%s - - # Get the location of the NetworkManager config files - NMPATH=$(NetworkManager --print-config | sed -nr "/^\[keyfile\]/ { :l /^path[ ]*/ { s/.*=[ ]*//; p; q;}; n; b l;}") - - # Store the location of the NM config files - if [[ ! -d $NMPATH ]]; then - NMPATH=/etc/NetworkManager/system-connections - fi - rm -rf ${NMPATH}/* - - if [[ ! -f /boot/mac_addresses ]] ; then - echo "no mac address configuration file found .. exiting" - exit 0 - fi - - network_namespace=test-netns - # Create a network namespace - ip netns add ${network_namespace} - - # create 2 veth pairs between host side and network_namespace - veth1_host_side_end_name=veth1-host - veth1_netns_side_end_name=veth1-netns - create_veth_pair ${veth1_host_side_end_name} ${veth1_netns_side_end_name} ${primary_mac} 192.168.0.100 ${network_namespace} - veth2_host_side_end_name=veth2-host - veth2_netns_side_end_name=veth2-netns - create_veth_pair ${veth2_host_side_end_name} ${veth2_netns_side_end_name} ${secondary_mac} 192.168.0.101 ${network_namespace} - - # Run a dnsmasq service on the network_namespace, to set the host-side veth ends a ip via their MAC addresses - echo -e "dhcp-range=192.168.0.50,192.168.0.60,255.255.255.0,12h\ndhcp-host=${primary_mac},${primary_ip}\ndhcp-host=${secondary_mac},${secondary_ip}" > /etc/dnsmasq.d/dhcp - # Disable interface=lo as new dnsmasq version has it by default - ip netns exec ${network_namespace} dnsmasq --except-interface=lo --bind-interfaces -u dnsmasq -g dnsmasq --conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig --conf-file=/dev/null & - - # Tell NM to manage the "veth-host" interface and bring it up (will attempt DHCP). - # Do this after we start dnsmasq so we don't have to deal with DHCP timeouts. - activate_veth_end ${veth1_host_side_end_name} - activate_veth_end ${veth2_host_side_end_name} - - # Run setup Ovs script to create the ovs bridge over the bond, using the 2 host-side veth ends. - /usr/local/bin/setup-ovs + // copied from https://github.com/RHsyseng/rhcos-slb/blob/31788956cc663d8375d7b8c09df015e623c7afb3/init-interfaces.sh + initInterfacesScript = `#!/usr/bin/env bash + set -ex + is_configured() { + [[ $(grep primary /etc/NetworkManager/system-connections/* | wc -l) -ge 1 && $(grep secondary /etc/NetworkManager/system-connections/* | wc -l) -ge 1 ]] + } + + is_con_exists() { + local con_name=$1 + if nmcli -t -g NAME con show | grep -w -q "$con_name"; then + return 0 # true + fi + return 1 # false + } + + is_con_active() { + local con_name=$1 + if nmcli -t -g NAME con show --active | grep -w -q "$con_name"; then + return 0 # true + fi + return 1 # false + } + + get_con_name_by_mac_or_device() { + local mac=$(echo $1 | sed -e 's/\\\|://g') + local dev_name=$2 + while read -r con; do + if [[ "$(nmcli -g 802-3-ethernet.mac-address c show "${con}" | tr '[A-Z]' '[a-z]' | sed -e 's/\\\|://g')" == "$mac" || $(nmcli -g connection.interface-name c show "${con}") == "${dev_name}" ]]; then + echo "${con}" + break + fi + done <<< "$(nmcli -g NAME c show)" + } + + generate_new_con_name() { + local device_name=$1 + printf "ethernet-%s-%s" "$device_name" "$RANDOM" + } + + set_description() { + local mac=$1 + local nic=$2 + local description=$3 + local connections=$(grep -REl "type=ethernet" /etc/NetworkManager/system-connections | xargs -I{} -- grep -El -i "mac-address=${mac}|interface-name=${nic}" "{}") + IFS=$'\n' + for connection in ${connections}; do + if ! grep nmstate.interface.description "${connection}"; then + echo "" >> "${connection}" + echo "[user]" >> "${connection}" + echo "nmstate.interface.description=${description}" >> "${connection}" + else + sed -i "s/nmstate\.interface\.description=.*/nmstate.interface.description=$description/" "${connection}" + fi + done + unset IFS + } + + if [[ ! -f /boot/mac_addresses ]] ; then + echo "no mac address configuration file found .. exiting" + exit 0 + fi + + if is_configured; then + echo "interfaces already configured" + exit 0 + fi + + primary_mac="$(awk -F= '/PRIMARY_MAC/ {print $2}' < /boot/mac_addresses | tr '[:upper:]' '[:lower:]')" + secondary_mac="$(awk -F= '/SECONDARY_MAC/ {print $2}' < /boot/mac_addresses | tr '[:upper:]' '[:lower:]')" + + default_device="" + secondary_device="" + default_connection_name="" + secondary_connection_name="" + + for dev in $(nmcli device status | awk '/ethernet/ {print $1}'); do + dev_mac=$(nmcli -g GENERAL.HWADDR dev show "$dev" | sed -e 's/\\//g' | tr '[:upper:]' '[:lower:]') + case $dev_mac in + "${primary_mac}") + default_device="$dev" + default_connection_name=$(get_con_name_by_mac_or_device "$primary_mac" "$dev") + ;; + "${secondary_mac}") + secondary_device="$dev" + secondary_connection_name=$(get_con_name_by_mac_or_device "$secondary_mac" "$dev") + ;; + *) + ;; + esac + done + + echo -e "default dev: $default_device (CONNECTION.NAME $default_connection_name)\nsecondary dev: $secondary_device (CONNECTION.NAME $secondary_connection_name)" + if [[ -z "$default_device" ]] || [[ -z "$secondary_device" ]]; then + echo "error: primary/secondary device name not found" + exit 0 + fi + + if eval ! is_con_exists "\"$default_connection_name\""; then + default_connection_name="$(generate_new_con_name "${default_device}")" && export default_connection_name + nmcli con add type ethernet \ + conn.interface "${default_device}" \ + connection.autoconnect yes \ + ipv4.method auto \ + con-name "${default_connection_name}" \ + 802-3-ethernet.mac-address "${primary_mac}" + fi + if eval ! is_con_active "\"$default_connection_name\""; then + nmcli con up "${default_connection_name}" + fi + + if eval ! is_con_exists "\"$secondary_connection_name\""; then + secondary_connection_name="$(generate_new_con_name "${secondary_device}")" && export secondary_connection_name + nmcli con add type ethernet \ + conn.interface "${secondary_device}" \ + connection.autoconnect yes \ + ipv4.method disabled \ + ipv6.method disabled \ + con-name "${secondary_connection_name}" \ + 802-3-ethernet.mac-address "${secondary_mac}" + fi + if eval ! is_con_active "\"${secondary_connection_name}\""; then + nmcli con mod "${secondary_connection_name}" \ + connection.interface-name "${secondary_device}" \ + connection.autoconnect yes \ + ipv4.method disabled \ + ipv6.method disabled \ + 802-3-ethernet.mac-address "${secondary_mac}" + nmcli con up "${secondary_connection_name}" || /bin/true + fi + + set_description "${primary_mac}" "${default_device}" primary + set_description "${secondary_mac}" "${secondary_device}" secondary + + nmcli c reload + ` + + initInterfacesSystemdContents = ` +[Unit] +Before=kubelet.service +After=NetworkManager.service capture-macs.service +[Service] +Type=oneshot +ExecStart=/bin/sh /var/init-interfaces.sh +[Install] +WantedBy=multi-user.target ` - setupOvsScript = `#!/usr/bin/env bash - set -ex - - rm -rf /etc/NetworkManager/system-connections/* - - # Get the location of the NetworkManager config files - NMPATH=$(NetworkManager --print-config | sed -nr "/^\[keyfile\]/ { :l /^path[ ]*/ { s/.*=[ ]*//; p; q;}; n; b l;}") - - if [[ ! -f /boot/mac_addresses ]] ; then - echo "no mac address configuration file found .. exiting" - exit 1 - fi - - # Store the location of the NM config files - if [[ ! -d $NMPATH ]]; then - NMPATH=/etc/NetworkManager/system-connections - fi - - # Copy the config files from stored location to NM settings folder - if [[ -d /var/ovsbond ]]; then - echo "Loading OVS old profile" - cp -r /var/ovsbond/* $NMPATH - systemctl restart NetworkManager - fi - - if [[ $(nmcli conn | grep -c ovs) -eq 0 ]]; then - echo "configure ovs bonding" - ovs-vsctl --if-exists del-br brcnv - primary_mac=$(cat /boot/mac_addresses | awk -F= '/PRIMARY_MAC/ {print $2}') - secondary_mac=$(cat /boot/mac_addresses | awk -F= '/SECONDARY_MAC/ {print $2}') - - default_device="" - secondary_device="" - profile_name="" - secondary_profile_name="" - - for dev in $(nmcli device status | awk '/ethernet/ {print $1}'); do - dev_mac=$(nmcli -g GENERAL.HWADDR dev show $dev | sed -e 's/\\//g' | tr '[A-Z]' '[a-z]') - case $dev_mac in - $primary_mac) - default_device=$dev - profile_name=$(nmcli -g GENERAL.CONNECTION dev show $dev) - ;; - $secondary_mac) - secondary_device=$dev - secondary_profile_name=$(nmcli -g GENERAL.CONNECTION dev show $dev) - ;; - *) - ;; - esac - done - echo -e "default dev: $default_device ($profile_name)\nsecondary dev: $secondary_device ($secondary_profile_name)" - - mac=$(sudo nmcli -g GENERAL.HWADDR dev show $default_device | sed -e 's/\\//g') - - # make bridge - nmcli conn add type ovs-bridge conn.interface brcnv con-name ovs-bridge-brcnv - nmcli conn add type ovs-port conn.interface brcnv-port master brcnv - nmcli conn add type ovs-interface con-name ovs-brcnv-iface conn.interface brcnv master brcnv-port ipv4.method auto ipv4.dhcp-client-id "mac" connection.autoconnect no 802-3-ethernet.cloned-mac-address $mac - - # make bond - nmcli conn add type ovs-port conn.interface bond0 master brcnv ovs-port.bond-mode balance-slb con-name ovs-slave-bond0 - nmcli conn add type ethernet conn.interface $default_device master bond0 con-name ovs-slave-1 - nmcli conn add type ethernet conn.interface $secondary_device master bond0 con-name ovs-slave-2 - nmcli conn down "$profile_name" || true - nmcli conn mod "$profile_name" connection.autoconnect no || true - nmcli conn down "$secondary_profile_name" || true - nmcli conn mod "$secondary_profile_name" connection.autoconnect no || true - if ! nmcli conn up ovs-brcnv-iface; then - nmcli conn up "$profile_name" || true - nmcli conn mod "$profile_name" connection.autoconnect yes - nmcli conn up "$secondary_profile_name" || true - nmcli conn mod "$secondary_profile_name" connection.autoconnect yes - nmcli conn delete $(nmcli c show |grep ovs-cnv |awk '{print $1}') || true - else - nmcli conn mod ovs-brcnv-iface connection.autoconnect yes - nmcli conn up ovs-slave-2 - # Remove Old NM config files and copy the new-ones - rm -rf /var/ovsbond - cp -r $NMPATH /var/ovsbond || true - fi - else - echo "ovs bridge already present" - for c in ovs-bridge-brcnv ovs-slave-bond0 ovs-slave-brcnv-port ovs-slave-1 ovs-slave-2 ovs-brcnv-iface; do nmcli c up $c; done - fi + captureMacsSystemdContents = ` +[Unit] +RequiresMountsFor=/boot +Description=Capture MAC address from kargs +After=create-datastore.service +Before=nestos-installer.target +[Service] +Type=oneshot +MountFlags=slave +ExecStart=/usr/local/bin/capture-macs +[Install] +RequiredBy=multi-user.target ` ) -func NetworkBondWithRestart(c cluster.TestCluster) { +// NetworkAdditionalNics verifies that additional NICs are created on the node +func NetworkAdditionalNics(c cluster.TestCluster) { primaryMac := "52:55:00:d1:56:00" secondaryMac := "52:55:00:d1:56:01" - primaryIp := "192.168.0.55" - secondaryIp := "192.168.0.56" - setupBondWithDhcpTest(c, primaryMac, secondaryMac, primaryIp, secondaryIp) + setupMultipleNetworkTest(c, primaryMac, secondaryMac) + + m := c.Machines()[0] + expectedMacsList := []string{primaryMac, secondaryMac} + checkExpectedMACs(c, m, expectedMacsList) +} + +// InitInterfacesTest checks init-interfaces script in both fresh setup and Node reboot +// In this test MCO is checked as part of ignition context since MCO is not available on this test infra +func InitInterfacesTest(c cluster.TestCluster) { + primaryMac := "52:55:00:d1:56:00" + secondaryMac := "52:55:00:d1:56:01" + setupWithInterfacesTest(c, primaryMac, secondaryMac) m := c.Machines()[0] - expectedUpConnections := getOvsRelatedConnections(c, m) - err := checkConnectionsUp(c, m, expectedUpConnections) + err := simulateNewInstallation(c, m, []string{primaryMac, secondaryMac}) if err != nil { - c.Fatalf("connections check failed before reboot: %v", err) + c.Fatalf("failed to simulate new setup with no connections: %v", err) + } + err = checkExpectedInterfaces(c, m, primaryMac, secondaryMac) + if err != nil { + c.Fatalf("failed when no connections are configured: %v", err) } err = m.Reboot() if err != nil { - c.Fatalf("failed to reboot the machine: %v", err) + c.Fatalf("failed to reboot Node: %v", err) } - - err = checkConnectionsUp(c, m, expectedUpConnections) + err = checkExpectedInterfaces(c, m, primaryMac, secondaryMac) if err != nil { - c.Fatalf("connections check failed post reboot: %v", err) + c.Fatalf("failed when after setup reboot: %v", err) } } -func getOvsRelatedConnections(c cluster.TestCluster, m platform.Machine) []string { - subString := "ovs" - connectionList := getConnectionsList(c, m) - ovsRelatedConnectionList := []string{} +func addKernelArgs(c cluster.TestCluster, m platform.Machine, args []string) { + if len(args) == 0 { + return + } - for _, connectionName := range connectionList { - if strings.Contains(connectionName, subString) { - ovsRelatedConnectionList = append(ovsRelatedConnectionList, connectionName) - } + rpmOstreeCommand := "sudo rpm-ostree kargs" + for _, arg := range args { + rpmOstreeCommand = fmt.Sprintf("%s --append %s", rpmOstreeCommand, arg) } - return ovsRelatedConnectionList -} -func getConnectionsList(c cluster.TestCluster, m platform.Machine) []string { - output := string(c.MustSSH(m, "nmcli -t -g NAME con show")) - return strings.Split(output, "\n") -} + c.RunCmdSync(m, rpmOstreeCommand) -func getActiveConnectionsList(c cluster.TestCluster, m platform.Machine) []string { - output := string(c.MustSSH(m, "nmcli -t -g NAME con show --active")) - return strings.Split(output, "\n") + err := m.Reboot() + if err != nil { + c.Fatalf("failed to reboot the machine: %v", err) + } } -func NetworkBondWithDhcp(c cluster.TestCluster) { - primaryMac := "52:55:00:d1:56:00" - secondaryMac := "52:55:00:d1:56:01" - primaryIp := "192.168.0.55" - secondaryIp := "192.168.0.56" - ovsBridgeInterface := "ovs-brcnv-iface" - - setupBondWithDhcpTest(c, primaryMac, secondaryMac, primaryIp, secondaryIp) +func setupMultipleNetworkTest(c cluster.TestCluster, primaryMac, secondaryMac string) { + var m platform.Machine + var err error - m := c.Machines()[0] - checkExpectedMAC(c, m, ovsBridgeInterface, primaryMac) - checkExpectedIP(c, m, ovsBridgeInterface, primaryIp) -} + options := platform.QemuMachineOptions{ + MachineOptions: platform.MachineOptions{ + AdditionalNics: 2, + }, + } -func initSetupVethPairsScript(primaryMac, secondaryMac, primaryIp, secondaryIp string) string { - return fmt.Sprintf(setupVethPairsTemplate, primaryMac, secondaryMac, primaryIp, secondaryIp) -} + var userdata = conf.Ignition(fmt.Sprintf(`{ + "ignition": { + "version": "3.2.0" + }, + "storage": { + "files": [ + { + "path": "/usr/local/bin/capture-macs", + "contents": { "source": "data:text/plain;base64,%s" }, + "mode": 755 + } + ] + }, + "systemd": { + "units": [ + { + "contents": "[Unit]\nRequiresMountsFor=/boot\nDescription=Capture MAC address from kargs\nAfter=create-datastore.service\nBefore=nestos-installer.target\n\n\n[Service]\nType=oneshot\nMountFlags=slave\nExecStart=/usr/local/bin/capture-macs\n\n[Install]\nRequiredBy=multi-user.target\n", + "enabled": true, + "name": "capture-macs.service" + } + ] + } + }`, base64.StdEncoding.EncodeToString([]byte(captureMacsScript)))) -func setupBondWithDhcpTest(c cluster.TestCluster, primaryMac, secondaryMac, primaryIp, secondaryIp string) { - var m platform.Machine - var err error - options := platform.QemuMachineOptions{} + switch pc := c.Cluster.(type) { + // These cases have to be separated because when put together to the same case statement + // the golang compiler no longer checks that the individual types in the case have the + // NewMachineWithQemuOptions function, but rather whether platform.Cluster + // does which fails + case *qemu.Cluster: + m, err = pc.NewMachineWithQemuOptions(userdata, options) + default: + panic("unreachable") + } + if err != nil { + c.Fatal(err) + } - setupVethPairs := initSetupVethPairsScript(primaryMac, secondaryMac, primaryIp, secondaryIp) + // Add karg needed for the ignition to configure the network properly. + addKernelArgs(c, m, []string{fmt.Sprintf("macAddressList=%s,%s", primaryMac, secondaryMac)}) +} - var userdata *conf.UserData = conf.Ignition(fmt.Sprintf(`{ +func setupWithInterfacesTest(c cluster.TestCluster, primaryMac, secondaryMac string) { + var userdata = conf.Ignition(fmt.Sprintf(`{ "ignition": { "version": "3.2.0" }, "storage": { "files": [ - { - "path": "/etc/NetworkManager/conf.d/10-dhcp-config.conf", - "contents": { "source": "data:text/plain;base64,%s" }, - "mode": 420 - }, { "path": "/usr/local/bin/capture-macs", "contents": { "source": "data:text/plain;base64,%s" }, "mode": 755 }, { - "path": "/usr/local/bin/create-veth-pairs", - "contents": { "source": "data:text/plain;base64,%s" }, - "mode": 755 - }, - { - "path": "/usr/local/bin/setup-ovs", + "path": "/var/init-interfaces.sh", "contents": { "source": "data:text/plain;base64,%s" }, "mode": 755 } @@ -528,33 +524,37 @@ func setupBondWithDhcpTest(c cluster.TestCluster, primaryMac, secondaryMac, prim "systemd": { "units": [ { - "enabled": true, - "name": "openvswitch.service" - }, - { - "contents": "[Unit]\nDescription=Capture MAC address from kargs\nBefore=nestos-installer.target\nAfter=nestos-installer.service\n\nConditionKernelCommandLine=macAddressList\nRequiresMountsFor=/boot\n\n[Service]\nType=oneshot\nMountFlags=slave\nExecStart=/usr/local/bin/capture-macs\n\n[Install]\nRequiredBy=multi-user.target\n", + "contents": "%s", "enabled": true, "name": "capture-macs.service" }, { - "contents": "[Unit]\nDescription=Create VETH Pairs and Configue OVS interface over bond\nBefore=ovs-configuration.service\nAfter=NetworkManager.service\nAfter=openvswitch.service\nAfter=capture-macs.service\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/create-veth-pairs\n\n[Install]\nRequiredBy=multi-user.target\n", + "contents": "%s", "enabled": true, - "name": "create-veth-pairs.service" + "name": "setup-ovs.service" } ] } }`, - base64.StdEncoding.EncodeToString([]byte(dhcpClientConfig)), base64.StdEncoding.EncodeToString([]byte(captureMacsScript)), - base64.StdEncoding.EncodeToString([]byte(setupVethPairs)), - base64.StdEncoding.EncodeToString([]byte(setupOvsScript)))) + base64.StdEncoding.EncodeToString([]byte(initInterfacesScript)), + strings.Replace(captureMacsSystemdContents, "\n", "\\n", -1), + strings.Replace(initInterfacesSystemdContents, "\n", "\\n", -1))) + + options := platform.QemuMachineOptions{ + MachineOptions: platform.MachineOptions{ + AdditionalNics: 2, + }, + } + var m platform.Machine + var err error switch pc := c.Cluster.(type) { // These cases have to be separated because when put together to the same case statement // the golang compiler no longer checks that the individual types in the case have the // NewMachineWithQemuOptions function, but rather whether platform.Cluster // does which fails - case *unprivqemu.Cluster: + case *qemu.Cluster: m, err = pc.NewMachineWithQemuOptions(userdata, options) default: panic("unreachable") @@ -567,172 +567,189 @@ func setupBondWithDhcpTest(c cluster.TestCluster, primaryMac, secondaryMac, prim addKernelArgs(c, m, []string{fmt.Sprintf("macAddressList=%s,%s", primaryMac, secondaryMac)}) } -// NetworkAdditionalNics verifies that additional NICs are created on the node -func NetworkAdditionalNics(c cluster.TestCluster) { - primaryMac := "52:55:00:d1:56:00" - secondaryMac := "52:55:00:d1:56:01" - ovsBridgeInterface := "ovs-brcnv-iface" +func simulateNewInstallation(c cluster.TestCluster, m platform.Machine, macConnectionsToDelete []string) error { + macConnectionMap, err := getMacConnectionMap(c, m) + if err != nil { + return fmt.Errorf("failed to get macConnectionMap: %v", err) + } + macInterfaceMap, err := getMacInterfaceMap(c, m) + if err != nil { + return fmt.Errorf("failed to get macInterfaceMap: %v", err) + } + flushInterfaceIpByMac(c, m, macInterfaceMap, macConnectionsToDelete) + removeConnectionsByMac(c, m, macConnectionMap, macConnectionsToDelete) - setupMultipleNetworkTest(c, primaryMac, secondaryMac) + err = m.Reboot() + if err != nil { + return fmt.Errorf("failed to reboot the machine: %v", err) + } + return nil +} - m := c.Machines()[0] - checkExpectedMAC(c, m, ovsBridgeInterface, primaryMac) +func flushInterfaceIpByMac(c cluster.TestCluster, m platform.Machine, macInterfaceMap map[string]string, macsList []string) { + for _, mac := range macsList { + InterfaceToFlush := macInterfaceMap[mac] + c.MustSSH(m, fmt.Sprintf("sudo ip addr flush dev '%s'", InterfaceToFlush)) + } } -func checkExpectedMAC(c cluster.TestCluster, m platform.Machine, interfaceName, expectedMac string) { - interfaceMACAddress, err := getInterfaceMAC(c, m, interfaceName) - if err != nil { - c.Fatalf("failed to fetch interface %s MAC Address: %v", interfaceName, err) +func removeConnectionsByMac(c cluster.TestCluster, m platform.Machine, macConnectionMap map[string]string, macsList []string) { + for _, mac := range macsList { + connectionToDelete := macConnectionMap[mac] + c.MustSSH(m, fmt.Sprintf("sudo nmcli con del '%s'", connectionToDelete)) } +} - if interfaceMACAddress != expectedMac { - c.Fatalf("interface %s MAC %s does not match expected MAC %s", interfaceName, interfaceMACAddress, expectedMac) +func checkExpectedInterfaces(c cluster.TestCluster, m platform.Machine, primaryMac, secondaryMac string) error { + macConnectionMap, err := getMacConnectionMap(c, m) + if err != nil { + return fmt.Errorf("failed to get macConnectionMap: %v", err) } + err = checkExpectedInterfacesStatus(c, m, macConnectionMap, []string{primaryMac, secondaryMac}, []string{}) + if err != nil { + return fmt.Errorf("interfaces are not in expected status when connections do not exist: %v", err) + } + err = checkExpectedInterfacesIPAddress(c, m, macConnectionMap, []string{primaryMac}, []string{secondaryMac}) + if err != nil { + return fmt.Errorf("interfaces are not in expected status when connections do not exist: %v", err) + } + return nil } -func checkConnectionsUp(c cluster.TestCluster, m platform.Machine, expectedUpConnections []string) error { +func checkExpectedInterfacesStatus(c cluster.TestCluster, m platform.Machine, macConnectionMap map[string]string, expectedUpInterfacesMacList, expectedDownInterfacesMacList []string) error { failedConnections := []string{} - activeConnections := getActiveConnectionsList(c, m) + for _, ifaceMac := range expectedUpInterfacesMacList { + connectionName := macConnectionMap[ifaceMac] + if !isConnectionUp(c, m, connectionName) { + failedConnections = append(failedConnections, fmt.Sprintf("expected connection %s to be UP", connectionName)) + } + } - for _, connection := range expectedUpConnections { - if !isStringInSlice(activeConnections, connection) { - failedConnections = append(failedConnections, connection) + for _, ifaceMac := range expectedDownInterfacesMacList { + connectionName := macConnectionMap[ifaceMac] + if isConnectionUp(c, m, connectionName) { + failedConnections = append(failedConnections, fmt.Sprintf("expected connection %s to be DOWN", connectionName)) } } + if len(failedConnections) != 0 { - return fmt.Errorf("connections not in expected status up: %v", failedConnections) + return fmt.Errorf(strings.Join(failedConnections, ",")) } return nil } -func isStringInSlice(stringList []string, val string) bool { - for _, str := range stringList { - if str == val { - return true +func isConnectionUp(c cluster.TestCluster, m platform.Machine, connectionName string) bool { + return getConnectionStatus(c, m, connectionName) == "activated" +} + +func getConnectionStatus(c cluster.TestCluster, m platform.Machine, connectionName string) string { + return string(c.MustSSH(m, fmt.Sprintf("nmcli -f GENERAL.STATE con show '%s' | awk '{print $2}'", connectionName))) +} + +func checkExpectedInterfacesIPAddress(c cluster.TestCluster, m platform.Machine, macConnectionMap map[string]string, expectedIpEnabledInterfaces, expectedIpDisabledInterfaces []string) error { + failedConnections := []string{} + for _, ifaceMac := range expectedIpEnabledInterfaces { + connectionName := macConnectionMap[ifaceMac] + if !isConnectionIpv4Enabled(c, m, connectionName) { + failedConnections = append(failedConnections, fmt.Sprintf("expected connection %s to have an IPv4 Address", connectionName)) } } - return false -} -func getInterfaceMAC(c cluster.TestCluster, m platform.Machine, interfaceName string) (string, error) { - output := string(c.MustSSH(m, fmt.Sprintf("nmcli -g 802-3-ethernet.cloned-mac-address connection show %s", interfaceName))) - output = strings.Replace(output, "\\:", ":", -1) + for _, ifaceMac := range expectedIpDisabledInterfaces { + connectionName := macConnectionMap[ifaceMac] + if isConnectionIpv4Enabled(c, m, connectionName) { + failedConnections = append(failedConnections, fmt.Sprintf("expected connection %s to not have an IPv4 Address", connectionName)) + } + } - var macAddress net.HardwareAddr - var err error - if macAddress, err = net.ParseMAC(output); err != nil { - return "", fmt.Errorf("failed to parse MAC address %v for interface Name %s: %v", output, interfaceName, err) + if len(failedConnections) != 0 { + return fmt.Errorf(strings.Join(failedConnections, ",")) } + return nil +} - return macAddress.String(), nil +func isConnectionIpv4Enabled(c cluster.TestCluster, m platform.Machine, connectionName string) bool { + return getConnectionIpv4Addresses(c, m, connectionName) != "" +} + +func getConnectionIpv4Addresses(c cluster.TestCluster, m platform.Machine, connectionName string) string { + return string(c.MustSSH(m, fmt.Sprintf("nmcli -g IP4.ADDRESS con show '%s'", connectionName))) } -func checkExpectedIP(c cluster.TestCluster, m platform.Machine, interfaceName, expectedIP string) { - interfaceIPAddress, err := getInterfaceIP(c, m, interfaceName) +func checkExpectedMACs(c cluster.TestCluster, m platform.Machine, expectedMacsList []string) { + macConnectionMap, err := getMacConnectionMap(c, m) if err != nil { - c.Fatalf("failed to fetch bond IP Address: %v", err) + c.Fatalf(fmt.Sprintf("failed to get macConnectionMap: %v", err)) } - if interfaceIPAddress != expectedIP { - c.Fatalf("interface %s IP %s does not match expected IP %s", interfaceName, interfaceIPAddress, expectedIP) + for _, expectedMac := range expectedMacsList { + if _, exists := macConnectionMap[expectedMac]; !exists { + c.Fatalf(fmt.Sprintf("expected Mac %s does not appear in macConnectionMap %v", expectedMac, macConnectionMap)) + } } } -func getInterfaceIP(c cluster.TestCluster, m platform.Machine, interfaceName string) (string, error) { - output := string(c.MustSSH(m, fmt.Sprintf("nmcli -g ip4.address connection show %s", interfaceName))) - - var ipAddress net.IP - var err error - if ipAddress, _, err = net.ParseCIDR(output); err != nil { - return "", fmt.Errorf("failed to parse IP address %v for interface Name %s: %v", output, interfaceName, err) +func getMacConnectionMap(c cluster.TestCluster, m platform.Machine) (map[string]string, error) { + connectionNamesList := getConnectionsList(c, m) + connectionDeviceMap, err := getConnectionDeviceMap(c, m, connectionNamesList) + if err != nil { + return nil, fmt.Errorf("failed to get connectionDeviceMap: %v", err) } - return ipAddress.String(), nil + macConnectionMap := map[string]string{} + for _, connection := range connectionNamesList { + interfaceMACAddress, err := getDeviceMAC(c, m, connectionDeviceMap[connection]) + if err != nil { + return nil, fmt.Errorf("failed to fetch connection %s MAC Address: %v", connection, err) + } + macConnectionMap[interfaceMACAddress] = connection + } + return macConnectionMap, nil } -func addKernelArgs(c cluster.TestCluster, m platform.Machine, args []string) { - if len(args) == 0 { - return +func getMacInterfaceMap(c cluster.TestCluster, m platform.Machine) (map[string]string, error) { + connectionNamesList := getConnectionsList(c, m) + connectionDeviceMap, err := getConnectionDeviceMap(c, m, connectionNamesList) + if err != nil { + return nil, fmt.Errorf("failed to get connectionDeviceMap: %v", err) } - rpmOstreeCommand := "sudo rpm-ostree kargs" - for _, arg := range args { - rpmOstreeCommand = fmt.Sprintf("%s --append %s", rpmOstreeCommand, arg) + macInterfaceMap := map[string]string{} + for _, connection := range connectionNamesList { + interfaceMACAddress, err := getDeviceMAC(c, m, connectionDeviceMap[connection]) + if err != nil { + return nil, fmt.Errorf("failed to fetch connection %s MAC Address: %v", connection, err) + } + macInterfaceMap[interfaceMACAddress] = connectionDeviceMap[connection] } + return macInterfaceMap, nil +} - c.RunCmdSync(m, rpmOstreeCommand) - - err := m.Reboot() - if err != nil { - c.Fatalf("failed to reboot the machine: %v", err) - } +func getConnectionsList(c cluster.TestCluster, m platform.Machine) []string { + output := string(c.MustSSH(m, "nmcli -t -f NAME con show")) + connectionNames := strings.Split(output, "\n") + return connectionNames } -func setupMultipleNetworkTest(c cluster.TestCluster, primaryMac, secondaryMac string) { - var m platform.Machine - var err error +func getConnectionDeviceMap(c cluster.TestCluster, m platform.Machine, connectionNamesList []string) (map[string]string, error) { + connectionDeviceMap := map[string]string{} - options := platform.QemuMachineOptions{ - MachineOptions: platform.MachineOptions{ - AdditionalNics: 2, - }, + for _, connection := range connectionNamesList { + deviceName := string(c.MustSSH(m, fmt.Sprintf("nmcli -g connection.interface-name con show '%s'", connection))) + connectionDeviceMap[connection] = deviceName } + return connectionDeviceMap, nil +} - var userdata *conf.UserData = conf.Ignition(fmt.Sprintf(`{ - "ignition": { - "version": "3.2.0" - }, - "storage": { - "files": [ - { - "path": "/usr/local/bin/capture-macs", - "contents": { "source": "data:text/plain;base64,%s" }, - "mode": 755 - }, - { - "path": "/usr/local/bin/setup-ovs", - "contents": { "source": "data:text/plain;base64,%s" }, - "mode": 755 - } - ] - }, - "systemd": { - "units": [ - { - "enabled": true, - "name": "openvswitch.service" - }, - { - "contents": "[Unit]\nDescription=Capture MAC address from kargs\nBefore=nestos-installer.target\nAfter=nestos-installer.service\n\nConditionKernelCommandLine=macAddressList\nRequiresMountsFor=/boot\n\n[Service]\nType=oneshot\nMountFlags=slave\nExecStart=/usr/local/bin/capture-macs\n\n[Install]\nRequiredBy=multi-user.target\n", - "enabled": true, - "name": "capture-macs.service" - }, - { - "contents": "[Unit]\nDescription=Setup OVS bonding\nBefore=ovs-configuration.service\nAfter=NetworkManager.service\nAfter=openvswitch.service\nAfter=capture-macs.service\nConditionKernelCommandLine=macAddressList\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/setup-ovs\n\n[Install]\nRequiredBy=multi-user.target\n", - "enabled": true, - "name": "setup-ovs.service" - } - - ] - } - }`, - base64.StdEncoding.EncodeToString([]byte(captureMacsScript)), - base64.StdEncoding.EncodeToString([]byte(setupOvsScript)))) +func getDeviceMAC(c cluster.TestCluster, m platform.Machine, deviceName string) (string, error) { + output := string(c.MustSSH(m, fmt.Sprintf("nmcli -g GENERAL.HWADDR device show '%s'", deviceName))) + output = strings.Replace(output, "\\:", ":", -1) - switch pc := c.Cluster.(type) { - // These cases have to be separated because when put together to the same case statement - // the golang compiler no longer checks that the individual types in the case have the - // NewMachineWithQemuOptions function, but rather whether platform.Cluster - // does which fails - case *qemu.Cluster: - m, err = pc.NewMachineWithQemuOptions(userdata, options) - default: - panic("unreachable") - } - if err != nil { - c.Fatal(err) + var macAddress net.HardwareAddr + var err error + if macAddress, err = net.ParseMAC(output); err != nil { + return "", fmt.Errorf("failed to parse MAC address %v for device Name %s: %v", output, deviceName, err) } - // Add karg needed for the ignition to configure the network properly. - addKernelArgs(c, m, []string{fmt.Sprintf("macAddressList=%s,%s", primaryMac, secondaryMac)}) + return macAddress.String(), nil } diff --git a/mantle/kola/tests/misc/nfs.go b/mantle/kola/tests/misc/nfs.go index 49643de46db39b89329755a6034c4891673a6449..f9b2167316d0e1b14916d18471a11b7d474e2a3c 100644 --- a/mantle/kola/tests/misc/nfs.go +++ b/mantle/kola/tests/misc/nfs.go @@ -57,6 +57,7 @@ func init() { Run: NFSv4, ClusterSize: 0, Name: "linux.nfs.v4", + Description: "Verify that NFSv4 works.", ExcludeDistros: []string{"fcos", "nestos"}, // Disabled on Azure because setting hostname diff --git a/mantle/kola/tests/misc/selinux.go b/mantle/kola/tests/misc/selinux.go index 12e133169e66084aa84c59f3be525d2867b62e81..0c283095bc441339d8d9e51ac259a9493c38df28 100644 --- a/mantle/kola/tests/misc/selinux.go +++ b/mantle/kola/tests/misc/selinux.go @@ -25,26 +25,24 @@ import ( ) func init() { - register.RegisterTest(®ister.Test{ - Run: SelinuxEnforce, - ClusterSize: 1, - Name: "nestos.selinux.enforce", - }) register.RegisterTest(®ister.Test{ Run: SelinuxBoolean, ClusterSize: 1, Name: "nestos.selinux.boolean", + Description: "Verify tweaking selinux boolean works.", }) register.RegisterTest(®ister.Test{ Run: SelinuxBooleanPersist, ClusterSize: 1, Name: "rhcos.selinux.boolean.persist", + Description: "Verify tweaking selinux boolean works and have it persistent across reboots.", }) register.RegisterTest(®ister.Test{ Run: SelinuxManage, ClusterSize: 1, Name: "rhcos.selinux.manage", Distros: []string{"rhcos"}, + Description: "Verify modifying an selinux file context persists through reboots.", }) } @@ -118,26 +116,6 @@ func getSelinuxBooleanState(c cluster.TestCluster, m platform.Machine, seBool st return boolState, nil } -// SelinuxEnforce checks that some basic things work after `setenforce 1` -func SelinuxEnforce(c cluster.TestCluster) { - cmdList := []cmdCheckOutput{ - {"getenforce", true, "Enforcing"}, - {"sudo setenforce 0", false, ""}, - {"getenforce", true, "Permissive"}, - {"sudo setenforce 1", false, ""}, - {"getenforce", true, "Enforcing"}, - {"systemctl --no-pager is-active system.slice", true, "active"}, - {"sudo cp /etc/selinux/config{,.old}", false, ""}, - {"sudo sed -i 's/SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config", false, ""}, - } - - m := c.Machines()[0] - - testSelinuxCmds(c, m, cmdList) - - c.AssertCmdOutputMatches(m, "getenforce", regexp.MustCompile("^Enforcing$")) -} - // SelinuxBoolean checks that you can tweak a boolean in the current session func SelinuxBoolean(c cluster.TestCluster) { seBoolean := "virt_use_nfs" diff --git a/mantle/kola/tests/misc/tls.go b/mantle/kola/tests/misc/tls.go deleted file mode 100644 index f9406bf860c9ae71b106c5764fdc5214ef0b23d7..0000000000000000000000000000000000000000 --- a/mantle/kola/tests/misc/tls.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2018 Red Hat -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package misc - -import ( - "github.com/coreos/coreos-assembler/mantle/kola/cluster" - "github.com/coreos/coreos-assembler/mantle/kola/register" -) - -var ( - urlsToFetch = []string{ - "https://www.baidu.com/", - } -) - -func init() { - register.RegisterTest(®ister.Test{ - Run: TestTLSFetchURLs, - ClusterSize: 1, - Name: "nestos.tls.fetch-urls", - Flags: []register.Flag{register.RequiresInternetAccess}, // Networking outside cluster required - }) -} - -func TestTLSFetchURLs(c cluster.TestCluster) { - m := c.Machines()[0] - - for _, url := range urlsToFetch { - c.RunCmdSyncf(m, "curl -s -S -m 30 --retry 2 %s", url) - } -} diff --git a/mantle/kola/tests/misc/users.go b/mantle/kola/tests/misc/users.go index 45a806e7f4e91e09929f6d2d5a689b84f3af0eb9..cea7acde7776d5dcf62b2c3f3de64472714c716e 100644 --- a/mantle/kola/tests/misc/users.go +++ b/mantle/kola/tests/misc/users.go @@ -25,8 +25,9 @@ func init() { register.RegisterTest(®ister.Test{ Run: CheckUserShells, ClusterSize: 1, - ExcludePlatforms: []string{"gce"}, + ExcludePlatforms: []string{"gcp"}, Name: "nestos.users.shells", + Description: "Verify that there are no invalid users.", Distros: []string{"fcos", "nestos"}, }) } @@ -36,11 +37,10 @@ func CheckUserShells(c cluster.TestCluster) { var badusers []string ValidUsers := map[string]string{ - "sync": "/bin/sync", - "shutdown": "/sbin/shutdown", - "halt": "/sbin/halt", - "nest": "/bin/bash", - "node_exporter": "/bin/nologin", + "sync": "/bin/sync", + "shutdown": "/sbin/shutdown", + "halt": "/sbin/halt", + "nest": "/bin/bash", } output := c.MustSSH(m, "getent passwd") diff --git a/mantle/kola/tests/ostree/basic.go b/mantle/kola/tests/ostree/basic.go index d872482d8941fe9475dd6c478bc44f59d22c6534..22aa088493dd7df52af6106682d5997b5985642f 100644 --- a/mantle/kola/tests/ostree/basic.go +++ b/mantle/kola/tests/ostree/basic.go @@ -15,49 +15,29 @@ package ostree import ( - "fmt" "regexp" "strings" - "time" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/cluster" "github.com/coreos/coreos-assembler/mantle/kola/register" - "github.com/coreos/coreos-assembler/mantle/kola/tests/util" "github.com/coreos/coreos-assembler/mantle/platform" ) -// the "basic" test is only supported on 'rhcos' for now because of how -// the refs are defined. if 'fcos' goes in the same direction, we can -// expand support there. func init() { - register.RegisterTest(®ister.Test{ - Run: ostreeBasicTest, - ClusterSize: 1, - Name: "ostree.basic", - Distros: []string{"rhcos", "nestos"}, - FailFast: true, - Tags: []string{"ostree"}, - }) - register.RegisterTest(®ister.Test{ Run: ostreeRemoteTest, ClusterSize: 1, Name: "ostree.remote", - Flags: []register.Flag{register.RequiresInternetAccess}, // need network to contact remote + Description: "Verify the ostree remote functions work.", FailFast: true, - Tags: []string{"ostree"}, + Tags: []string{"ostree", kola.NeedsInternetTag}, // need network to contact remote }) } -type ostreeAdminStatus struct { - Checksum string - Origin string - Version string -} - // getOstreeRemotes returns the current number of ostree remotes on a machine func getOstreeRemotes(c cluster.TestCluster, m platform.Machine) (int, []string) { - remoteListOut := string(c.MustSSH(m, "sudo ostree remote list")) + remoteListOut := string(c.MustSSH(m, "ostree remote list")) numRemotes := 0 // If we get anything other than an empty string calculate the results // NOTE: This is needed as splitting "" ends up providing a count of 1 @@ -69,121 +49,6 @@ func getOstreeRemotes(c cluster.TestCluster, m platform.Machine) (int, []string) return numRemotes, remoteListRaw } -// getOstreeAdminStatus stuffs the important output of `ostree admin status` -// into an `ostreeAdminStatus` struct -func getOstreeAdminStatus(c cluster.TestCluster, m platform.Machine) (ostreeAdminStatus, error) { - oaStatus := ostreeAdminStatus{} - - oasOutput, err := c.SSH(m, "sudo ostree admin status") - if err != nil { - return oaStatus, fmt.Errorf(`Could not get "ostree admin status": %v`, err) - } - - oasSplit := strings.Split(string(oasOutput), "\n") - if len(oasSplit) < 3 { - return oaStatus, fmt.Errorf(`Unexpected output from "ostree admin status": %v`, string(oasOutput)) - } - - // we use a bunch of regexps to find the content in each line of output - // from "ostree admin status". the `match` for each line sticks the - // captured group as the last element of the array; that is used as the - // value for each field of the struct - reCsum, _ := regexp.Compile(`^\* [\w\-]+ ([0-9a-f]+)\.\d`) - csumMatch := reCsum.FindStringSubmatch(oasSplit[0]) - if csumMatch == nil { - return oaStatus, fmt.Errorf(`Could not parse first line from "ostree admin status": %q`, oasSplit[0]) - } - oaStatus.Checksum = csumMatch[len(csumMatch)-1] - - reVersion, _ := regexp.Compile(`^Version: (.*)`) - versionMatch := reVersion.FindStringSubmatch(strings.TrimSpace(oasSplit[1])) - if versionMatch == nil { - return oaStatus, fmt.Errorf(`Could not parse second line from "ostree admin status": %q`, oasSplit[1]) - } - oaStatus.Version = versionMatch[len(versionMatch)-1] - - reOrigin, _ := regexp.Compile(`^origin refspec: (.*)`) - originMatch := reOrigin.FindStringSubmatch(strings.TrimSpace(oasSplit[2])) - if originMatch == nil { - return oaStatus, fmt.Errorf(`Could not parse third line from "ostree admin status": %q`, oasSplit[2]) - } - oaStatus.Origin = originMatch[len(originMatch)-1] - - return oaStatus, nil -} - -// ostreeBasicTest performs sanity checks on the output from `ostree admin status`, -// `ostree rev-parse`, and `ostree show` by comparing to the output from `rpm-ostree status` -func ostreeBasicTest(c cluster.TestCluster) { - m := c.Machines()[0] - - ros, err := util.GetRpmOstreeStatusJSON(c, m) - if err != nil { - c.Fatal(err) - } - - oas, err := getOstreeAdminStatus(c, m) - if err != nil { - c.Fatal(err) - } - - if len(ros.Deployments) < 1 { - c.Fatalf(`Did not find any deployments?!`) - } - - // verify the output from `ostree admin status` - c.RunLogged("admin status", func(c cluster.TestCluster) { - if oas.Checksum != ros.Deployments[0].Checksum { - c.Fatalf(`Checksums do not match; expected %q, got %q`, ros.Deployments[0].Checksum, oas.Checksum) - } - if oas.Version != ros.Deployments[0].Version { - c.Fatalf(`Versions do not match; expected %q, got %q`, ros.Deployments[0].Version, oas.Version) - } - if oas.Origin != ros.Deployments[0].Origin { - c.Fatalf(`Origins do not match; expected %q, got %q`, ros.Deployments[0].Origin, oas.Origin) - } - }) - - // verify the output from `ostree rev-parse` - // this is kind of moot since the origin for RHCOS is just - // the checksum now - c.RunLogged("rev-parse", func(c cluster.TestCluster) { - // check the output of `ostree rev-parse` - c.AssertCmdOutputContains(m, ("sudo ostree rev-parse " + oas.Origin), oas.Checksum) - }) - - // verify the output of 'ostree show' - c.RunLogged("show", func(c cluster.TestCluster) { - oShowOut := c.MustSSH(m, ("sudo ostree show " + oas.Checksum)) - oShowOutSplit := strings.Split(string(oShowOut), "\n") - // we need at least the first 4 lines (commit, ContentChecksum, Date, Version) - // to proceed safely - if len(oShowOutSplit) < 4 { - c.Fatalf(`Unexpected output from "ostree show": %q`, string(oShowOut)) - } - - // convert the 'timestamp' from `rpm-ostree status` into a date that - // we can compare to the date in `ostree admin status` - // also, wtf is up with formatting date/time in golang?! - timeFormat := "2006-01-02 15:04:05 +0000" - tsUnix := time.Unix(ros.Deployments[0].Timestamp, 0).UTC() - tsFormatted := tsUnix.Format(timeFormat) - oShowDate := strings.TrimPrefix(oShowOutSplit[2], "Date: ") - - if oShowDate != tsFormatted { - c.Fatalf(`Dates do not match; expected %q, got %q`, tsFormatted, oShowDate) - } - - oVersionSplit := strings.Fields(oShowOutSplit[3]) - if len(oVersionSplit) < 2 { - c.Fatalf(`Unexpected content in "Version" field of "ostree show" output: %q`, oShowOutSplit[3]) - } - if oVersionSplit[1] != ros.Deployments[0].Version { - c.Fatalf(`Versions do not match; expected %q, got %q`, ros.Deployments[0].Version, oVersionSplit[1]) - } - }) -} - // ostreeRemoteTest verifies the `ostree remote` functionality; // specifically: `add`, `delete`, `list`, `refs`, `show-url`, `summary` func ostreeRemoteTest(c cluster.TestCluster) { @@ -195,7 +60,7 @@ func ostreeRemoteTest(c cluster.TestCluster) { // TODO: if this remote ever changes, update the `refMatch` regexp // in the `ostree remote summary` test below remoteName := "custom" - remoteUrl := "https://dl.fedoraproject.org/atomic/repo/" + remoteUrl := "https://kojipkgs.fedoraproject.org/ostree/repo/" // verify `ostree remote add` is successful c.Run("add", func(c cluster.TestCluster) { @@ -205,7 +70,7 @@ func ostreeRemoteTest(c cluster.TestCluster) { // verify `ostree remote list` c.Run("list", func(c cluster.TestCluster) { - osRemoteListOut := c.MustSSH(m, "sudo ostree remote list -u") + osRemoteListOut := c.MustSSH(m, "ostree remote list -u") osRemoteListSplit := strings.Split(string(osRemoteListOut), "\n") // should have original remote + newly added remote @@ -230,12 +95,12 @@ func ostreeRemoteTest(c cluster.TestCluster) { // verify `ostree remote show-url` c.Run("show-url", func(c cluster.TestCluster) { - c.AssertCmdOutputContains(m, ("sudo ostree remote show-url " + remoteName), remoteUrl) + c.AssertCmdOutputContains(m, ("ostree remote show-url " + remoteName), remoteUrl) }) // verify `ostree remote refs` c.Run("refs", func(c cluster.TestCluster) { - osRemoteRefsOut := c.MustSSH(m, ("sudo ostree remote refs " + remoteName)) + osRemoteRefsOut := c.MustSSH(m, ("ostree remote refs " + remoteName)) if len(strings.Split(string(osRemoteRefsOut), "\n")) < 1 { c.Fatalf(`Did not receive expected amount of refs from remote: %v`, string(osRemoteRefsOut)) } @@ -243,14 +108,14 @@ func ostreeRemoteTest(c cluster.TestCluster) { // verify `ostree remote summary` c.Run("summary", func(c cluster.TestCluster) { - remoteRefsOut := c.MustSSH(m, ("sudo ostree remote refs " + remoteName)) + remoteRefsOut := c.MustSSH(m, ("ostree remote refs " + remoteName)) remoteRefsOutSplit := strings.Split(string(remoteRefsOut), "\n") remoteRefsCount := len(remoteRefsOutSplit) if remoteRefsCount < 1 { c.Fatalf(`Did not find any refs on ostree remote: %q`, string(remoteRefsOut)) } - osRemoteSummaryOut := c.MustSSH(m, ("sudo ostree remote summary " + remoteName)) + osRemoteSummaryOut := c.MustSSH(m, ("ostree remote summary " + remoteName)) if len(strings.Split(string(osRemoteSummaryOut), "\n")) < 1 { c.Fatalf(`Did not receive expected summary content from remote: %v`, string(osRemoteSummaryOut)) } @@ -286,7 +151,7 @@ func ostreeRemoteTest(c cluster.TestCluster) { // verify `ostree remote delete` c.Run("delete", func(c cluster.TestCluster) { - preRemotesOut := c.MustSSH(m, "sudo ostree remote list") + preRemotesOut := c.MustSSH(m, "ostree remote list") preNumRemotes := len(strings.Split(string(preRemotesOut), "\n")) if preNumRemotes < 1 { diff --git a/mantle/kola/tests/ostree/unlock.go b/mantle/kola/tests/ostree/unlock.go index 7b5ddfda4722fbf9d21e2433d7eb65adf479e2f8..5c1cccf7347fb64f2bdfe7bc3e88419536899977 100644 --- a/mantle/kola/tests/ostree/unlock.go +++ b/mantle/kola/tests/ostree/unlock.go @@ -17,11 +17,11 @@ package ostree import ( "fmt" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/cluster" "github.com/coreos/coreos-assembler/mantle/kola/register" "github.com/coreos/coreos-assembler/mantle/kola/tests/util" "github.com/coreos/coreos-assembler/mantle/platform" - "github.com/coreos/coreos-assembler/mantle/platform/conf" ) func init() { @@ -29,36 +29,18 @@ func init() { Run: ostreeUnlockTest, ClusterSize: 1, Name: "ostree.unlock", - Flags: []register.Flag{register.RequiresInternetAccess}, // need network to pull RPM + Description: "Verify installing an rpm does not persist when using `ostree admin unlock`.", FailFast: true, - Tags: []string{"ostree"}, - // remove this testcase for iso,becase ro mount 'error: Remounting /sysroot read-write: Permission denied' - // ExcludePlatforms: []string{"qemu-iso"}, + Tags: []string{"ostree", kola.NeedsInternetTag}, // need network to pull RPM }) register.RegisterTest(®ister.Test{ Run: ostreeHotfixTest, ClusterSize: 1, - Flags: []register.Flag{register.RequiresInternetAccess}, // need network to pull RPM Name: "ostree.hotfix", + Description: "Verify that the deployment can be put into hotfix mode where RPMs installed with persist across reboots.", FailFast: true, - Tags: []string{"ostree"}, - // remove this testcase for iso,becase ro mount 'error: Remounting /sysroot read-write: Permission denied' - // ExcludePlatforms: []string{"qemu-iso"}, - // enable debugging for https://github.com/coreos/fedora-coreos-tracker/issues/942 - // we can drop it once we resolved it - UserData: conf.Butane(` -variant: fcos -version: 1.4.0 -systemd: - units: - - name: rpm-ostreed.service - dropins: - - name: 10-debug.conf - contents: |- - [Service] - Environment=G_MESSAGES_DEBUG=rpm-ostreed`), + Tags: []string{"ostree", kola.NeedsInternetTag}, // need network to pull RPM }) - } var ( diff --git a/mantle/kola/tests/podman/podman.go b/mantle/kola/tests/podman/podman.go index 4a9fc83fe0ecde5ca6b8ed49ced829cd0810dc86..c209cf2e716faef17cb0dcc51d1b606123d3cba8 100644 --- a/mantle/kola/tests/podman/podman.go +++ b/mantle/kola/tests/podman/podman.go @@ -35,6 +35,7 @@ func init() { Run: podmanBaseTest, ClusterSize: 1, Name: `podman.base`, + Description: "Verify podman info and running with various options work.", RequiredTag: "podman", }) // These remaining tests use networking, and hence don't work reliably on RHCOS @@ -43,7 +44,8 @@ func init() { Run: podmanWorkflow, ClusterSize: 1, Name: `podman.workflow`, - Flags: []register.Flag{register.RequiresInternetAccess}, // For pulling nginx + Description: "Verify container can run with volume mount and port forwarding.", + Tags: []string{kola.NeedsInternetTag}, // For pulling nginx Distros: []string{"fcos", "nestos"}, FailFast: true, RequiredTag: "podman", @@ -52,10 +54,11 @@ func init() { Run: podmanNetworksReliably, ClusterSize: 1, Name: `podman.network-single`, + Description: "Verify basic container network connectivity.", // Not really but podman blows up if there's no /etc/resolv.conf - Tags: []string{kola.NeedsInternetTag}, + Tags: []string{kola.NeedsInternetTag}, Distros: []string{"fcos", "nestos"}, - Timeout: 20 * time.Minute, + Timeout: 20 * time.Minute, RequiredTag: "podman", }) // https://github.com/coreos/mantle/pull/1080 @@ -130,7 +133,6 @@ func podmanWorkflow(c cluster.TestCluster) { // Test: Verify container can run with volume mount and port forwarding image := "atomhub.openatom.cn/library/nginx" - container_name := "nginx" wwwRoot := "/usr/share/nginx/html" var id string @@ -139,7 +141,7 @@ func podmanWorkflow(c cluster.TestCluster) { cmd := fmt.Sprintf("echo TEST PAGE > %s/index.html", string(dir)) c.RunCmdSync(m, cmd) - cmd = fmt.Sprintf("sudo podman run --name %s -d -p 80:80 -v %s/index.html:%s/index.html:z %s", container_name, string(dir), wwwRoot, image) + cmd = fmt.Sprintf("sudo podman run -d -p 80:80 -v %s/index.html:%s/index.html:z %s", string(dir), wwwRoot, image) out := c.MustSSH(m, cmd) id = string(out)[0:64] @@ -165,48 +167,6 @@ func podmanWorkflow(c cluster.TestCluster) { c.AssertCmdOutputContains(m, cmd, "hello") }) - // Test: Cp local files to container - c.Run("cp", func(c cluster.TestCluster) { - _, err := c.SSH(m, "sudo touch example.txt && sudo podman cp example.txt nginx:/home") - if err != nil { - c.Fatal(err) - } - }) - - // Test: Export container to tar - c.Run("export", func(c cluster.TestCluster) { - _, err := c.SSH(m, "sudo podman export -o local_nginx.tar nginx") - if err != nil { - c.Fatal(err) - } - }) - - // Test: Import - c.Run("import", func(c cluster.TestCluster) { - _, err := c.SSH(m, "sudo podman import local_nginx.tar local_nginx && sudo podman images | grep local_nginx") - if err != nil { - c.Fatal(err) - } - }) - - // Test: Save tar - c.Run("save", func(c cluster.TestCluster) { - cmd := fmt.Sprintf("sudo podman save -o local_nginx2.tar %s", image) - _, err := c.SSH(m, cmd) - if err != nil { - c.Fatal(err) - } - }) - - // Test: Load tar - c.Run("load", func(c cluster.TestCluster) { - cmd := fmt.Sprintf("sudo podman load --input local_nginx2.tar && sudo podman images | grep %s", image) - _, err := c.SSH(m, cmd) - if err != nil { - c.Fatal(err) - } - }) - // Test: Stop container c.Run("stop", func(c cluster.TestCluster) { cmd := fmt.Sprintf("sudo podman stop %s", id) diff --git a/mantle/kola/tests/rhcos/sssd.go b/mantle/kola/tests/rhcos/sssd.go index e7fae98edb196b142293a6afb4e653ebf7ca71b4..a972db85b5ae3e58c5769639c1d8d6430ffaea30 100644 --- a/mantle/kola/tests/rhcos/sssd.go +++ b/mantle/kola/tests/rhcos/sssd.go @@ -26,6 +26,7 @@ func init() { Run: verifySSSD, ClusterSize: 1, Name: `rhcos.sssd`, + Description: "Verify nss-altfiles and pam configs are expected.", Flags: []register.Flag{}, Distros: []string{"rhcos", "nestos"}, Platforms: []string{"qemu"}, diff --git a/mantle/kola/tests/rhcos/upgrade.go b/mantle/kola/tests/rhcos/upgrade.go index 9af96b69b7311f770a518f8077b7004e1c7dafc6..8f435c33544bc596fe57138c3f2a15974e6e2697 100644 --- a/mantle/kola/tests/rhcos/upgrade.go +++ b/mantle/kola/tests/rhcos/upgrade.go @@ -16,6 +16,7 @@ package rhcos import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -35,6 +36,7 @@ import ( "github.com/coreos/coreos-assembler/mantle/platform/conf" "github.com/coreos/coreos-assembler/mantle/platform/machine/qemu" installer "github.com/coreos/coreos-assembler/mantle/util" + "github.com/coreos/go-semver/semver" ) func init() { @@ -43,6 +45,7 @@ func init() { ClusterSize: 1, // if renaming this, also rename the command in kolet-httpd.service below Name: "rhcos.upgrade.luks", + Description: "Verify that rhcos supports upgrading with LUKS.", FailFast: true, Tags: []string{"upgrade"}, Distros: []string{"rhcos"}, @@ -70,6 +73,7 @@ func init() { ClusterSize: 1, // if renaming this, also rename the command in kolet-httpd.service below Name: "rhcos.upgrade.basic", + Description: "Verify that rhcos supports upgrading.", FailFast: true, Tags: []string{"upgrade"}, Distros: []string{"rhcos"}, @@ -85,8 +89,9 @@ func init() { Run: rhcosUpgradeFromOcpRhcos, ClusterSize: 0, Name: "rhcos.upgrade.from-ocp-rhcos", + Description: "Verify upgrading from the latest RHCOS released for OCP works.", FailFast: true, - Flags: []register.Flag{register.RequiresInternetAccess}, + Tags: []string{"upgrade", kola.NeedsInternetTag}, Distros: []string{"rhcos"}, Platforms: []string{"qemu"}, ExcludeArchitectures: []string{"s390x", "ppc64le", "aarch64"}, @@ -282,7 +287,12 @@ func getJson(url string, target interface{}) error { func downloadLatestReleasedRHCOS(target string) (string, error) { buildID := kola.CosaBuild.Meta.BuildID ocpVersion := strings.Split(buildID, ".")[0] + rhelVersion := strings.Split(buildID, ".")[1] ocpVersionF := fmt.Sprintf("%s.%s", ocpVersion[:1], ocpVersion[1:]) + // The stream name isn't anywhere in the build so we can only infer + // the RHEL version from the RHCOS version string. This will break + // on three digit versions like 10.1 or 9.10. + rhelVersionF := fmt.Sprintf("%s.%s", rhelVersion[:1], rhelVersion[1:]) channel := "fast-" + ocpVersionF type Release struct { @@ -358,8 +368,26 @@ func downloadLatestReleasedRHCOS(target string) (string, error) { return }(releaseIndex, unique) + // In cases where there is a blocked upgrade to a new Y-stream there can be + // two nodes that don't have an edge to upgrade to. This is generally the + // latest 4.Y-1.Z and the latest 4.Y.Z. Choose the latest 4.Y.Z + if len(difference) < 1 { + return "", errors.New("Could not find the latest release") + } + latest := difference[0] + if len(difference) > 1 { + latestVersion := semver.New(graph.Nodes[latest].Version) + for _, v := range difference { + currentVersion := semver.New(graph.Nodes[v].Version) + if latestVersion.LessThan(*currentVersion) { + latest = v + latestVersion = currentVersion + } + } + } + var ocpRelease *OcpRelease - latestOcpPayload := graph.Nodes[difference[0]].Payload + latestOcpPayload := graph.Nodes[latest].Payload // oc should be included in cosa since https://github.com/coreos/coreos-assembler/pull/2777 cmd := exec.Command("/usr/bin/oc", "adm", "release", "info", latestOcpPayload, "-o", "json") output, err := cmd.Output() @@ -372,13 +400,24 @@ func downloadLatestReleasedRHCOS(target string) (string, error) { var latestOcpRhcosBuild *cosa.Build rhcosVersion := ocpRelease.DisplayVersions.MachineOS.Version - latestBaseUrl := fmt.Sprintf("https://rhcos-redirector.apps.art.xq1c.p1.openshiftapps.com/art/storage/releases/rhcos-%s/%s/%s", + latestBaseUrl := fmt.Sprintf("https://rhcos.mirror.openshift.com/art/storage/prod/streams/%s-%s/builds/%s/%s", ocpVersionF, + rhelVersionF, rhcosVersion, coreosarch.CurrentRpmArch()) latestRhcosBuildMetaUrl := fmt.Sprintf("%s/meta.json", latestBaseUrl) if err := getJson(latestRhcosBuildMetaUrl, &latestOcpRhcosBuild); err != nil { - return "", err + // Try the stream; ideally we'd only do this if the error + // was 403 denied (which is really a 404), but meh this is temporary + // anyway. + latestBaseUrl = fmt.Sprintf("https://rhcos.mirror.openshift.com/art/storage/prod/streams/%s/builds/%s/%s", + ocpVersionF, + rhcosVersion, + coreosarch.CurrentRpmArch()) + latestRhcosBuildMetaUrl = fmt.Sprintf("%s/meta.json", latestBaseUrl) + if err := getJson(latestRhcosBuildMetaUrl, &latestOcpRhcosBuild); err != nil { + return "", err + } } latestRhcosQcow2 := latestOcpRhcosBuild.BuildArtifacts.Qemu.Path diff --git a/mantle/kola/tests/rpmostree/deployments.go b/mantle/kola/tests/rpmostree/deployments.go index 9a26628a3581594ad7719cc3b2613567b5cc591b..22c684eba7981feecc560968c6464121409db0df 100644 --- a/mantle/kola/tests/rpmostree/deployments.go +++ b/mantle/kola/tests/rpmostree/deployments.go @@ -19,6 +19,7 @@ import ( "reflect" "regexp" + "github.com/coreos/coreos-assembler/mantle/kola" "github.com/coreos/coreos-assembler/mantle/kola/cluster" "github.com/coreos/coreos-assembler/mantle/kola/register" "github.com/coreos/coreos-assembler/mantle/kola/tests/util" @@ -30,6 +31,7 @@ func init() { Run: rpmOstreeUpgradeRollback, ClusterSize: 1, Name: "rpmostree.upgrade-rollback", + Description: "Verify an upgrade and rollback with a simulated update works.", FailFast: true, Tags: []string{"rpm-ostree", "upgrade"}, // remove this testcase for iso,becase ro mount 'error: Remounting /sysroot read-write: Permission denied' @@ -39,7 +41,8 @@ func init() { Run: rpmOstreeInstallUninstall, ClusterSize: 1, Name: "rpmostree.install-uninstall", - Tags: []string{"rpm-ostree"}, + Description: "Verify rpm-ostree supports installing and uninstalling rpms.", + Tags: []string{"rpm-ostree", kola.NeedsInternetTag}, // these need network to retrieve bits // this Ignition config lands the dummy RPM UserData: conf.Ignition(`{ "ignition": { @@ -64,7 +67,6 @@ func init() { } } `), - Flags: []register.Flag{register.RequiresInternetAccess}, // these need network to retrieve bits }) } @@ -190,7 +192,7 @@ func rpmOstreeUpgradeRollback(c cluster.TestCluster) { // This uses a dummy RPM that was originally created for the atomic-host-tests; // see: https://github.com/projectatomic/atomic-host-tests func rpmOstreeInstallUninstall(c cluster.TestCluster) { - var ahtRpmPath = "/var/home/nest/aht-dummy-1.0-1.noarch.rpm" + var ahtRpmPath = "/var/home/nest/aht-dummy.rpm" var installPkgName = "aht-dummy-1.0-1.noarch" var installBinName = "aht-dummy" var installBinPath string @@ -203,11 +205,6 @@ func rpmOstreeInstallUninstall(c cluster.TestCluster) { m := c.Machines()[0] - _, err := c.SSH(m, `bash -c 'cd ${HOME} && curl -L -O https://www.nestos.org.cn/kola/aht-dummy-1.0-1.noarch.rpm'`) - if err != nil { - c.Fatal(err) - } - originalStatus, err := util.GetRpmOstreeStatusJSON(c, m) if err != nil { c.Fatal(err) diff --git a/mantle/kola/tests/rpmostree/rebase.go b/mantle/kola/tests/rpmostree/rebase.go deleted file mode 100644 index 46caf93d94f751388a51e5009b0efc1a2b485d2d..0000000000000000000000000000000000000000 --- a/mantle/kola/tests/rpmostree/rebase.go +++ /dev/null @@ -1,71 +0,0 @@ -package rpmostree - -import ( - "github.com/coreos/mantle/kola/cluster" - "github.com/coreos/mantle/kola/register" - "github.com/coreos/mantle/kola/tests/util" -) - -func init() { - register.RegisterTest(®ister.Test{ - Run: rpmOstreeRebase, - ClusterSize: 1, - Name: "rpmostree.rebase", - FailFast: true, - Tags: []string{"rpm-ostree", "upgrade"}, - Flags: []register.Flag{register.RequiresInternetAccess}, - // remove this testcase for iso,becase ro mount 'error: Remounting /sysroot read-write: Permission denied' - // ExcludePlatforms: []string{"qemu-iso"}, - }) -} - -func rpmOstreeRebase(c cluster.TestCluster) { - m := c.Machines()[0] - arch := c.MustSSH(m, "uname -m") - var newBranch string = "ostree-unverified-registry:hub.oepkgs.net/nestos/nestos:22.03-LTS-SP3.20240110.0-" + string(arch) - - originalStatus, err := util.GetRpmOstreeStatusJSON(c, m) - if err != nil { - c.Fatal(err) - } - - if len(originalStatus.Deployments) < 1 { - c.Fatalf(`Unexpected results from "rpm-ostree status"; received: %v`, originalStatus) - } - - c.Run("ostree upgrade", func(c cluster.TestCluster) { - // use "rpm-ostree rebase" to get to the "new" commit - _ = c.MustSSH(m, "sudo systemctl start docker.service && sudo rpm-ostree rebase --experimental "+newBranch+" --bypass-driver") - // get latest rpm-ostree status output to check validity - postUpgradeStatus, err := util.GetRpmOstreeStatusJSON(c, m) - if err != nil { - c.Fatal(err) - } - - // should have an additional deployment - if len(postUpgradeStatus.Deployments) != len(originalStatus.Deployments)+1 { - c.Fatalf("Expected %d deployments; found %d deployments", len(originalStatus.Deployments)+1, len(postUpgradeStatus.Deployments)) - } - // reboot into new deployment - rebootErr := m.Reboot() - if rebootErr != nil { - c.Fatalf("Failed to reboot machine: %v", rebootErr) - } - - // get latest rpm-ostree status output - postRebootStatus, err := util.GetRpmOstreeStatusJSON(c, m) - if err != nil { - c.Fatal(err) - } - - // should have 2 deployments, the previously booted deployment and the test deployment due to rpm-ostree pruning - if len(postRebootStatus.Deployments) != 2 { - c.Fatalf("Expected %d deployments; found %d deployment", 2, len(postRebootStatus.Deployments)) - } - - // new deployment should be booted - if !postRebootStatus.Deployments[0].Booted { - c.Fatalf("New deployment is not reporting as booted") - } - }) -} diff --git a/mantle/kola/tests/rpmostree/status.go b/mantle/kola/tests/rpmostree/status.go index d9bde0b98dd94f657bec9ff5fe14f9879e3c72e9..b24dee148fcd631213ebb8bb47dc9a3beb5e4ea1 100644 --- a/mantle/kola/tests/rpmostree/status.go +++ b/mantle/kola/tests/rpmostree/status.go @@ -30,6 +30,7 @@ func init() { Run: rpmOstreeStatus, ClusterSize: 1, Name: "rpmostree.status", + Description: "Verify rpm-ostree status works.", Tags: []string{"rpm-ostree"}, }) } diff --git a/mantle/kola/tests/util/containers.go b/mantle/kola/tests/util/containers.go index 829a0974bd9a388d0662fa86fac26fa6e6d93005..f570d58d446819d6bb13d55d2da3d6943e2e7243 100644 --- a/mantle/kola/tests/util/containers.go +++ b/mantle/kola/tests/util/containers.go @@ -32,6 +32,7 @@ func GenPodmanScratchContainer(c cluster.TestCluster, m platform.Machine, name s // seemed to have symlinks to the versioned shared libraries. Deleting /etc/ld.so.cache // restored symlinks to the non-versioned shared libraries. cmd := `tmpdir=$(mktemp -d); cd $tmpdir; echo -e "FROM scratch\nCOPY . /" > Dockerfile; + sudo rm -f /etc/ld.so.cache; b=$(which %s); libs=$(sudo ldd $b | grep -o /lib'[^ ]*' | sort -u); sudo rsync -av --relative --copy-links $b $libs ./; sudo podman build --network host --layers=false -t localhost/%s .` @@ -42,8 +43,8 @@ func GenPodmanScratchContainer(c cluster.TestCluster, m platform.Machine, name s func GenIsulaScratchContainer(c cluster.TestCluster, m platform.Machine, name string, binnames []string) { cmd := `tmpdir=$(mktemp -d); cd $tmpdir; echo -e "FROM scratch\nCOPY . /" > Dockerfile; sudo rm -f /etc/ld.so.cache; - b=$(which %s); libs=$(sudo ldd $b | grep -o /lib'[^ ]*' | sort -u); + b=$(which %s); libs=$(sudo ldd $b | grep -o /lib'[^ ]*' | sort -u); sudo rsync -av --relative --copy-links $b $libs ./; sudo isula-build ctr-img build -f Dockerfile -o isulad:echo1:latest .` - c.RunCmdSyncf(m, cmd, strings.Join(binnames, " ")) + c.RunCmdSyncf(m, cmd, strings.Join(binnames, " "), name) } diff --git a/mantle/kola/tests/util/luks.go b/mantle/kola/tests/util/luks.go index 1c51eac9e8173d37c227286ebaeb67b588602382..5fbd122ce78466e0f0c1aaef530912162c0abf2f 100644 --- a/mantle/kola/tests/util/luks.go +++ b/mantle/kola/tests/util/luks.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS,