func TestServerGroups(t *testing.T) {
	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	computeClient, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	sg, err := createServerGroup(t, computeClient)
	if err != nil {
		t.Fatalf("Unable to create server group: %v", err)
	}
	defer func() {
		servergroups.Delete(computeClient, sg.ID)
		t.Logf("Server Group deleted.")
	}()

	err = getServerGroup(t, computeClient, sg.ID)
	if err != nil {
		t.Fatalf("Unable to get server group: %v", err)
	}

	firstServer, err := createServerInGroup(t, computeClient, choices, sg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(computeClient, firstServer.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(computeClient, firstServer, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	firstServer, err = servers.Get(computeClient, firstServer.ID).Extract()

	secondServer, err := createServerInGroup(t, computeClient, choices, sg)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(computeClient, secondServer.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(computeClient, secondServer, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	secondServer, err = servers.Get(computeClient, secondServer.ID).Extract()

	if err = verifySchedulerWorked(t, firstServer, secondServer); err != nil {
		t.Fatalf("Scheduling did not work: %v", err)
	}
}
func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) {
	if s.server == nil {
		return
	}

	config := state.Get("config").(Config)
	ui := state.Get("ui").(packer.Ui)

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	ui.Say("Terminating the source server...")
	if err := servers.Delete(computeClient, s.server.ID).ExtractErr(); err != nil {
		ui.Error(fmt.Sprintf("Error terminating server, may still be around: %s", err))
		return
	}

	stateChange := StateChangeConf{
		Pending: []string{"ACTIVE", "BUILD", "REBUILD", "SUSPENDED", "SHUTOFF", "STOPPED"},
		Refresh: ServerStateRefreshFunc(computeClient, s.server),
		Target:  []string{"DELETED"},
	}

	WaitForState(&stateChange)
}
func resourceComputeInstanceV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	computeClient, err := config.computeV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack compute client: %s", err)
	}

	err = servers.Delete(computeClient, d.Id()).ExtractErr()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack server: %s", err)
	}

	// Wait for the instance to delete before moving on.
	log.Printf("[DEBUG] Waiting for instance (%s) to delete", d.Id())

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE"},
		Target:     []string{"DELETED"},
		Refresh:    ServerV2StateRefreshFunc(computeClient, d.Id()),
		Timeout:    30 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to delete: %s",
			d.Id(), err)
	}

	d.SetId("")
	return nil
}
func TestActionResizeRevert(t *testing.T) {
	t.Parallel()

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)
	resizeServer(t, client, server, choices)

	t.Logf("Attempting to revert resize for server %s", server.ID)

	if res := servers.RevertResize(client, server.ID); res.Err != nil {
		t.Fatal(err)
	}

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}
}
Exemple #5
0
func TestSecGroups(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	serverID, needsDeletion := findServer(t, client)

	groupID := createSecGroup(t, client)

	listSecGroups(t, client)

	newName := tools.RandomString("secgroup_", 5)
	updateSecGroup(t, client, groupID, newName)

	getSecGroup(t, client, groupID)

	addRemoveRules(t, client, groupID)

	addServerToSecGroup(t, client, serverID, newName)

	removeServerFromSecGroup(t, client, serverID, newName)

	if needsDeletion {
		servers.Delete(client, serverID)
	}

	deleteSecGroup(t, client, groupID)
}
func TestMultiEphemeral(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	name := tools.RandomString("Gophercloud-", 8)
	t.Logf("Creating server [%s].", name)

	bd := []bootfromvolume.BlockDevice{
		bootfromvolume.BlockDevice{
			BootIndex:           0,
			UUID:                choices.ImageID,
			SourceType:          bootfromvolume.Image,
			DestinationType:     "local",
			DeleteOnTermination: true,
		},
		bootfromvolume.BlockDevice{
			BootIndex:           -1,
			SourceType:          bootfromvolume.Blank,
			DestinationType:     "local",
			DeleteOnTermination: true,
			GuestFormat:         "ext4",
			VolumeSize:          1,
		},
		bootfromvolume.BlockDevice{
			BootIndex:           -1,
			SourceType:          bootfromvolume.Blank,
			DestinationType:     "local",
			DeleteOnTermination: true,
			GuestFormat:         "ext4",
			VolumeSize:          1,
		},
	}

	serverCreateOpts := servers.CreateOpts{
		Name:      name,
		FlavorRef: choices.FlavorID,
		ImageRef:  choices.ImageID,
	}
	server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
		serverCreateOpts,
		bd,
	}).Extract()
	th.AssertNoErr(t, err)
	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	t.Logf("Created server: %+v\n", server)
	defer servers.Delete(client, server.ID)
	t.Logf("Deleting server [%s]...", name)
}
Exemple #7
0
func TestCreateServerWithKeyPair(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	publicKey := privateKey.PublicKey
	pub, err := ssh.NewPublicKey(&publicKey)
	th.AssertNoErr(t, err)
	pubBytes := ssh.MarshalAuthorizedKey(pub)
	pk := string(pubBytes)

	kp, err := keypairs.Create(client, keypairs.CreateOpts{
		Name:      keyName,
		PublicKey: pk,
	}).Extract()
	th.AssertNoErr(t, err)
	t.Logf("Created key pair: %s\n", kp)

	choices, err := ComputeChoicesFromEnv()
	th.AssertNoErr(t, err)

	name := tools.RandomString("Gophercloud-", 8)
	t.Logf("Creating server [%s] with key pair.", name)

	serverCreateOpts := servers.CreateOpts{
		Name:      name,
		FlavorRef: choices.FlavorID,
		ImageRef:  choices.ImageID,
	}

	server, err := servers.Create(client, keypairs.CreateOptsExt{
		serverCreateOpts,
		keyName,
	}).Extract()
	th.AssertNoErr(t, err)
	defer servers.Delete(client, server.ID)
	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	server, err = servers.Get(client, server.ID).Extract()
	t.Logf("Created server: %+v\n", server)
	th.AssertNoErr(t, err)
	th.AssertEquals(t, server.KeyName, keyName)

	t.Logf("Deleting key pair [%s]...", kp.Name)
	err = keypairs.Delete(client, keyName).ExtractErr()
	th.AssertNoErr(t, err)

	t.Logf("Deleting server [%s]...", name)
}
func TestServerMetadata(t *testing.T) {
	t.Parallel()

	choices, err := ComputeChoicesFromEnv()
	th.AssertNoErr(t, err)

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)
	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	metadata, err := servers.UpdateMetadata(client, server.ID, servers.MetadataOpts{
		"foo":  "bar",
		"this": "that",
	}).Extract()
	th.AssertNoErr(t, err)
	t.Logf("UpdateMetadata result: %+v\n", metadata)

	err = servers.DeleteMetadatum(client, server.ID, "foo").ExtractErr()
	th.AssertNoErr(t, err)

	metadata, err = servers.CreateMetadatum(client, server.ID, servers.MetadatumOpts{
		"foo": "baz",
	}).Extract()
	th.AssertNoErr(t, err)
	t.Logf("CreateMetadatum result: %+v\n", metadata)

	metadata, err = servers.Metadatum(client, server.ID, "foo").Extract()
	th.AssertNoErr(t, err)
	t.Logf("Metadatum result: %+v\n", metadata)
	th.AssertEquals(t, "baz", metadata["foo"])

	metadata, err = servers.Metadata(client, server.ID).Extract()
	th.AssertNoErr(t, err)
	t.Logf("Metadata result: %+v\n", metadata)

	metadata, err = servers.ResetMetadata(client, server.ID, servers.MetadataOpts{}).Extract()
	th.AssertNoErr(t, err)
	t.Logf("ResetMetadata result: %+v\n", metadata)
	th.AssertDeepEquals(t, map[string]string{}, metadata)
}
func TestCreateDestroyServer(t *testing.T) {
	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(client, server.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	pager := servers.ListAddresses(client, server.ID)
	pager.EachPage(func(page pagination.Page) (bool, error) {
		networks, err := servers.ExtractAddresses(page)
		if err != nil {
			return false, err
		}

		for n, a := range networks {
			t.Logf("%s: %+v\n", n, a)
		}
		return true, nil
	})

	pager = servers.ListAddressesByNetwork(client, server.ID, choices.NetworkName)
	pager.EachPage(func(page pagination.Page) (bool, error) {
		addresses, err := servers.ExtractNetworkAddresses(page)
		if err != nil {
			return false, err
		}

		for _, a := range addresses {
			t.Logf("%+v\n", a)
		}
		return true, nil
	})
}
func TestActionRebuild(t *testing.T) {
	t.Parallel()

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	t.Logf("Attempting to rebuild server %s", server.ID)

	rebuildOpts := servers.RebuildOpts{
		Name:      tools.RandomString("ACPTTEST", 16),
		AdminPass: tools.MakeNewPassword(server.AdminPass),
		ImageID:   choices.ImageID,
	}

	rebuilt, err := servers.Rebuild(client, server.ID, rebuildOpts).Extract()
	if err != nil {
		t.Fatal(err)
	}

	if rebuilt.ID != server.ID {
		t.Errorf("Expected rebuilt server ID of [%s]; got [%s]", server.ID, rebuilt.ID)
	}

	if err = waitForStatus(client, rebuilt, "REBUILD"); err != nil {
		t.Fatal(err)
	}

	if err = waitForStatus(client, rebuilt, "ACTIVE"); err != nil {
		t.Fatal(err)
	}
}
func TestUpdateServer(t *testing.T) {
	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	alternateName := tools.RandomString("ACPTTEST", 16)
	for alternateName == server.Name {
		alternateName = tools.RandomString("ACPTTEST", 16)
	}

	t.Logf("Attempting to rename the server to %s.", alternateName)

	updated, err := servers.Update(client, server.ID, servers.UpdateOpts{Name: alternateName}).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 #12
0
func TestFloatingIP(t *testing.T) {
	pool := os.Getenv("OS_POOL_NAME")
	if pool == "" {
		t.Fatalf("OS_POOL_NAME must be set")
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	server, err := createFIPServer(t, client, choices)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(client, server.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	fip, err := createFloatingIP(t, client)
	if err != nil {
		t.Fatalf("Unable to create floating IP: %v", err)
	}
	defer func() {
		err = floatingip.Delete(client, fip.ID).ExtractErr()
		th.AssertNoErr(t, err)
		t.Logf("Floating IP deleted.")
	}()

	associateFloatingIPDeprecated(t, client, server.ID, fip)
	associateFloatingIP(t, client, server.ID, fip)
	associateFloatingIPFixed(t, client, server.ID, fip)

}
func TestAttachVolume(t *testing.T) {
	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	computeClient, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	blockClient, err := newBlockClient(t)
	if err != nil {
		t.Fatalf("Unable to create a blockstorage client: %v", err)
	}

	server, err := createVAServer(t, computeClient, choices)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(computeClient, server.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(computeClient, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	volume, err := createVAVolume(t, blockClient)
	if err != nil {
		t.Fatalf("Unable to create volume: %v", err)
	}
	defer func() {
		err = volumes.Delete(blockClient, volume.ID).ExtractErr()
		th.AssertNoErr(t, err)
		t.Logf("Volume deleted.")
	}()

	createVolumeAttachment(t, computeClient, blockClient, server.ID, volume.ID)

}
func TestActionReboot(t *testing.T) {
	t.Parallel()

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	res := servers.Reboot(client, server.ID, "aldhjflaskhjf")
	if res.Err == nil {
		t.Fatal("Expected the SDK to provide an ArgumentError here")
	}

	t.Logf("Attempting reboot of server %s", server.ID)
	res = servers.Reboot(client, server.ID, servers.OSReboot)
	if res.Err != nil {
		t.Fatalf("Unable to reboot server: %v", err)
	}

	if err = waitForStatus(client, server, "REBOOT"); err != nil {
		t.Fatal(err)
	}

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}
}
Exemple #15
0
func TestNetworks(t *testing.T) {
	networkName := os.Getenv("OS_NETWORK_NAME")
	if networkName == "" {
		t.Fatalf("OS_NETWORK_NAME must be set")
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	networkID, err := getNetworkIDFromNetworkExtension(t, client, networkName)
	if err != nil {
		t.Fatalf("Unable to get network ID: %v", err)
	}

	// createNetworkServer is defined in tenantnetworks_test.go
	server, err := createNetworkServer(t, client, choices, networkID)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(client, server.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}

	allPages, err := networks.List(client).AllPages()
	allNetworks, err := networks.ExtractNetworks(allPages)
	th.AssertNoErr(t, err)
	t.Logf("Retrieved all %d networks: %+v", len(allNetworks), allNetworks)
}
func TestActionChangeAdminPassword(t *testing.T) {
	t.Parallel()

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatal(err)
	}
	defer servers.Delete(client, server.ID)

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	randomPassword := tools.MakeNewPassword(server.AdminPass)
	res := servers.ChangeAdminPassword(client, server.ID, randomPassword)
	if res.Err != nil {
		t.Fatal(err)
	}

	if err = waitForStatus(client, server, "PASSWORD"); err != nil {
		t.Fatal(err)
	}

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}
}
func TestCreateDestroyServer(t *testing.T) {
	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	client, err := newClient()
	if err != nil {
		t.Fatalf("Unable to create a compute client: %v", err)
	}

	server, err := createServer(t, client, choices)
	if err != nil {
		t.Fatalf("Unable to create server: %v", err)
	}
	defer func() {
		servers.Delete(client, server.ID)
		t.Logf("Server deleted.")
	}()

	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatalf("Unable to wait for server: %v", err)
	}
}
Exemple #18
0
func (c *GenericClient) DeleteInstance(d *Driver) error {
	if result := servers.Delete(c.Compute, d.MachineId); result.Err != nil {
		return result.Err
	}
	return nil
}
// Delete requests that a server previously provisioned be removed from your account.
func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
	return os.Delete(client, id)
}
func resourceComputeInstanceV2Delete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	computeClient, err := config.computeV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack compute client: %s", err)
	}

	// Make sure all volumes are detached before deleting
	volumes := d.Get("volume")
	if volumeSet, ok := volumes.(*schema.Set); ok {
		volumeList := volumeSet.List()
		if len(volumeList) > 0 {
			log.Printf("[DEBUG] Attempting to detach the following volumes: %#v", volumeList)
			if blockClient, err := config.blockStorageV1Client(d.Get("region").(string)); err != nil {
				return err
			} else {
				if err := detachVolumesFromInstance(computeClient, blockClient, d.Id(), volumeList); err != nil {
					return err
				}
			}
		}
	}

	if d.Get("stop_before_destroy").(bool) {
		err = startstop.Stop(computeClient, d.Id()).ExtractErr()
		if err != nil {
			log.Printf("[WARN] Error stopping OpenStack instance: %s", err)
		} else {
			stopStateConf := &resource.StateChangeConf{
				Pending:    []string{"ACTIVE"},
				Target:     []string{"SHUTOFF"},
				Refresh:    ServerV2StateRefreshFunc(computeClient, d.Id()),
				Timeout:    3 * time.Minute,
				Delay:      10 * time.Second,
				MinTimeout: 3 * time.Second,
			}
			log.Printf("[DEBUG] Waiting for instance (%s) to stop", d.Id())
			_, err = stopStateConf.WaitForState()
			if err != nil {
				log.Printf("[WARN] Error waiting for instance (%s) to stop: %s, proceeding to delete", d.Id(), err)
			}
		}
	}

	err = servers.Delete(computeClient, d.Id()).ExtractErr()
	if err != nil {
		return fmt.Errorf("Error deleting OpenStack server: %s", err)
	}

	// Wait for the instance to delete before moving on.
	log.Printf("[DEBUG] Waiting for instance (%s) to delete", d.Id())

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"ACTIVE", "SHUTOFF"},
		Target:     []string{"DELETED"},
		Refresh:    ServerV2StateRefreshFunc(computeClient, d.Id()),
		Timeout:    30 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to delete: %s",
			d.Id(), err)
	}

	d.SetId("")
	return nil
}
func main() {
	// step-1
	var authUsername string = "your_auth_username"
	var authPassword string = "your_auth_password"
	var authUrl string = "http://controller:5000"
	var projectName string = "your_project_id"
	var regionName string = "your_region_name"

	authOpts := gophercloud.AuthOptions{
		IdentityEndpoint: authUrl,
		Username:         authUsername,
		Password:         authPassword,
		TenantID:         projectName,
	}
	provider, _ := openstack.AuthenticatedClient(authOpts)
	client, _ := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
		Region: regionName,
	})

	// step-2
	pager := images.ListDetail(client, images.ListOpts{})
	page, _ := pager.AllPages()
	imageList, _ := images.ExtractImages(page)
	fmt.Println(imageList)

	// step-3
	pager = flavors.ListDetail(client, flavors.ListOpts{})
	page, _ = pager.AllPages()
	flavorList, _ := flavors.ExtractFlavors(page)
	fmt.Println(flavorList)

	// step-4
	imageID := "74e6d1ec-9a08-444c-8518-4f232446386d"
	image, _ := images.Get(client, imageID).Extract()
	fmt.Println(image)

	// step-5
	flavorID := "1"
	flavor, _ := flavors.Get(client, flavorID).Extract()
	fmt.Println(flavor)

	// step-6
	instanceName := "testing"
	testingInstance, _ := servers.Create(client, servers.CreateOpts{
		Name:      instanceName,
		ImageRef:  imageID,
		FlavorRef: flavorID,
	}).Extract()
	fmt.Println(testingInstance)

	// step-7
	pager = servers.List(client, servers.ListOpts{})
	page, _ = pager.AllPages()
	serverList, _ := servers.ExtractServers(page)
	fmt.Println(serverList)

	// step-8
	servers.Delete(client, testingInstance.ID)

	// step-9
	fmt.Println("Checking for existing SSH key pair...")
	keyPairName := "demokey"
	pubKeyFile := "~/.ssh/id_rsa.pub"
	keyPairExists := false

	pager = keypairs.List(client)
	page, _ = pager.AllPages()
	keypairList, _ := keypairs.ExtractKeyPairs(page)
	for _, k := range keypairList {
		if k.Name == keyPairName {
			keyPairExists = true
			break
		}
	}

	if keyPairExists {
		fmt.Println("Keypair " + keyPairName + " already exists. Skipping import.")
	} else {
		fmt.Println("adding keypair...")
		bs, _ := ioutil.ReadFile(pubKeyFile)
		keypairs.Create(client, keypairs.CreateOpts{
			Name:      keyPairName,
			PublicKey: string(bs),
		}).Extract()
	}

	pager = keypairs.List(client)
	page, _ = pager.AllPages()
	keypairList, _ = keypairs.ExtractKeyPairs(page)
	fmt.Println(keypairList)

	// step-10
	fmt.Println("Checking for existing security group...")
	var allInOneSecurityGroup secgroups.SecurityGroup
	securityGroupName := "all-in-one"
	securityGroupExists := false

	pager = secgroups.List(client)
	page, _ = pager.AllPages()
	secgroupList, _ := secgroups.ExtractSecurityGroups(page)
	for _, secGroup := range secgroupList {
		if secGroup.Name == securityGroupName {
			allInOneSecurityGroup = secGroup
			securityGroupExists = true
			break
		}
	}

	if securityGroupExists {
		fmt.Println("Security Group " + allInOneSecurityGroup.Name + " already exists. Skipping creation.")
	} else {
		allInOneSecurityGroup, _ := secgroups.Create(client, secgroups.CreateOpts{
			Name:        securityGroupName,
			Description: "network access for all-in-one application.",
		}).Extract()
		secgroups.CreateRule(client, secgroups.CreateRuleOpts{
			ParentGroupID: allInOneSecurityGroup.ID,
			FromPort:      80,
			ToPort:        80,
			IPProtocol:    "TCP",
			CIDR:          "0.0.0.0/0",
		}).Extract()
		secgroups.CreateRule(client, secgroups.CreateRuleOpts{
			ParentGroupID: allInOneSecurityGroup.ID,
			FromPort:      22,
			ToPort:        22,
			IPProtocol:    "TCP",
			CIDR:          "0.0.0.0/0",
		}).Extract()
	}

	pager = secgroups.List(client)
	page, _ = pager.AllPages()
	secgroupList, _ = secgroups.ExtractSecurityGroups(page)
	fmt.Println(secgroupList)

	// step-11
	userData := `#!/usr/bin/env bash
curl -L -s https://git.openstack.org/cgit/openstack/faafo/plain/contrib/install.sh | bash -s -- \
    -i faafo -i messaging -r api -r worker -r demo
`

	// step-12
	fmt.Println("Checking for existing instance...")
	instanceName = "all-in-one"
	instanceExists := false

	pager = servers.List(client, servers.ListOpts{})
	page, _ = pager.AllPages()
	serverList, _ = servers.ExtractServers(page)
	for _, s := range serverList {
		if s.Name == instanceName {
			testingInstance = &s
			instanceExists = true
			break
		}
	}

	if instanceExists {
		fmt.Println("Instance " + testingInstance.Name + " already exists. Skipping creation.")
	} else {
		opts := servers.CreateOpts{
			Name:           instanceName,
			ImageRef:       image.ID,
			FlavorRef:      flavor.ID,
			SecurityGroups: []string{securityGroupName},
			UserData:       []byte(userData),
		}
		testingInstance, _ = servers.Create(client, keypairs.CreateOptsExt{
			CreateOptsBuilder: opts,
			KeyName:           keyPairName,
		}).Extract()
	}
	servers.WaitForStatus(client, testingInstance.ID, "ACTIVE", 300)

	pager = servers.List(client, servers.ListOpts{})
	page, _ = pager.AllPages()
	serverList, _ = servers.ExtractServers(page)
	fmt.Println(serverList)

	// step-13
	var privateIP string
	for t, addrs := range testingInstance.Addresses {
		if t != "private" || len(privateIP) != 0 {
			continue
		}
		addrs, ok := addrs.([]interface{})
		if !ok {
			continue
		}
		for _, addr := range addrs {
			a, ok := addr.(map[string]interface{})
			if !ok || a["version"].(float64) != 4 {
				continue
			}
			ip, ok := a["addr"].(string)
			if ok && len(ip) != 0 {
				privateIP = ip
				fmt.Println("Private IP found: " + privateIP)
				break
			}
		}
	}

	// step-14
	var publicIP string
	for t, addrs := range testingInstance.Addresses {
		if t != "public" || len(publicIP) != 0 {
			continue
		}
		addrs, ok := addrs.([]interface{})
		if !ok {
			continue
		}
		for _, addr := range addrs {
			a, ok := addr.(map[string]interface{})
			if !ok || a["version"].(float64) != 4 {
				continue
			}
			ip, ok := a["addr"].(string)
			if ok && len(ip) != 0 {
				publicIP = ip
				fmt.Println("Public IP found: " + publicIP)
				break
			}
		}
	}

	// step-15
	fmt.Println("Checking for unused Floating IP...")
	var unusedFloatingIP string
	pager = floatingip.List(client)
	page, _ = pager.AllPages()
	floatingIPList, _ := floatingip.ExtractFloatingIPs(page)
	for _, ip := range floatingIPList {
		if ip.InstanceID == "" {
			unusedFloatingIP = ip.IP
			break
		}
	}

	networkClient, _ := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
		Region: regionName,
	})

	pager = networks.List(networkClient, networks.ListOpts{})
	page, _ = pager.AllPages()
	poolList, _ := external.ExtractList(page)
	for _, pool := range poolList {
		if len(unusedFloatingIP) != 0 || !pool.External {
			continue
		}
		fmt.Println("Allocating new Floating IP from pool: " + pool.Name)
		f, _ := floatingip.Create(client, floatingip.CreateOpts{Pool: pool.Name}).Extract()
		unusedFloatingIP = f.IP
	}

	// step-16
	if len(publicIP) != 0 {
		fmt.Println("Instance " + testingInstance.Name + " already has a public ip. Skipping attachment.")
	} else {
		floatingip.Associate(client, testingInstance.ID, unusedFloatingIP)
	}

	// step-17
	var actualIPAddress string
	if len(publicIP) != 0 {
		actualIPAddress = publicIP
	} else if len(unusedFloatingIP) != 0 {
		actualIPAddress = unusedFloatingIP
	} else {
		actualIPAddress = privateIP
	}

	fmt.Println("The Fractals app will be deployed to http://" + actualIPAddress)
}