diff --git a/cmd/manager/main.go b/cmd/manager/main.go index e56c4f8f..06094c8f 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -45,7 +45,6 @@ import ( "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/hostnamevalidation" "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/hotattach" "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/imageboot" - "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/imagebuilder" "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/licensevalidation" "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/livemigrate" "github.com/GoogleCloudPlatform/cloud-image-tests/test_suites/loadbalancer" @@ -353,10 +352,6 @@ func main() { imageboot.Name, imageboot.TestSetup, }, - { - imagebuilder.Name, - imagebuilder.TestSetup, - }, { licensevalidation.Name, licensevalidation.TestSetup, diff --git a/test_suites/imagebuilder/guest_agent_test.go b/test_suites/imagebuilder/guest_agent_test.go deleted file mode 100644 index 234eaa5b..00000000 --- a/test_suites/imagebuilder/guest_agent_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package imagebuilder - -import ( - "os/exec" - "strings" - "testing" - - "github.com/GoogleCloudPlatform/cloud-image-tests/utils" -) - -// TestGoogleGuestAgentHealthy checks if the Google Guest Agent service is active and fully operational (SubState=running). -func TestGoogleGuestAgentHealthy(t *testing.T) { - ctx := utils.Context(t) - - // 1. Check if the service is active. - cmdActive := exec.CommandContext(ctx, "systemctl", "is-active", "google-guest-agent.service") - stdoutActive, err := cmdActive.Output() - if err != nil { - t.Errorf("Running `systemctl is-active google-guest-agent.service` expected `active`, but got: %q, Error: %v", - strings.TrimSpace(string(stdoutActive)), err) - } - - // 2. Query systemd for the exact substate of the service manager. - cmdShow := exec.CommandContext(ctx, "systemctl", "show", "google-guest-agent.service", "--property=SubState") - stdoutShow, err := cmdShow.Output() - if err != nil { - t.Fatalf("Failed while running `systemctl show google-guest-agent.service --property=SubState` to query systemd for SubState: %v. Stderr: %q", err, utils.ParseStderr(err)) - } - - // Output format is usually "SubState=running" or "SubState=dead" - substate := strings.TrimSpace(string(stdoutShow)) - if !strings.Contains(substate, "SubState=running") { - t.Errorf("Health Check Failed: Agent is not fully operational after running 'systemctl show google-guest-agent.service --property=SubState'. Found %q (expected SubState=running)", substate) - } else { - t.Log("Health Check Passed: google-guest-agent is actively running.") - } -} diff --git a/test_suites/imagebuilder/idpf_test.go b/test_suites/imagebuilder/idpf_test.go deleted file mode 100644 index 8424be28..00000000 --- a/test_suites/imagebuilder/idpf_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Package imagebuilder is a CIT suite for testing customer images built by the GCE Image Builder. -package imagebuilder - -import ( - "fmt" - "net" - "os" - "path/filepath" - "testing" -) - -const idpfDriverName = "idpf" - -// TestIDPFNICDriver ensures that for bare metal instances where the image supports IDPF, the IDPF -// driver is correctly loaded and used for physical network interfaces, and their naming follows the -// acceptable naming scheme. -func TestIDPFNICDriver(t *testing.T) { - interfaces, err := net.Interfaces() - if err != nil { - t.Fatalf("Failed to retrieve network interfaces via net.Interfaces() (equivalent command: 'ip -j a'): %v", err) - } - - var physicalNICsFound int - - for _, iface := range interfaces { - // Skip the loopback interface - if iface.Name == "lo" || (iface.Flags&net.FlagLoopback) != 0 { - continue - } - - driverPath := fmt.Sprintf("/sys/class/net/%s/device/driver", iface.Name) - target, err := os.Readlink(driverPath) - if err != nil { - if os.IsNotExist(err) { - // Virtual / bridge interface, skip checking driver - continue - } - t.Errorf("Failed to read symlink for interface %q, driver path %q: %v", iface.Name, driverPath, err) - continue - } - - physicalNICsFound++ - - driverName := filepath.Base(target) - if driverName != idpfDriverName { - t.Errorf("Interface %q is using driver %q, expected %q (Intel IDPF driver)", iface.Name, driverName, idpfDriverName) - } else { - t.Logf("Successfully verified interface %q is using driver %q", iface.Name, driverName) - } - - } - - if physicalNICsFound == 0 { - t.Error("No physical cloud network interfaces were discovered on this bare metal system.") - } -} diff --git a/test_suites/imagebuilder/nic_naming_test.go b/test_suites/imagebuilder/nic_naming_test.go deleted file mode 100644 index 9ef34aae..00000000 --- a/test_suites/imagebuilder/nic_naming_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Package imagebuilder is a CIT suite for testing customer images built by the GCE Image Builder. -package imagebuilder - -import ( - "net" - "strings" - "testing" -) - -func TestNetworkInterfaceNaming(t *testing.T) { - interfaces, err := net.Interfaces() - if err != nil { - t.Fatalf("Failed to retrieve network interfaces via net.Interfaces() (equivalent command: 'ip -j a'): %v", err) - } - - // Ensure either traditional name (eth*) or predictable name (en*) is present - var foundValidName bool - for _, iface := range interfaces { - // Skip loopback interfaces. - if iface.Name == "lo" || (iface.Flags&net.FlagLoopback) != 0 { - continue - } - - if strings.HasPrefix(iface.Name, "eth") || strings.HasPrefix(iface.Name, "en") { - foundValidName = true - t.Logf("Found network interface with valid naming convention: %q", iface.Name) - } - } - - if !foundValidName { - t.Error("Failure: No non-loopback interface was found following either traditional naming (eth*) or predictable naming (en*) conventions (equivalent command: 'ip -j a').") - } -} diff --git a/test_suites/imagebuilder/nic_up_test.go b/test_suites/imagebuilder/nic_up_test.go deleted file mode 100644 index fa9111fe..00000000 --- a/test_suites/imagebuilder/nic_up_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package imagebuilder - -import ( - "net" - "testing" -) - -func TestNetworkInterfacesUp(t *testing.T) { - interfaces, err := net.Interfaces() - if err != nil { - t.Fatalf("Failed to retrieve network interfaces via net.Interfaces() (equivalent command: 'ip -j a'): %v", err) - } - - // Validate that we have at least one valid, UP network interface - var upCount int - var foundNonLoopback bool - - for _, iface := range interfaces { - // Skip the loopback interface via FlagLoopback or name "lo" - if iface.Name == "lo" || (iface.Flags&net.FlagLoopback) != 0 { - continue - } - - foundNonLoopback = true - - // Check if the interface has the FlagUp set - if (iface.Flags & net.FlagUp) != 0 { - upCount++ - t.Logf("Found active network interface: %s (Flags: %v)", iface.Name, iface.Flags) - } - } - - if !foundNonLoopback { - t.Error("Failure: No non-loopback network interfaces were discovered on this system (equivalent command: 'ip -j a').") - } - - if upCount == 0 { - t.Error("Failure: Found network interfaces, but zero non-loopback interfaces are 'UP' (equivalent command: 'ip -j a').") - } -} diff --git a/test_suites/imagebuilder/secure_boot_test.go b/test_suites/imagebuilder/secure_boot_test.go deleted file mode 100644 index e481a53c..00000000 --- a/test_suites/imagebuilder/secure_boot_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package imagebuilder - -import ( - "fmt" - "os" - "os/exec" - "testing" - - "github.com/GoogleCloudPlatform/cloud-image-tests/utils" -) - -const ( - secureBootFile = "/sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c" - setupModeFile = "/sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c" - metadataCurlCmd = `curl -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/image` -) - -func TestGuestSecureBoot(t *testing.T) { - if err := testLinuxGuestSecureBoot(t); err != nil { - t.Fatalf("[FAILED] error running SecureBoot test: %v", err) - } - t.Logf("Secure Boot is enabled and configured correctly.") -} - -func mountEFIVarsCOS(t *testing.T) error { - t.Helper() - ctx := utils.Context(t) - content, err := os.ReadFile("/etc/os-release") - if err != nil { - t.Logf("Could not read os-release: %v", err) - return nil - } - if !utils.IsCOS(string(content)) { - return nil - } - if _, err := os.Stat(secureBootFile); !os.IsNotExist(err) { - return nil - } - cmd := exec.CommandContext(ctx, "mount", "-t", "efivarfs", "efivarfs", "/sys/firmware/efi/efivars/") - _, err = cmd.Output() - if err != nil { - return fmt.Errorf("failed to mount EFI vars with command %q: %v", cmd.String(), err) - } - return nil -} - -func testLinuxGuestSecureBoot(t *testing.T) error { - if err := mountEFIVarsCOS(t); err != nil { - return err - } - if _, err := os.Stat(secureBootFile); os.IsNotExist(err) { - return fmt.Errorf("failed to stat file %q: secureboot efi var is missing", secureBootFile) - } - data, err := os.ReadFile(secureBootFile) - if err != nil { - return fmt.Errorf("failed reading secure boot file %q: %v", secureBootFile, err) - } - // https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-firmware-efi-vars - secureBootMode := data[len(data)-1] - // https://uefi.org/specs/UEFI/2.9_A/32_Secure_Boot_and_Driver_Signing.html#firmware-os-key-exchange-creating-trust-relationships - // If setup mode is not 0 secure boot isn't actually enabled because no PK is enrolled. - if _, err = os.Stat(setupModeFile); os.IsNotExist(err) { - return fmt.Errorf("failed to stat file %q: setupmode efi var is missing", setupModeFile) - } - data, err = os.ReadFile(setupModeFile) - if err != nil { - return fmt.Errorf("failed reading setup mode file %q: %v", setupModeFile, err) - } - setupMode := data[len(data)-1] - if secureBootMode != 1 || setupMode != 0 { - return fmt.Errorf("secure boot is not enabled, found secureboot mode: %c (want 1) and setup mode: %c (want 0)", secureBootMode, setupMode) - } - return nil -} diff --git a/test_suites/imagebuilder/setup.go b/test_suites/imagebuilder/setup.go deleted file mode 100644 index 85380ad2..00000000 --- a/test_suites/imagebuilder/setup.go +++ /dev/null @@ -1,87 +0,0 @@ -// Package imagebuilder is a CIT suite for testing customer images built by the Image Builder. -package imagebuilder - -import ( - "fmt" - "strings" - - "github.com/GoogleCloudPlatform/cloud-image-tests" - "github.com/GoogleCloudPlatform/cloud-image-tests/utils" - "github.com/GoogleCloudPlatform/compute-daisy" - "google.golang.org/api/compute/v1" -) - -var ( - // Name is the name of the test package. It must match the directory name. - Name = "imagebuilder" -) - -// supportedSecureBootBaremetalMachineTypes is a list of baremetal machine types that support -// secure boot. -// https://docs.cloud.google.com/compute/shielded-vm/docs/shielded-vm#limitations -var ( - supportedSecureBootBaremetalMachineTypes = []string{"a4x", "c4a"} -) - -// TestSetup sets up the test workflow. -func TestSetup(t *imagetest.TestWorkflow) error { - vm1, err := t.CreateTestVM("networkingandguestagent") - if err != nil { - return err - } - vm1.RunTests("TestNetworkInterfacesUp|TestNetworkInterfaceNaming|TestGoogleGuestAgentHealthy") - - if utils.HasFeature(t.Image, "UEFI_COMPATIBLE") { - // Only some baremetal machine types support secure boot. - // https://docs.cloud.google.com/compute/shielded-vm/docs/shielded-vm#limitations - runSecureBoot := !isBaremetal(t.MachineType.Name) - if !runSecureBoot { - for _, supportedType := range supportedSecureBootBaremetalMachineTypes { - if strings.Contains(t.MachineType.Name, supportedType) { - runSecureBoot = true - break - } - } - } - - if runSecureBoot { - vm2, err := t.CreateTestVM("secureboot") - if err != nil { - return err - } - vm2.EnableSecureBoot() - vm2.RunTests("TestGuestSecureBoot") - } - } - - if utils.HasFeature(t.Image, "SUSPEND_RESUME_COMPATIBLE") { - suspend := &daisy.Instance{} - suspend.Scopes = append(suspend.Scopes, "https://www.googleapis.com/auth/cloud-platform") - suspendvm, err := t.CreateTestVMMultipleDisks([]*compute.Disk{{Name: "suspend"}}, suspend) - if err != nil { - return err - } - suspendvm.RunTests("TestSuspend") - suspendvm.Resume() - } - - if utils.HasFeature(t.Image, "IDPF") && isBaremetal(t.MachineType.Name) { - zone := t.Zone.Name - fmt.Printf("Using zone %s for %s instance\n", zone, t.MachineType.Name) - baremetal := &daisy.Instance{} - baremetal.MachineType = t.MachineType.Name - baremetal.Zone = zone - baremetal.Scheduling = &compute.Scheduling{OnHostMaintenance: "TERMINATE"} - baremetalDiskType := imagetest.DiskTypeNeeded(baremetal.MachineType) - baremetalVM, err := t.CreateTestVMMultipleDisks([]*compute.Disk{{Name: "baremetal", Type: baremetalDiskType, Zone: zone}}, baremetal) - if err != nil { - return err - } - baremetalVM.RunTests("TestIDPFNICDriver") - } - return nil -} - -func isBaremetal(machineType string) bool { - return strings.Contains(machineType, "-metal") -} diff --git a/test_suites/imagebuilder/suspend_resume_test.go b/test_suites/imagebuilder/suspend_resume_test.go deleted file mode 100644 index 32620b4f..00000000 --- a/test_suites/imagebuilder/suspend_resume_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package imagebuilder - -import ( - "net/http" - "os" - "strings" - "testing" - - "github.com/GoogleCloudPlatform/cloud-image-tests/utils" -) - -const marker = "/var/suspend-test-start" - -func TestSuspend(t *testing.T) { - - if _, err := os.Stat(marker); err != nil && !os.IsNotExist(err) { - t.Fatalf("could not determine if suspend testing has already started: %v", err) - } else if err == nil { - t.Fatal("unexpected reboot during suspend test") - } - err := os.WriteFile(marker, nil, 0777) - if err != nil { - t.Fatalf("could not mark beginning of suspend testing: %v", err) - } - ctx := utils.Context(t) - prj, zone, err := utils.GetProjectZone(ctx) - if err != nil { - t.Fatalf("could not find project and zone: %v", err) - } - inst, err := utils.GetInstanceName(ctx) - if err != nil { - t.Fatalf("could not get instance: %v", err) - } - - client, err := utils.GetDaisyClient(ctx) - if err != nil { - t.Fatalf("could not make compute api client: %v", err) - } - - err = client.Suspend(prj, zone, inst) - if err != nil { - // We can't really check the operation error here, we want to attempt to wait until its suspended but the wait operation will likely error out due to being interrupted by the suspension - if !strings.Contains(err.Error(), "operation failed") && !strings.Contains(err.Error(), "failed to get zone operation") { - t.Fatalf("could not suspend self: %v", err) - } - } - - if _, err := os.Stat(marker); err != nil { - t.Fatalf("could not confirm suspend testing has started ok: %v", err) - } - _, err = http.Get("https://cloud.google.com") - if err != nil { - t.Errorf("no network connectivity after resume: %v", err) - } - t.Log("Instance has network connectivity after resuming") -}