Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}