Blame cmd/osbuild-image-tests/openstacktest/openstack.go

Packit 63bb0d
// +build integration
Packit 63bb0d
Packit 63bb0d
package openstacktest
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"os"
Packit 63bb0d
Packit 63bb0d
	"github.com/gophercloud/gophercloud"
Packit 63bb0d
	"github.com/gophercloud/gophercloud/openstack"
Packit 63bb0d
	"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
Packit 63bb0d
	"github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata"
Packit 63bb0d
	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
const WaitTimeout = 600 // in seconds
Packit 63bb0d
Packit 63bb0d
func UploadImageToOpenStack(p *gophercloud.ProviderClient, imagePath string, imageName string) (*images.Image, error) {
Packit 63bb0d
	client, err := openstack.NewImageServiceV2(p, gophercloud.EndpointOpts{
Packit 63bb0d
		Region: os.Getenv("OS_REGION_NAME"),
Packit 63bb0d
	})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, fmt.Errorf("Error creating ImageService client: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// create a new image which gives us the ID
Packit 63bb0d
	image, err := images.Create(client, images.CreateOpts{
Packit 63bb0d
		Name: imageName,
Packit 63bb0d
		DiskFormat: "qcow2",
Packit 63bb0d
		ContainerFormat: "bare",
Packit 63bb0d
	}).Extract()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return image, fmt.Errorf("Creating image failed: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// then upload the actual binary data
Packit 63bb0d
	imageData, err := os.Open(imagePath)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return image, fmt.Errorf("Error opening %s: %v", imagePath, err)
Packit 63bb0d
	}
Packit 63bb0d
	defer imageData.Close()
Packit 63bb0d
Packit 63bb0d
	err = imagedata.Upload(client, image.ID, imageData).ExtractErr()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return image, fmt.Errorf("Upload to OpenStack failed: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// wait for the status to change from Queued to Active
Packit 63bb0d
	err = gophercloud.WaitFor(WaitTimeout, func() (bool, error) {
Packit 63bb0d
		actual, err := images.Get(client, image.ID).Extract()
Packit 63bb0d
		return actual.Status == images.ImageStatusActive, err
Packit 63bb0d
	})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return image, fmt.Errorf("Waiting for image to become Active failed: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return image, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func DeleteImageFromOpenStack(p *gophercloud.ProviderClient, imageUUID string) error {
Packit 63bb0d
	client, err := openstack.NewImageServiceV2(p, gophercloud.EndpointOpts{
Packit 63bb0d
		Region: os.Getenv("OS_REGION_NAME"),
Packit 63bb0d
	})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("Error creating ImageService client: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	err = images.Delete(client, imageUUID).ExtractErr()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("cannot delete the image: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func WithBootedImageInOpenStack(p *gophercloud.ProviderClient, imageID, userData string, f func(address string) error) (retErr error) {
Packit 63bb0d
	client, err := openstack.NewComputeV2(p, gophercloud.EndpointOpts{
Packit 63bb0d
		Region: os.Getenv("OS_REGION_NAME"),
Packit 63bb0d
	})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("Error creating Compute client: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	server, err := servers.Create(client, servers.CreateOpts{
Packit 63bb0d
		Name:      "osbuild-composer-vm-for-" + imageID,
Packit 63bb0d
		FlavorRef: "77b8cf27-be16-40d9-95b1-81db4522be1e", // ci.m1.medium.ephemeral
Packit 63bb0d
		Networks: []servers.Network{  // provider_net_cci_2
Packit 63bb0d
			servers.Network{UUID: "74e8faa7-87ba-41b2-a000-438013194814"},
Packit 63bb0d
		},
Packit 63bb0d
		ImageRef:  imageID,
Packit 63bb0d
		UserData: []byte(userData),
Packit 63bb0d
	}).Extract()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("Cannot create instance: %v", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// cleanup
Packit 63bb0d
	defer func(){
Packit 63bb0d
		err := servers.ForceDelete(client, server.ID).ExtractErr()
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			fmt.Printf("Force deleting instance %s failed: %v", server.ID, err)
Packit 63bb0d
			return
Packit 63bb0d
		}
Packit 63bb0d
	}()
Packit 63bb0d
Packit 63bb0d
	// wait for the status to become Active
Packit 63bb0d
	err = servers.WaitForStatus(client, server.ID, "ACTIVE", WaitTimeout)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("Waiting for instance %s to become Active failed: %v", server.ID, err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// get server details again to refresh the IP addresses
Packit 63bb0d
	server, err = servers.Get(client, server.ID).Extract()
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return fmt.Errorf("Cannot get instance details: %v\n", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// server.AccessIPv4 is empty so list all addresses and
Packit 63bb0d
	// get the first fixed one. ssh should be equally happy with v4 or v6
Packit 63bb0d
	var fixedIP string
Packit 63bb0d
	for _, networkAddresses := range server.Addresses["provider_net_cci_2"].([]interface{}) {
Packit 63bb0d
		address := networkAddresses.(map[string]interface{})
Packit 63bb0d
		if address["OS-EXT-IPS:type"] == "fixed" {
Packit 63bb0d
			fixedIP = address["addr"].(string)
Packit 63bb0d
			break
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	if fixedIP == "" {
Packit 63bb0d
		return fmt.Errorf("Cannot find IP address for instance %s", server.ID)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return f(fixedIP)
Packit 63bb0d
}