func setImageInformation(computeClient *gophercloud.ServiceClient, server *servers.Server, d *schema.ResourceData) error { // If block_device was used, an Image does not need to be specified. // If an Image was specified, ignore it if _, ok := d.GetOk("block_device"); ok { d.Set("image_id", "Attempt to boot from volume - no image supplied") return nil } imageId := server.Image["id"].(string) if imageId != "" { d.Set("image_id", imageId) if image, err := images.Get(computeClient, imageId).Extract(); err != nil { errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) if !ok { return err } if errCode.Actual == 404 { // If the image name can't be found, set the value to "Image not found". // The most likely scenario is that the image no longer exists in the Image Service // but the instance still has a record from when it existed. d.Set("image_name", "Image not found") return nil } else { return err } } else { d.Set("image_name", image.Name) } } return nil }
// WaitForImage waits for the given Image ID to become ready. func WaitForImage(client *gophercloud.ServiceClient, imageId string) error { maxNumErrors := 10 numErrors := 0 for { image, err := images.Get(client, imageId).Extract() if err != nil { errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) if ok && (errCode.Actual == 500 || errCode.Actual == 404) { numErrors++ if numErrors >= maxNumErrors { log.Printf("[ERROR] Maximum number of errors (%d) reached; failing with: %s", numErrors, err) return err } log.Printf("[ERROR] %d error received, will ignore and retry: %s", errCode.Actual, err) time.Sleep(2 * time.Second) continue } return err } if image.Status == "ACTIVE" { return nil } log.Printf("Waiting for image creation status: %s (%d%%)", image.Status, image.Progress) time.Sleep(2 * time.Second) } }
func setImageInformation(computeClient *gophercloud.ServiceClient, server *servers.Server, d *schema.ResourceData) error { // If block_device was used, an Image does not need to be specified, unless an image/local // combination was used. This emulates normal boot behavior. Otherwise, ignore the image altogether. if vL, ok := d.GetOk("block_device"); ok { needImage := false for _, v := range vL.([]interface{}) { vM := v.(map[string]interface{}) if vM["source_type"] == "image" && vM["destination_type"] == "local" { needImage = true } } if !needImage { d.Set("image_id", "Attempt to boot from volume - no image supplied") return nil } } imageId := server.Image["id"].(string) if imageId != "" { d.Set("image_id", imageId) if image, err := images.Get(computeClient, imageId).Extract(); err != nil { errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) if !ok { return err } if errCode.Actual == 404 { // If the image name can't be found, set the value to "Image not found". // The most likely scenario is that the image no longer exists in the Image Service // but the instance still has a record from when it existed. d.Set("image_name", "Image not found") return nil } else { return err } } else { d.Set("image_name", image.Name) } } return nil }
// WaitForImage waits for the given Image ID to become ready. func WaitForImage(client *gophercloud.ServiceClient, imageId string) error { for { image, err := images.Get(client, imageId).Extract() if err != nil { errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) if ok && errCode.Actual == 500 { log.Printf("[ERROR] 500 error received, will ignore and retry: %s", err) time.Sleep(2 * time.Second) continue } return err } if image.Status == "ACTIVE" { return nil } log.Printf("Waiting for image creation status: %s (%d%%)", image.Status, image.Progress) time.Sleep(2 * time.Second) } }
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) }
func resourceComputeInstanceV2Read(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) } server, err := servers.Get(computeClient, d.Id()).Extract() if err != nil { return CheckDeleted(d, err, "server") } log.Printf("[DEBUG] Retreived Server %s: %+v", d.Id(), server) d.Set("name", server.Name) // begin reading the network configuration d.Set("access_ip_v4", server.AccessIPv4) d.Set("access_ip_v6", server.AccessIPv6) hostv4 := server.AccessIPv4 hostv6 := server.AccessIPv6 networkDetails, err := resourceInstanceNetworks(computeClient, d) addresses := resourceInstanceAddresses(server.Addresses) if err != nil { return 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 { if floatingIP, ok := n["floating_ip"]; ok { hostv4 = floatingIP.(string) } else { if hostv4 == "" && n["fixed_ip_v4"] != nil { hostv4 = n["fixed_ip_v4"].(string) } } if hostv6 == "" && n["fixed_ip_v6"] != nil { hostv6 = n["fixed_ip_v6"].(string) } networks[0] = map[string]interface{}{ "name": netName, "fixed_ip_v4": n["fixed_ip_v4"], "fixed_ip_v6": n["fixed_ip_v6"], "mac": n["mac"], } } } else { for i, net := range networkDetails { n := addresses[net["name"].(string)] if floatingIP, ok := n["floating_ip"]; ok { hostv4 = floatingIP.(string) } else { if hostv4 == "" && n["fixed_ip_v4"] != nil { hostv4 = n["fixed_ip_v4"].(string) } } if hostv6 == "" && n["fixed_ip_v6"] != nil { hostv6 = n["fixed_ip_v6"].(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"], "mac": n["mac"], } } } log.Printf("[DEBUG] new networks: %+v", networks) d.Set("network", networks) d.Set("access_ip_v4", hostv4) d.Set("access_ip_v6", hostv6) log.Printf("hostv4: %s", hostv4) log.Printf("hostv6: %s", hostv6) // prefer the v6 address if no v4 address exists. preferredv := "" if hostv4 != "" { preferredv = hostv4 } else if hostv6 != "" { preferredv = hostv6 } if preferredv != "" { // Initialize the connection info d.SetConnInfo(map[string]string{ "type": "ssh", "host": preferredv, }) } // end network configuration 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) imageId, ok := server.Image["id"].(string) if !ok { return fmt.Errorf("Error setting OpenStack server's image: %v", server.Image) } d.Set("image_id", imageId) image, err := images.Get(computeClient, imageId).Extract() if err != nil { return err } d.Set("image_name", image.Name) // volume attachments vas, err := getVolumeAttachments(computeClient, d.Id()) if err != nil { return err } if len(vas) > 0 { attachments := make([]map[string]interface{}, len(vas)) for i, attachment := range vas { attachments[i] = make(map[string]interface{}) attachments[i]["id"] = attachment.ID attachments[i]["volume_id"] = attachment.VolumeID attachments[i]["device"] = attachment.Device } log.Printf("[INFO] Volume attachments: %v", attachments) d.Set("volume", attachments) } return nil }
// Get acquires additional detail about a specific image by ID. func Get(client *gophercloud.ServiceClient, id string) os.GetResult { return os.Get(client, id) }