blob: da8ff3b74f84ff69d6625c4c8c07c5d04a23ad66 [file] [log] [blame]
// Package v2 contains common functions for creating compute-based resources
// for use in acceptance tests. See the `*_test.go` files for example usages.
package v2
import (
"crypto/rand"
"crypto/rsa"
"fmt"
"testing"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/quotasets"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"golang.org/x/crypto/ssh"
)
// AssociateFloatingIP will associate a floating IP with an instance. An error
// will be returned if the floating IP was unable to be associated.
func AssociateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server) error {
associateOpts := floatingips.AssociateOpts{
FloatingIP: floatingIP.IP,
}
t.Logf("Attempting to associate floating IP %s to instance %s", floatingIP.IP, server.ID)
err := floatingips.AssociateInstance(client, server.ID, associateOpts).ExtractErr()
if err != nil {
return err
}
return nil
}
// AssociateFloatingIPWithFixedIP will associate a floating IP with an
// instance's specific fixed IP. An error will be returend if the floating IP
// was unable to be associated.
func AssociateFloatingIPWithFixedIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server, fixedIP string) error {
associateOpts := floatingips.AssociateOpts{
FloatingIP: floatingIP.IP,
FixedIP: fixedIP,
}
t.Logf("Attempting to associate floating IP %s to fixed IP %s on instance %s", floatingIP.IP, fixedIP, server.ID)
err := floatingips.AssociateInstance(client, server.ID, associateOpts).ExtractErr()
if err != nil {
return err
}
return nil
}
// CreateBootableVolumeServer works like CreateServer but is configured with
// one or more block devices defined by passing in []bootfromvolume.BlockDevice.
// An error will be returned if a server was unable to be created.
func CreateBootableVolumeServer(t *testing.T, client *gophercloud.ServiceClient, blockDevices []bootfromvolume.BlockDevice, choices *clients.AcceptanceTestChoices) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create bootable volume server: %s", name)
serverCreateOpts := servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
Networks: []servers.Network{
servers.Network{UUID: networkID},
},
}
server, err = bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
serverCreateOpts,
blockDevices,
}).Extract()
if err != nil {
return server, err
}
return server, nil
}
// CreateDefaultRule will create a default security group rule with a
// random port range between 80 and 90. An error will be returned if
// a default rule was unable to be created.
func CreateDefaultRule(t *testing.T, client *gophercloud.ServiceClient) (dsr.DefaultRule, error) {
createOpts := dsr.CreateOpts{
FromPort: tools.RandomInt(80, 89),
ToPort: tools.RandomInt(90, 99),
IPProtocol: "TCP",
CIDR: "0.0.0.0/0",
}
defaultRule, err := dsr.Create(client, createOpts).Extract()
if err != nil {
return *defaultRule, err
}
t.Logf("Created default rule: %s", defaultRule.ID)
return *defaultRule, nil
}
// CreateFloatingIP will allocate a floating IP.
// An error will be returend if one was unable to be allocated.
func CreateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices) (*floatingips.FloatingIP, error) {
createOpts := floatingips.CreateOpts{
Pool: choices.FloatingIPPoolName,
}
floatingIP, err := floatingips.Create(client, createOpts).Extract()
if err != nil {
return floatingIP, err
}
t.Logf("Created floating IP: %s", floatingIP.ID)
return floatingIP, nil
}
func createKey() (string, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", err
}
publicKey := privateKey.PublicKey
pub, err := ssh.NewPublicKey(&publicKey)
if err != nil {
return "", err
}
pubBytes := ssh.MarshalAuthorizedKey(pub)
pk := string(pubBytes)
return pk, nil
}
// CreateKeyPair will create a KeyPair with a random name. An error will occur
// if the keypair failed to be created. An error will be returned if the
// keypair was unable to be created.
func CreateKeyPair(t *testing.T, client *gophercloud.ServiceClient) (*keypairs.KeyPair, error) {
keyPairName := tools.RandomString("keypair_", 5)
t.Logf("Attempting to create keypair: %s", keyPairName)
createOpts := keypairs.CreateOpts{
Name: keyPairName,
}
keyPair, err := keypairs.Create(client, createOpts).Extract()
if err != nil {
return keyPair, err
}
t.Logf("Created keypair: %s", keyPairName)
return keyPair, nil
}
// CreateSecurityGroup will create a security group with a random name.
// An error will be returned if one was failed to be created.
func CreateSecurityGroup(t *testing.T, client *gophercloud.ServiceClient) (secgroups.SecurityGroup, error) {
createOpts := secgroups.CreateOpts{
Name: tools.RandomString("secgroup_", 5),
Description: "something",
}
securityGroup, err := secgroups.Create(client, createOpts).Extract()
if err != nil {
return *securityGroup, err
}
t.Logf("Created security group: %s", securityGroup.ID)
return *securityGroup, nil
}
// CreateSecurityGroupRule will create a security group rule with a random name
// and a random TCP port range between port 80 and 99. An error will be
// returned if the rule failed to be created.
func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, securityGroupID string) (secgroups.Rule, error) {
createOpts := secgroups.CreateRuleOpts{
ParentGroupID: securityGroupID,
FromPort: tools.RandomInt(80, 89),
ToPort: tools.RandomInt(90, 99),
IPProtocol: "TCP",
CIDR: "0.0.0.0/0",
}
rule, err := secgroups.CreateRule(client, createOpts).Extract()
if err != nil {
return *rule, err
}
t.Logf("Created security group rule: %s", rule.ID)
return *rule, nil
}
// CreateServer creates a basic instance with a randomly generated name.
// The flavor of the instance will be the value of the OS_FLAVOR_ID environment variable.
// The image will be the value of the OS_IMAGE_ID environment variable.
// The instance will be launched on the network specified in OS_NETWORK_NAME.
// An error will be returned if the instance was unable to be created.
func CreateServer(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s", name)
pwd := tools.MakeNewPassword("")
server, err = servers.Create(client, servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
AdminPass: pwd,
Networks: []servers.Network{
servers.Network{UUID: networkID},
},
Personality: servers.Personality{
&servers.File{
Path: "/etc/test",
Contents: []byte("hello world"),
},
},
}).Extract()
if err != nil {
return server, err
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return server, err
}
return server, nil
}
// CreateServerGroup will create a server with a random name. An error will be
// returned if the server group failed to be created.
func CreateServerGroup(t *testing.T, client *gophercloud.ServiceClient, policy string) (*servergroups.ServerGroup, error) {
sg, err := servergroups.Create(client, &servergroups.CreateOpts{
Name: "test",
Policies: []string{policy},
}).Extract()
if err != nil {
return sg, err
}
return sg, nil
}
// CreateServerInServerGroup works like CreateServer but places the instance in
// a specified Server Group.
func CreateServerInServerGroup(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices, serverGroup *servergroups.ServerGroup) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s", name)
pwd := tools.MakeNewPassword("")
serverCreateOpts := servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
AdminPass: pwd,
Networks: []servers.Network{
servers.Network{UUID: networkID},
},
}
schedulerHintsOpts := schedulerhints.CreateOptsExt{
serverCreateOpts,
schedulerhints.SchedulerHints{
Group: serverGroup.ID,
},
}
server, err = servers.Create(client, schedulerHintsOpts).Extract()
if err != nil {
return server, err
}
return server, nil
}
// CreateServerWithPublicKey works the same as CreateServer, but additionally
// configures the server with a specified Key Pair name.
func CreateServerWithPublicKey(t *testing.T, client *gophercloud.ServiceClient, choices *clients.AcceptanceTestChoices, keyPairName string) (*servers.Server, error) {
if testing.Short() {
t.Skip("Skipping test that requires server creation in short mode.")
}
var server *servers.Server
networkID, err := GetNetworkIDFromTenantNetworks(t, client, choices.NetworkName)
if err != nil {
return server, err
}
name := tools.RandomString("ACPTTEST", 16)
t.Logf("Attempting to create server: %s", name)
serverCreateOpts := servers.CreateOpts{
Name: name,
FlavorRef: choices.FlavorID,
ImageRef: choices.ImageID,
Networks: []servers.Network{
servers.Network{UUID: networkID},
},
}
server, err = servers.Create(client, keypairs.CreateOptsExt{
serverCreateOpts,
keyPairName,
}).Extract()
if err != nil {
return server, err
}
if err = WaitForComputeStatus(client, server, "ACTIVE"); err != nil {
return server, err
}
return server, nil
}
// CreateVolumeAttachment will attach a volume to a server. An error will be
// returned if the volume failed to attach.
func CreateVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, server *servers.Server, volume *volumes.Volume) (*volumeattach.VolumeAttachment, error) {
volumeAttachOptions := volumeattach.CreateOpts{
VolumeID: volume.ID,
}
t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID)
volumeAttachment, err := volumeattach.Create(client, server.ID, volumeAttachOptions).Extract()
if err != nil {
return volumeAttachment, err
}
if err = volumes.WaitForStatus(blockClient, volume.ID, "in-use", 60); err != nil {
return volumeAttachment, err
}
return volumeAttachment, nil
}
// DeleteDefaultRule deletes a default security group rule.
// A fatal error will occur if the rule failed to delete. This works best when
// using it as a deferred function.
func DeleteDefaultRule(t *testing.T, client *gophercloud.ServiceClient, defaultRule dsr.DefaultRule) {
err := dsr.Delete(client, defaultRule.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete default rule %s: %v", defaultRule.ID, err)
}
t.Logf("Deleted default rule: %s", defaultRule.ID)
}
// DeleteFloatingIP will de-allocate a floating IP. A fatal error will occur if
// the floating IP failed to de-allocate. This works best when using it as a
// deferred function.
func DeleteFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP) {
err := floatingips.Delete(client, floatingIP.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete floating IP %s: %v", floatingIP.ID, err)
}
t.Logf("Deleted floating IP: %s", floatingIP.ID)
}
// DeleteKeyPair will delete a specified keypair. A fatal error will occur if
// the keypair failed to be deleted. This works best when used as a deferred
// function.
func DeleteKeyPair(t *testing.T, client *gophercloud.ServiceClient, keyPair *keypairs.KeyPair) {
err := keypairs.Delete(client, keyPair.Name).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete keypair %s: %v", keyPair.Name, err)
}
t.Logf("Deleted keypair: %s", keyPair.Name)
}
// DeleteSecurityGroup will delete a security group. A fatal error will occur
// if the group failed to be deleted. This works best as a deferred function.
func DeleteSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, securityGroup secgroups.SecurityGroup) {
err := secgroups.Delete(client, securityGroup.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete security group %s: %s", securityGroup.ID, err)
}
t.Logf("Deleted security group: %s", securityGroup.ID)
}
// DeleteSecurityGroupRule will delete a security group rule. A fatal error
// will occur if the rule failed to be deleted. This works best when used
// as a deferred function.
func DeleteSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, rule secgroups.Rule) {
err := secgroups.DeleteRule(client, rule.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete rule: %v", err)
}
t.Logf("Deleted security group rule: %s", rule.ID)
}
// DeleteServer deletes an instance via its UUID.
// A fatal error will occur if the instance failed to be destroyed. This works
// best when using it as a deferred function.
func DeleteServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server) {
err := servers.Delete(client, server.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete server %s: %s", server.ID, err)
}
t.Logf("Deleted server: %s", server.ID)
}
// DeleteServerGroup will delete a server group. A fatal error will occur if
// the server group failed to be deleted. This works best when used as a
// deferred function.
func DeleteServerGroup(t *testing.T, client *gophercloud.ServiceClient, serverGroup *servergroups.ServerGroup) {
err := servergroups.Delete(client, serverGroup.ID).ExtractErr()
if err != nil {
t.Fatalf("Unable to delete server group %s: %v", serverGroup.ID, err)
}
t.Logf("Deleted server group %s", serverGroup.ID)
}
// DeleteVolumeAttachment will disconnect a volume from an instance. A fatal
// error will occur if the volume failed to detach. This works best when used
// as a deferred function.
func DeleteVolumeAttachment(t *testing.T, client *gophercloud.ServiceClient, blockClient *gophercloud.ServiceClient, server *servers.Server, volumeAttachment *volumeattach.VolumeAttachment) {
err := volumeattach.Delete(client, server.ID, volumeAttachment.VolumeID).ExtractErr()
if err != nil {
t.Fatalf("Unable to detach volume: %v", err)
}
if err = volumes.WaitForStatus(blockClient, volumeAttachment.ID, "available", 60); err != nil {
t.Fatalf("Unable to wait for volume: %v", err)
}
t.Logf("Deleted volume: %s", volumeAttachment.VolumeID)
}
// DisassociateFloatingIP will disassociate a floating IP from an instance. A
// fatal error will occur if the floating IP failed to disassociate. This works
// best when using it as a deferred function.
func DisassociateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIP *floatingips.FloatingIP, server *servers.Server) {
disassociateOpts := floatingips.DisassociateOpts{
FloatingIP: floatingIP.IP,
}
err := floatingips.DisassociateInstance(client, server.ID, disassociateOpts).ExtractErr()
if err != nil {
t.Fatalf("Unable to disassociate floating IP %s from server %s: %v", floatingIP.IP, server.ID, err)
}
t.Logf("Disassociated floating IP %s from server %s", floatingIP.IP, server.ID)
}
// GetNetworkIDFromNetworks will return the network ID from a specified network
// UUID using the os-networks API extension. An error will be returned if the
// network could not be retrieved.
func GetNetworkIDFromNetworks(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
allPages, err := networks.List(client).AllPages()
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
networkList, err := networks.ExtractNetworks(allPages)
if err != nil {
t.Fatalf("Unable to list networks: %v", err)
}
networkID := ""
for _, network := range networkList {
t.Logf("Network: %v", network)
if network.Label == networkName {
networkID = network.ID
}
}
t.Logf("Found network ID for %s: %s", networkName, networkID)
return networkID, nil
}
// GetNetworkIDFromTenantNetworks will return the network UUID for a given
// network name using the os-tenant-networks API extension. An error will be
// returned if the network could not be retrieved.
func GetNetworkIDFromTenantNetworks(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
allPages, err := tenantnetworks.List(client).AllPages()
if err != nil {
return "", err
}
allTenantNetworks, err := tenantnetworks.ExtractNetworks(allPages)
if err != nil {
return "", err
}
for _, network := range allTenantNetworks {
if network.Name == networkName {
return network.ID, nil
}
}
return "", fmt.Errorf("Failed to obtain network ID for network %s", networkName)
}
// ImportPublicKey will create a KeyPair with a random name and a specified
// public key. An error will be returned if the keypair failed to be created.
func ImportPublicKey(t *testing.T, client *gophercloud.ServiceClient, publicKey string) (*keypairs.KeyPair, error) {
keyPairName := tools.RandomString("keypair_", 5)
t.Logf("Attempting to create keypair: %s", keyPairName)
createOpts := keypairs.CreateOpts{
Name: keyPairName,
PublicKey: publicKey,
}
keyPair, err := keypairs.Create(client, createOpts).Extract()
if err != nil {
return keyPair, err
}
t.Logf("Created keypair: %s", keyPairName)
return keyPair, nil
}
// ResizeServer performs a resize action on an instance. An error will be
// returned if the instance failed to resize.
// The new flavor that the instance will be resized to is specified in OS_FLAVOR_ID_RESIZE.
func ResizeServer(t *testing.T, client *gophercloud.ServiceClient, server *servers.Server, choices *clients.AcceptanceTestChoices) error {
opts := &servers.ResizeOpts{
FlavorRef: choices.FlavorIDResize,
}
if res := servers.Resize(client, server.ID, opts); res.Err != nil {
return res.Err
}
if err := WaitForComputeStatus(client, server, "VERIFY_RESIZE"); err != nil {
return err
}
return nil
}
// WaitForComputeStatus will poll an instance's status until it either matches
// the specified status or the status becomes ERROR.
func WaitForComputeStatus(client *gophercloud.ServiceClient, server *servers.Server, status string) error {
return tools.WaitFor(func() (bool, error) {
latest, err := servers.Get(client, server.ID).Extract()
if err != nil {
return false, err
}
if latest.Status == status {
// Success!
return true, nil
}
if latest.Status == "ERROR" {
return false, fmt.Errorf("Instance in ERROR state")
}
return false, nil
})
}
// PrintServer will print an instance and all of its attributes.
func PrintServer(t *testing.T, server *servers.Server) {
t.Logf("ID: %s", server.ID)
t.Logf("TenantID: %s", server.TenantID)
t.Logf("UserID: %s", server.UserID)
t.Logf("Name: %s", server.Name)
t.Logf("Updated: %s", server.Updated)
t.Logf("Created: %s", server.Created)
t.Logf("HostID: %s", server.HostID)
t.Logf("Status: %s", server.Status)
t.Logf("Progress: %d", server.Progress)
t.Logf("AccessIPv4: %s", server.AccessIPv4)
t.Logf("AccessIPv6: %s", server.AccessIPv6)
t.Logf("Image: %s", server.Image)
t.Logf("Flavor: %s", server.Flavor)
t.Logf("Addresses: %#v", server.Addresses)
t.Logf("Metadata: %#v", server.Metadata)
t.Logf("Links: %#v", server.Links)
t.Logf("KeyName: %s", server.KeyName)
t.Logf("AdminPass: %s", server.AdminPass)
t.Logf("SecurityGroups: %#v", server.SecurityGroups)
}
// PrintDefaultRule will print a default security group rule and all of its attributes.
func PrintDefaultRule(t *testing.T, defaultRule *dsr.DefaultRule) {
t.Logf("\tID: %s", defaultRule.ID)
t.Logf("\tFrom Port: %d", defaultRule.FromPort)
t.Logf("\tTo Port: %d", defaultRule.ToPort)
t.Logf("\tIP Protocol: %s", defaultRule.IPProtocol)
t.Logf("\tIP Range: %s", defaultRule.IPRange.CIDR)
t.Logf("\tParent Group ID: %s", defaultRule.ParentGroupID)
t.Logf("\tGroup Tenant ID: %s", defaultRule.Group.TenantID)
t.Logf("\tGroup Name: %s", defaultRule.Group.Name)
}
// PrintFlavor will print a flavor and all of its attributes.
func PrintFlavor(t *testing.T, flavor *flavors.Flavor) {
t.Logf("ID: %s", flavor.ID)
t.Logf("Name: %s", flavor.Name)
t.Logf("RAM: %d", flavor.RAM)
t.Logf("Disk: %d", flavor.Disk)
t.Logf("Swap: %d", flavor.Swap)
t.Logf("RxTxFactor: %f", flavor.RxTxFactor)
}
// PrintFloatingIP will print a floating IP and all of its attributes.
func PrintFloatingIP(t *testing.T, floatingIP *floatingips.FloatingIP) {
t.Logf("ID: %s", floatingIP.ID)
t.Logf("Fixed IP: %s", floatingIP.FixedIP)
t.Logf("Instance ID: %s", floatingIP.InstanceID)
t.Logf("IP: %s", floatingIP.IP)
t.Logf("Pool: %s", floatingIP.Pool)
}
// PrintImage will print an image and all of its attributes.
func PrintImage(t *testing.T, image images.Image) {
t.Logf("ID: %s", image.ID)
t.Logf("Name: %s", image.Name)
t.Logf("MinDisk: %d", image.MinDisk)
t.Logf("MinRAM: %d", image.MinRAM)
t.Logf("Status: %s", image.Status)
t.Logf("Progress: %d", image.Progress)
t.Logf("Metadata: %#v", image.Metadata)
t.Logf("Created: %s", image.Created)
t.Logf("Updated: %s", image.Updated)
}
// PrintKeyPair will print keypair and all of its attributes.
func PrintKeyPair(t *testing.T, keypair *keypairs.KeyPair) {
t.Logf("Name: %s", keypair.Name)
t.Logf("Fingerprint: %s", keypair.Fingerprint)
t.Logf("Public Key: %s", keypair.PublicKey)
t.Logf("Private Key: %s", keypair.PrivateKey)
t.Logf("UserID: %s", keypair.UserID)
}
// PrintNetwork will print an os-networks based network and all of its attributes.
func PrintNetwork(t *testing.T, network *networks.Network) {
t.Logf("Bridge: %s", network.Bridge)
t.Logf("BridgeInterface: %s", network.BridgeInterface)
t.Logf("Broadcast: %s", network.Broadcast)
t.Logf("CIDR: %s", network.CIDR)
t.Logf("CIDRv6: %s", network.CIDRv6)
t.Logf("CreatedAt: %v", network.CreatedAt)
t.Logf("Deleted: %t", network.Deleted)
t.Logf("DeletedAt: %v", network.DeletedAt)
t.Logf("DHCPStart: %s", network.DHCPStart)
t.Logf("DNS1: %s", network.DNS1)
t.Logf("DNS2: %s", network.DNS2)
t.Logf("Gateway: %s", network.Gateway)
t.Logf("Gatewayv6: %s", network.Gatewayv6)
t.Logf("Host: %s", network.Host)
t.Logf("ID: %s", network.ID)
t.Logf("Injected: %t", network.Injected)
t.Logf("Label: %s", network.Label)
t.Logf("MultiHost: %t", network.MultiHost)
t.Logf("Netmask: %s", network.Netmask)
t.Logf("Netmaskv6: %s", network.Netmaskv6)
t.Logf("Priority: %d", network.Priority)
t.Logf("ProjectID: %s", network.ProjectID)
t.Logf("RXTXBase: %d", network.RXTXBase)
t.Logf("UpdatedAt: %v", network.UpdatedAt)
t.Logf("VLAN: %d", network.VLAN)
t.Logf("VPNPrivateAddress: %s", network.VPNPrivateAddress)
t.Logf("VPNPublicAddress: %s", network.VPNPublicAddress)
t.Logf("VPNPublicPort: %d", network.VPNPublicPort)
}
// PrintQuotaSet will print a quota set and all of its attributes.
func PrintQuotaSet(t *testing.T, quotaSet *quotasets.QuotaSet) {
t.Logf("instances: %d\n", quotaSet.Instances)
t.Logf("cores: %d\n", quotaSet.Cores)
t.Logf("ram: %d\n", quotaSet.Ram)
t.Logf("key_pairs: %d\n", quotaSet.KeyPairs)
t.Logf("metadata_items: %d\n", quotaSet.MetadataItems)
t.Logf("security_groups: %d\n", quotaSet.SecurityGroups)
t.Logf("security_group_rules: %d\n", quotaSet.SecurityGroupRules)
t.Logf("fixed_ips: %d\n", quotaSet.FixedIps)
t.Logf("floating_ips: %d\n", quotaSet.FloatingIps)
t.Logf("injected_file_content_bytes: %d\n", quotaSet.InjectedFileContentBytes)
t.Logf("injected_file_path_bytes: %d\n", quotaSet.InjectedFilePathBytes)
t.Logf("injected_files: %d\n", quotaSet.InjectedFiles)
}
// PrintSecurityGroup will print a security group and all of its attributes and rules.
func PrintSecurityGroup(t *testing.T, securityGroup *secgroups.SecurityGroup) {
t.Logf("ID: %s", securityGroup.ID)
t.Logf("Name: %s", securityGroup.Name)
t.Logf("Description: %s", securityGroup.Description)
t.Logf("Tenant ID: %s", securityGroup.TenantID)
t.Logf("Rules:")
for _, rule := range securityGroup.Rules {
t.Logf("\tID: %s", rule.ID)
t.Logf("\tFrom Port: %d", rule.FromPort)
t.Logf("\tTo Port: %d", rule.ToPort)
t.Logf("\tIP Protocol: %s", rule.IPProtocol)
t.Logf("\tIP Range: %s", rule.IPRange.CIDR)
t.Logf("\tParent Group ID: %s", rule.ParentGroupID)
t.Logf("\tGroup Tenant ID: %s", rule.Group.TenantID)
t.Logf("\tGroup Name: %s", rule.Group.Name)
}
}
// PrintServerGroup will print a server group and all of its attributes.
func PrintServerGroup(t *testing.T, serverGroup *servergroups.ServerGroup) {
t.Logf("ID: %s", serverGroup.ID)
t.Logf("Name: %s", serverGroup.Name)
t.Logf("Policies: %#v", serverGroup.Policies)
t.Logf("Members: %#v", serverGroup.Members)
t.Logf("Metadata: %#v", serverGroup.Metadata)
}
// PrintTenantNetwork will print an os-tenant-networks based network and all of its attributes.
func PrintTenantNetwork(t *testing.T, network *tenantnetworks.Network) {
t.Logf("ID: %s", network.ID)
t.Logf("Name: %s", network.Name)
t.Logf("CIDR: %s", network.CIDR)
}
// PrintVolumeAttachment will print a volume attachment and all of its attributes.
func PrintVolumeAttachment(t *testing.T, volumeAttachment *volumeattach.VolumeAttachment) {
t.Logf("ID: %s", volumeAttachment.ID)
t.Logf("Device: %s", volumeAttachment.Device)
t.Logf("VolumeID: %s", volumeAttachment.VolumeID)
t.Logf("ServerID: %s", volumeAttachment.ServerID)
}