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)
}
Exemple #4
0
// 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
	})
}
Exemple #11
0
// 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
}
Exemple #12
0
// 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")
	}
}
Exemple #13
0
// 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
}
Exemple #18
0
// 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
}