func TestCreateServer(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() HandleServerCreationSuccessfully(t, SingleServerBody) actual, err := servers.Create(client.ServiceClient(), servers.CreateOpts{ Name: "derp", ImageRef: "f90f6034-2570-4974-8351-6b49732ef2eb", FlavorRef: "1", }).Extract() th.AssertNoErr(t, err) th.CheckDeepEquals(t, ServerDerp, *actual) }
func TestCreateServerWithImageNameAndFlavorName(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() HandleServerCreationSuccessfully(t, SingleServerBody) actual, err := servers.Create(client.ServiceClient(), servers.CreateOpts{ Name: "derp", ImageName: "cirros-0.3.2-x86_64-disk", FlavorName: "m1.tiny", ServiceClient: client.ServiceClient(), }).Extract() th.AssertNoErr(t, err) th.CheckDeepEquals(t, ServerDerp, *actual) }
func TestCreateServerWithUserdataEncoded(t *testing.T) { th.SetupHTTP() defer th.TeardownHTTP() HandleServerCreationWithUserdata(t, SingleServerBody) encoded := base64.StdEncoding.EncodeToString([]byte("userdata string")) actual, err := servers.Create(client.ServiceClient(), servers.CreateOpts{ Name: "derp", ImageRef: "f90f6034-2570-4974-8351-6b49732ef2eb", FlavorRef: "1", UserData: []byte(encoded), }).Extract() th.AssertNoErr(t, err) th.CheckDeepEquals(t, ServerDerp, *actual) }
// 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}, }, Metadata: map[string]string{ "abc": "def", }, 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 }
// 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 }
func resourceComputeInstanceV2Create(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) } var createOpts servers.CreateOptsBuilder // Determines the Image ID using the following rules: // If a bootable block_device was specified, ignore the image altogether. // If an image_id was specified, use it. // If an image_name was specified, look up the image ID, report if error. imageId, err := getImageIDFromConfig(computeClient, d) if err != nil { return err } flavorId, err := getFlavorID(computeClient, d) if err != nil { return err } // determine if block_device configuration is correct // this includes valid combinations and required attributes if err := checkBlockDeviceConfig(d); err != nil { return err } // check if floating IP configuration is correct if err := checkInstanceFloatingIPs(d); err != nil { return err } // Build a list of networks with the information given upon creation. // Error out if an invalid network configuration was used. networkDetails, err := getInstanceNetworks(computeClient, d) if err != nil { return err } networks := make([]servers.Network, len(networkDetails)) for i, net := range networkDetails { networks[i] = servers.Network{ UUID: net["uuid"].(string), Port: net["port"].(string), FixedIP: net["fixed_ip_v4"].(string), } } configDrive := d.Get("config_drive").(bool) createOpts = &servers.CreateOpts{ Name: d.Get("name").(string), ImageRef: imageId, FlavorRef: flavorId, SecurityGroups: resourceInstanceSecGroupsV2(d), AvailabilityZone: d.Get("availability_zone").(string), Networks: networks, Metadata: resourceInstanceMetadataV2(d), ConfigDrive: &configDrive, AdminPass: d.Get("admin_pass").(string), UserData: []byte(d.Get("user_data").(string)), Personality: resourceInstancePersonalityV2(d), } if keyName, ok := d.Get("key_pair").(string); ok && keyName != "" { createOpts = &keypairs.CreateOptsExt{ CreateOptsBuilder: createOpts, KeyName: keyName, } } if vL, ok := d.GetOk("block_device"); ok { blockDevices, err := resourceInstanceBlockDevicesV2(d, vL.([]interface{})) if err != nil { return err } createOpts = &bootfromvolume.CreateOptsExt{ CreateOptsBuilder: createOpts, BlockDevice: blockDevices, } } schedulerHintsRaw := d.Get("scheduler_hints").(*schema.Set).List() if len(schedulerHintsRaw) > 0 { log.Printf("[DEBUG] schedulerhints: %+v", schedulerHintsRaw) schedulerHints := resourceInstanceSchedulerHintsV2(d, schedulerHintsRaw[0].(map[string]interface{})) createOpts = &schedulerhints.CreateOptsExt{ CreateOptsBuilder: createOpts, SchedulerHints: schedulerHints, } } log.Printf("[DEBUG] Create Options: %#v", createOpts) // If a block_device is used, use the bootfromvolume.Create function as it allows an empty ImageRef. // Otherwise, use the normal servers.Create function. var server *servers.Server if _, ok := d.GetOk("block_device"); ok { server, err = bootfromvolume.Create(computeClient, createOpts).Extract() } else { server, err = servers.Create(computeClient, createOpts).Extract() } if err != nil { return fmt.Errorf("Error creating OpenStack server: %s", err) } log.Printf("[INFO] Instance ID: %s", server.ID) // Store the ID now d.SetId(server.ID) // Wait for the instance to become running so we can get some attributes // that aren't available until later. log.Printf( "[DEBUG] Waiting for instance (%s) to become running", server.ID) stateConf := &resource.StateChangeConf{ Pending: []string{"BUILD"}, Target: []string{"ACTIVE"}, Refresh: ServerV2StateRefreshFunc(computeClient, server.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 become ready: %s", server.ID, err) } // Now that the instance has been created, we need to do an early read on the // networks in order to associate floating IPs _, err = getInstanceNetworksAndAddresses(computeClient, d) // If floating IPs were specified, associate them after the instance has launched. err = associateFloatingIPsToInstance(computeClient, d) if err != nil { return err } // if volumes were specified, attach them after the instance has launched. if v, ok := d.GetOk("volume"); ok { vols := v.(*schema.Set).List() if blockClient, err := config.blockStorageV1Client(GetRegion(d)); err != nil { return fmt.Errorf("Error creating OpenStack block storage client: %s", err) } else { if err := attachVolumesToInstance(computeClient, blockClient, d.Id(), vols); err != nil { return err } } } return resourceComputeInstanceV2Read(d, meta) }
// 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 }
func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(Config) flavor := state.Get("flavor_id").(string) 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 } networks := make([]servers.Network, len(s.Networks)) for i, networkUuid := range s.Networks { networks[i].UUID = networkUuid } userData := []byte(s.UserData) if s.UserDataFile != "" { userData, err = ioutil.ReadFile(s.UserDataFile) if err != nil { err = fmt.Errorf("Error reading user data file: %s", err) state.Put("error", err) return multistep.ActionHalt } } ui.Say("Launching server...") serverOpts := servers.CreateOpts{ Name: s.Name, ImageRef: s.SourceImage, ImageName: s.SourceImageName, FlavorRef: flavor, SecurityGroups: s.SecurityGroups, Networks: networks, AvailabilityZone: s.AvailabilityZone, UserData: userData, ConfigDrive: &s.ConfigDrive, ServiceClient: computeClient, } var serverOptsExt servers.CreateOptsBuilder keyName, hasKey := state.GetOk("keyPair") if hasKey { serverOptsExt = keypairs.CreateOptsExt{ CreateOptsBuilder: serverOpts, KeyName: keyName.(string), } } else { serverOptsExt = serverOpts } s.server, err = servers.Create(computeClient, serverOptsExt).Extract() if err != nil { err := fmt.Errorf("Error launching source server: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } ui.Message(fmt.Sprintf("Server ID: %s", s.server.ID)) log.Printf("server id: %s", s.server.ID) ui.Say("Waiting for server to become ready...") stateChange := StateChangeConf{ Pending: []string{"BUILD"}, Target: []string{"ACTIVE"}, Refresh: ServerStateRefreshFunc(computeClient, s.server), StepState: state, } latestServer, err := WaitForState(&stateChange) if err != nil { err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.ID, err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } s.server = latestServer.(*servers.Server) state.Put("server", s.server) return multistep.ActionContinue }