func (s *StepWaitForRackConnect) Run(state multistep.StateBag) multistep.StepAction { if !s.Wait { return multistep.ActionContinue } config := state.Get("config").(Config) server := state.Get("server").(*servers.Server) ui := state.Get("ui").(packer.Ui) // We need the v2 compute client computeClient, err := config.computeV2Client() if err != nil { err = fmt.Errorf("Error initializing compute client: %s", err) state.Put("error", err) return multistep.ActionHalt } ui.Say(fmt.Sprintf( "Waiting for server (%s) to become RackConnect ready...", server.ID)) for { server, err = servers.Get(computeClient, server.ID).Extract() if err != nil { return multistep.ActionHalt } if server.Metadata["rackconnect_automation_status"] == "DEPLOYED" { state.Put("server", server) break } time.Sleep(2 * time.Second) } return multistep.ActionContinue }
func testAccCheckComputeV2InstanceExists(t *testing.T, n string, instance *servers.Server) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { return fmt.Errorf("Not found: %s", n) } if rs.Primary.ID == "" { return fmt.Errorf("No ID is set") } config := testAccProvider.Meta().(*Config) computeClient, err := config.computeV2Client(OS_REGION_NAME) if err != nil { return fmt.Errorf("(testAccCheckComputeV2InstanceExists) Error creating OpenStack compute client: %s", err) } found, err := servers.Get(computeClient, rs.Primary.ID).Extract() if err != nil { return err } if found.ID != rs.Primary.ID { return fmt.Errorf("Instance not found") } *instance = *found return nil } }
func TestFloatingIPsFixedIPAssociate(t *testing.T) { if testing.Short() { t.Skip("Skipping test that requires server creation in short mode.") } client, err := clients.NewComputeV2Client() if err != nil { t.Fatalf("Unable to create a compute client: %v", err) } choices, err := clients.AcceptanceTestChoicesFromEnv() if err != nil { t.Fatal(err) } server, err := CreateServer(t, client, choices) if err != nil { t.Fatalf("Unable to create server: %v", err) } defer DeleteServer(t, client, server) newServer, err := servers.Get(client, server.ID).Extract() if err != nil { t.Fatalf("Unable to get server %s: %v", server.ID, err) } floatingIP, err := CreateFloatingIP(t, client, choices) if err != nil { t.Fatalf("Unable to create floating IP: %v", err) } defer DeleteFloatingIP(t, client, floatingIP) PrintFloatingIP(t, floatingIP) var fixedIP string for _, networkAddresses := range newServer.Addresses[choices.NetworkName].([]interface{}) { address := networkAddresses.(map[string]interface{}) if address["OS-EXT-IPS:type"] == "fixed" { if address["version"].(float64) == 4 { fixedIP = address["addr"].(string) } } } err = AssociateFloatingIPWithFixedIP(t, client, floatingIP, newServer, fixedIP) if err != nil { t.Fatalf("Unable to associate floating IP %s with server %s: %v", floatingIP.IP, newServer.ID, err) } defer DisassociateFloatingIP(t, client, floatingIP, newServer) newFloatingIP, err := floatingips.Get(client, floatingIP.ID).Extract() if err != nil { t.Fatalf("Unable to get floating IP %s: %v", floatingIP.ID, err) } t.Logf("Floating IP %s is associated with Fixed IP %s", floatingIP.IP, newFloatingIP.FixedIP) PrintFloatingIP(t, newFloatingIP) }
// checkServer achieves the aims of CheckServer() func (p *openstackp) checkServer(serverID string) (bool, error) { server, err := servers.Get(p.computeClient, serverID).Extract() if err != nil { if err.Error() == "Resource not found" { return false, nil } return false, err } return server.Status == "ACTIVE", nil }
func TestServergroupsAffinityPolicy(t *testing.T) { client, err := clients.NewComputeV2Client() if err != nil { t.Fatalf("Unable to create a compute client: %v", err) } choices, err := clients.AcceptanceTestChoicesFromEnv() if err != nil { t.Fatal(err) } serverGroup, err := CreateServerGroup(t, client, "affinity") if err != nil { t.Fatalf("Unable to create server group: %v", err) } defer DeleteServerGroup(t, client, serverGroup) firstServer, err := CreateServerInServerGroup(t, client, choices, serverGroup) if err != nil { t.Fatalf("Unable to create server: %v", err) } defer DeleteServer(t, client, firstServer) firstServer, err = servers.Get(client, firstServer.ID).Extract() secondServer, err := CreateServerInServerGroup(t, client, choices, serverGroup) if err != nil { t.Fatalf("Unable to create server: %v", err) } if err = WaitForComputeStatus(client, secondServer, "ACTIVE"); err != nil { t.Fatalf("Unable to wait for server: %v", err) } defer DeleteServer(t, client, secondServer) secondServer, err = servers.Get(client, secondServer.ID).Extract() if firstServer.HostID != secondServer.HostID { t.Fatalf("%s and %s were not scheduled on the same host.", firstServer.ID, secondServer.ID) } }
// getInstanceNetworks collects instance network information from different sources // and aggregates it all together. func getInstanceNetworksAndAddresses(computeClient *gophercloud.ServiceClient, d *schema.ResourceData) ([]map[string]interface{}, error) { server, err := servers.Get(computeClient, d.Id()).Extract() if err != nil { return nil, CheckDeleted(d, err, "server") } networkDetails, err := getInstanceNetworks(computeClient, d) addresses := getInstanceAddresses(server.Addresses) if err != nil { return nil, err } // if there are no networkDetails, make networks at least a length of 1 networkLength := 1 if len(networkDetails) > 0 { networkLength = len(networkDetails) } networks := make([]map[string]interface{}, networkLength) // Loop through all networks and addresses, // merge relevant address details. if len(networkDetails) == 0 { for netName, n := range addresses { networks[0] = map[string]interface{}{ "name": netName, "fixed_ip_v4": n["fixed_ip_v4"], "fixed_ip_v6": n["fixed_ip_v6"], "floating_ip": n["floating_ip"], "mac": n["mac"], } } } else { for i, net := range networkDetails { n := addresses[net["name"].(string)] networks[i] = map[string]interface{}{ "uuid": networkDetails[i]["uuid"], "name": networkDetails[i]["name"], "port": networkDetails[i]["port"], "fixed_ip_v4": n["fixed_ip_v4"], "fixed_ip_v6": n["fixed_ip_v6"], "floating_ip": n["floating_ip"], "mac": n["mac"], "access_network": networkDetails[i]["access_network"], } } } log.Printf("[DEBUG] networks: %+v", networks) return networks, nil }
func TestServersCreateDestroy(t *testing.T) { client, err := clients.NewComputeV2Client() if err != nil { t.Fatalf("Unable to create a compute client: %v", err) } choices, err := clients.AcceptanceTestChoicesFromEnv() if err != nil { t.Fatal(err) } server, err := CreateServer(t, client, choices) if err != nil { t.Fatalf("Unable to create server: %v", err) } defer DeleteServer(t, client, server) newServer, err := servers.Get(client, server.ID).Extract() if err != nil { t.Errorf("Unable to retrieve server: %v", err) } PrintServer(t, newServer) allAddressPages, err := servers.ListAddresses(client, server.ID).AllPages() if err != nil { t.Errorf("Unable to list server addresses: %v", err) } allAddresses, err := servers.ExtractAddresses(allAddressPages) if err != nil { t.Errorf("Unable to extract server addresses: %v", err) } for network, address := range allAddresses { t.Logf("Addresses on %s: %+v", network, address) } allNetworkAddressPages, err := servers.ListAddressesByNetwork(client, server.ID, choices.NetworkName).AllPages() if err != nil { t.Errorf("Unable to list server addresses: %v", err) } allNetworkAddresses, err := servers.ExtractNetworkAddresses(allNetworkAddressPages) if err != nil { t.Errorf("Unable to extract server addresses: %v", err) } t.Logf("Addresses on %s:", choices.NetworkName) for _, address := range allNetworkAddresses { t.Logf("%+v", address) } }
// ServerV2StateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // an OpenStack instance. func ServerV2StateRefreshFunc(client *gophercloud.ServiceClient, instanceID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { s, err := servers.Get(client, instanceID).Extract() if err != nil { if _, ok := err.(gophercloud.ErrDefault404); ok { return s, "DELETED", nil } return nil, "", err } return s, s.Status, nil } }
func TestGetServer(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() HandleServerGetSuccessfully(t) client := client.ServiceClient() actual, err := servers.Get(client, "1234asdf").Extract() if err != nil { t.Fatalf("Unexpected Get error: %v", err) } th.CheckDeepEquals(t, ServerDerp, *actual) }
func TestServersUpdate(t *testing.T) { client, err := clients.NewComputeV2Client() if err != nil { t.Fatalf("Unable to create a compute client: %v", err) } choices, err := clients.AcceptanceTestChoicesFromEnv() if err != nil { t.Fatal(err) } server, err := CreateServer(t, client, choices) if err != nil { t.Fatal(err) } defer DeleteServer(t, client, server) alternateName := tools.RandomString("ACPTTEST", 16) for alternateName == server.Name { alternateName = tools.RandomString("ACPTTEST", 16) } t.Logf("Attempting to rename the server to %s.", alternateName) updateOpts := servers.UpdateOpts{ Name: alternateName, } updated, err := servers.Update(client, server.ID, updateOpts).Extract() if err != nil { t.Fatalf("Unable to rename server: %v", err) } if updated.ID != server.ID { t.Errorf("Updated server ID [%s] didn't match original server ID [%s]!", updated.ID, server.ID) } err = tools.WaitFor(func() (bool, error) { latest, err := servers.Get(client, updated.ID).Extract() if err != nil { return false, err } return latest.Name == alternateName, 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, Networks: []servers.Network{ servers.Network{UUID: networkID}, }, } if blockDevices[0].SourceType == bootfromvolume.SourceImage && blockDevices[0].DestinationType == bootfromvolume.DestinationLocal { serverCreateOpts.ImageRef = blockDevices[0].UUID } server, err = bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{ serverCreateOpts, blockDevices, }).Extract() if err != nil { return server, err } if err := WaitForComputeStatus(client, server, "ACTIVE"); err != nil { return server, err } newServer, err := servers.Get(client, server.ID).Extract() return newServer, nil }
// CommHost looks up the host for the communicator. func CommHost( client *gophercloud.ServiceClient, sshinterface string, sshipversion string) func(multistep.StateBag) (string, error) { return func(state multistep.StateBag) (string, error) { s := state.Get("server").(*servers.Server) // If we have a specific interface, try that if sshinterface != "" { if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" { log.Printf("[DEBUG] Using IP address %s from specified interface %s to connect", addr, sshinterface) return addr, nil } } // If we have a floating IP, use that ip := state.Get("access_ip").(*floatingips.FloatingIP) if ip != nil && ip.IP != "" { log.Printf("[DEBUG] Using floating IP %s to connect", ip.IP) return ip.IP, nil } if s.AccessIPv4 != "" { log.Printf("[DEBUG] Using AccessIPv4 %s to connect", s.AccessIPv4) return s.AccessIPv4, nil } // Try to get it from the requested interface if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" { log.Printf("[DEBUG] Using IP address %s to connect", addr) return addr, nil } s, err := servers.Get(client, s.ID).Extract() if err != nil { return "", err } state.Put("server", s) time.Sleep(1 * time.Second) return "", errors.New("couldn't determine IP address for server") } }
// 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 }) }
func testAccCheckComputeV2InstanceDoesNotExist(t *testing.T, n string, instance *servers.Server) resource.TestCheckFunc { return func(s *terraform.State) error { config := testAccProvider.Meta().(*Config) computeClient, err := config.computeV2Client(OS_REGION_NAME) if err != nil { return fmt.Errorf("(testAccCheckComputeV2InstanceExists) Error creating OpenStack compute client: %s", err) } _, err = servers.Get(computeClient, instance.ID).Extract() if err != nil { if _, ok := err.(gophercloud.ErrDefault404); ok { return nil } return err } return fmt.Errorf("Instance still exists") } }
func testAccCheckComputeV2InstanceDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) computeClient, err := config.computeV2Client(OS_REGION_NAME) if err != nil { return fmt.Errorf("(testAccCheckComputeV2InstanceDestroy) Error creating OpenStack compute client: %s", err) } for _, rs := range s.RootModule().Resources { if rs.Type != "openstack_compute_instance_v2" { continue } _, err := servers.Get(computeClient, rs.Primary.ID).Extract() if err == nil { return fmt.Errorf("Instance still exists") } } return nil }
func TestKeypairsServerCreateWithKey(t *testing.T) { if testing.Short() { t.Skip("Skipping test that requires server creation in short mode.") } client, err := clients.NewComputeV2Client() if err != nil { t.Fatalf("Unable to create a compute client: %v", err) } choices, err := clients.AcceptanceTestChoicesFromEnv() if err != nil { t.Fatal(err) } publicKey, err := createKey() if err != nil { t.Fatalf("Unable to create public key: %s", err) } keyPair, err := ImportPublicKey(t, client, publicKey) if err != nil { t.Fatalf("Unable to create keypair: %s", err) } defer DeleteKeyPair(t, client, keyPair) server, err := CreateServerWithPublicKey(t, client, choices, keyPair.Name) if err != nil { t.Fatalf("Unable to create server: %s", err) } defer DeleteServer(t, client, server) server, err = servers.Get(client, server.ID).Extract() if err != nil { t.Fatalf("Unable to retrieve server: %s", err) } if server.KeyName != keyPair.Name { t.Fatalf("key name of server %s is %s, not %s", server.ID, server.KeyName, keyPair.Name) } }
func resourceComputeInstanceV2Read(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) computeClient, err := config.computeV2Client(GetRegion(d)) if err != nil { return fmt.Errorf("Error creating OpenStack compute client: %s", err) } server, err := servers.Get(computeClient, d.Id()).Extract() if err != nil { return CheckDeleted(d, err, "server") } log.Printf("[DEBUG] Retrieved Server %s: %+v", d.Id(), server) d.Set("name", server.Name) // Get the instance network and address information networks, err := getInstanceNetworksAndAddresses(computeClient, d) if err != nil { return err } // Determine the best IPv4 and IPv6 addresses to access the instance with hostv4, hostv6 := getInstanceAccessAddresses(d, networks) if server.AccessIPv4 != "" && hostv4 == "" { hostv4 = server.AccessIPv4 } if server.AccessIPv6 != "" && hostv6 == "" { hostv6 = server.AccessIPv6 } d.Set("network", networks) d.Set("access_ip_v4", hostv4) d.Set("access_ip_v6", hostv6) // Determine the best IP address to use for SSH connectivity. // Prefer IPv4 over IPv6. preferredSSHAddress := "" if hostv4 != "" { preferredSSHAddress = hostv4 } else if hostv6 != "" { preferredSSHAddress = hostv6 } if preferredSSHAddress != "" { // Initialize the connection info d.SetConnInfo(map[string]string{ "type": "ssh", "host": preferredSSHAddress, }) } d.Set("metadata", server.Metadata) secGrpNames := []string{} for _, sg := range server.SecurityGroups { secGrpNames = append(secGrpNames, sg["name"].(string)) } d.Set("security_groups", secGrpNames) flavorId, ok := server.Flavor["id"].(string) if !ok { return fmt.Errorf("Error setting OpenStack server's flavor: %v", server.Flavor) } d.Set("flavor_id", flavorId) flavor, err := flavors.Get(computeClient, flavorId).Extract() if err != nil { return err } d.Set("flavor_name", flavor.Name) // Set the instance's image information appropriately if err := setImageInformation(computeClient, server, d); err != nil { return err } // volume attachments if err := getVolumeAttachments(computeClient, d); err != nil { return err } return nil }
// spawn achieves the aims of Spawn() func (p *openstackp) spawn(resources *Resources, osPrefix string, flavorID string, externalIP bool, postCreationScript []byte) (serverID string, serverIP string, adminPass string, err error) { // get available images, pick the one that matches desired OS // *** rackspace API lets you filter on eg. os_distro=ubuntu and os_version=12.04; can we do the same here? pager := images.ListDetail(p.computeClient, images.ListOpts{Status: "ACTIVE"}) var imageID string err = pager.EachPage(func(page pagination.Page) (bool, error) { imageList, err := images.ExtractImages(page) if err != nil { return false, err } for _, i := range imageList { if i.Progress == 100 && strings.HasPrefix(i.Name, osPrefix) { imageID = i.ID return false, nil } } return true, nil }) if err != nil { return } // create the server with a unique name server, err := servers.Create(p.computeClient, keypairs.CreateOptsExt{ CreateOptsBuilder: servers.CreateOpts{ Name: uniqueResourceName(resources.ResourceName), FlavorRef: flavorID, ImageRef: imageID, SecurityGroups: []string{p.securityGroup}, Networks: []servers.Network{{UUID: p.networkUUID}}, UserData: postCreationScript, // Metadata map[string]string }, KeyName: resources.ResourceName, }).Extract() if err != nil { return } // wait for it to come up; servers.WaitForStatus has a timeout, but it // doesn't always work, so we roll our own waitForActive := make(chan error) go func() { timeout := time.After(60 * time.Second) ticker := time.NewTicker(1 * time.Second) for { select { case <-ticker.C: current, err := servers.Get(p.computeClient, server.ID).Extract() if err != nil { ticker.Stop() waitForActive <- err return } if current.Status == "ACTIVE" { ticker.Stop() waitForActive <- nil return } if current.Status == "ERROR" { ticker.Stop() waitForActive <- errors.New("there was an error in bringing up the new server") return } continue case <-timeout: ticker.Stop() waitForActive <- errors.New("timed out waiting for server to become ACTIVE") return } } }() err = <-waitForActive if err != nil { // since we're going to return an error that we failed to spawn, try and // delete the bad server in case it is still there servers.Delete(p.computeClient, server.ID) return } // *** NB. it can still take some number of seconds before I can ssh to it serverID = server.ID adminPass = server.AdminPass // get the servers IP; if we error for any reason we'll delete the server // first, because without an IP it's useless if externalIP { // give it a floating ip var floatingIP string floatingIP, err = p.getAvailableFloatingIP() if err != nil { p.destroyServer(serverID) return } // associate floating ip with server *** we have a race condition // between finding/creating free floating IP above, and using it here err = floatingips.AssociateInstance(p.computeClient, serverID, floatingips.AssociateOpts{ FloatingIP: floatingIP, }).ExtractErr() if err != nil { p.destroyServer(serverID) return } serverIP = floatingIP } else { // find its auto-assigned internal ip *** there must be a better way of // doing this... allNetworkAddressPages, serr := servers.ListAddressesByNetwork(p.computeClient, serverID, p.networkName).AllPages() if serr != nil { p.destroyServer(serverID) err = serr return } allNetworkAddresses, serr := servers.ExtractNetworkAddresses(allNetworkAddressPages) if serr != nil { p.destroyServer(serverID) err = serr return } for _, address := range allNetworkAddresses { if address.Version == 4 && strings.HasPrefix(address.Address, "192.168") { serverIP = address.Address break } } } return }