func (this *OpenStack) VmCreate(vm *lobster.VirtualMachine, options *lobster.VMIVmCreateOptions) (string, error) { flavorID := vm.Plan.Identification if flavorID == "" { flavorOpts := flavors.ListOpts{ MinDisk: vm.Plan.Storage, MinRAM: vm.Plan.Ram, } flavorPager := flavors.ListDetail(this.ComputeClient, flavorOpts) var matchFlavor *flavors.Flavor err := flavorPager.EachPage(func(page pagination.Page) (bool, error) { flavorList, err := flavors.ExtractFlavors(page) if err != nil { return false, err } for _, flavor := range flavorList { if flavor.Disk == vm.Plan.Storage && flavor.RAM == vm.Plan.Ram && flavor.VCPUs == vm.Plan.Cpu { matchFlavor = &flavor return false, nil } } return true, nil }) if err != nil { return "", err } else if matchFlavor == nil { return "", errors.New("plan not available in this region") } flavorID = matchFlavor.ID } password := utils.Uid(16) opts := servers.CreateOpts{ Name: vm.Name, ImageRef: options.ImageIdentification, FlavorRef: flavorID, Networks: []servers.Network{{UUID: this.networkId}}, AdminPass: password, UserData: []byte("#cloud-config\npassword: "******"\nchpasswd: { expire: False }\nssh_pwauth: True\n"), } createResult := servers.Create(this.ComputeClient, opts) server, err := createResult.Extract() if err != nil { return "", err } // try to associate floating IP with this VM // do asynchronously since it might fail until network port is created go func() { for try := 0; try < 6; try++ { time.Sleep(4 * time.Second) // find a free floating IP var freeFloatingIp *floatingip.FloatingIP err := floatingip.List(this.ComputeClient).EachPage(func(page pagination.Page) (bool, error) { floatingIps, err := floatingip.ExtractFloatingIPs(page) if err != nil { return false, err } for _, floatingIp := range floatingIps { if floatingIp.InstanceID == "" { freeFloatingIp = &floatingIp return false, nil } } return true, nil }) if err != nil { log.Printf("OpenStack: error while looking for free floating IP: %s", err.Error()) continue } else if freeFloatingIp == nil { log.Printf("OpenStack: Did not find free floating IP!") continue } // associate it err = floatingip.Associate(this.ComputeClient, server.ID, freeFloatingIp.IP).ExtractErr() if err == nil { break } else { log.Printf("OpenStack: error while associating floating IP: %s", err.Error()) } } }() vm.SetMetadata("password", password) return server.ID, nil }
func (os *OpenStack) CreateInstance(instance *compute.Instance) (*compute.Instance, error) { imageID, err := common.GetMatchingImageID(os, &instance.Image) if err != nil { return nil, err } flavorID, err := common.GetMatchingFlavorID(os, &instance.Flavor) if err != nil { return nil, err } password := instance.Password if password == "" { password = utils.Uid(16) } opts := servers.CreateOpts{ Name: instance.Name, ImageRef: imageID, FlavorRef: flavorID, AdminPass: password, UserData: []byte("#cloud-config\npassword: "******"\nchpasswd: { expire: False }\nssh_pwauth: True\n"), AvailabilityZone: instance.Region, } if instance.NetworkID != "" { opts.Networks = []servers.Network{{UUID: instance.NetworkID}} } if opts.Name == "" { opts.Name = DEFAULT_NAME } createResult := servers.Create(os.ComputeClient, opts) server, err := createResult.Extract() if err != nil { return nil, err } // try to associate floating IP with this VM // do asynchronously since it might fail until network port is created go func() { for try := 0; try < 6; try++ { time.Sleep(4 * time.Second) // find a free floating IP, or find the IP matching requested IP var freeFloatingIP *floatingip.FloatingIP err := floatingip.List(os.ComputeClient).EachPage(func(page pagination.Page) (bool, error) { floatingIPs, err := floatingip.ExtractFloatingIPs(page) if err != nil { return false, err } for _, floatingIP := range floatingIPs { if floatingIP.InstanceID == "" && (instance.IP == "" || floatingIP.IP == instance.IP) { freeFloatingIP = &floatingIP return false, nil } } return true, nil }) if err != nil { continue } else if freeFloatingIP == nil { continue } // associate it err = floatingip.Associate(os.ComputeClient, server.ID, freeFloatingIP.IP).ExtractErr() if err == nil { break } } }() return &compute.Instance{ ID: server.ID, Name: server.Name, Status: os.mapInstanceStatus(server.Status), Password: password, }, nil }