Beispiel #1
0
func (cs *CloudStack) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	if instance.Image.ID == "" {
		return nil, errors.New("instance image ID must be set")
	}

	flavorID, err := common.GetMatchingFlavorID(cs, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	parts := strings.Split(flavorID, "/")
	if len(parts) != 2 {
		return nil, fmt.Errorf("invalid service / disk offering: %s", flavorID)
	}

	opts := api.DeployVirtualMachineOptions{
		ServiceOffering: parts[0],
		DiskOffering:    parts[1],
		Template:        instance.Image.ID,
		Network:         instance.NetworkID,
		Name:            instance.Name,
	}

	id, jobid, err := cs.client.DeployVirtualMachine(&opts)
	if err != nil {
		return nil, err
	}

	return &compute.Instance{
		ID:    id,
		Name:  instance.Name,
		JobID: jobid,
	}, nil
}
Beispiel #2
0
func (do *DigitalOcean) ResizeInstance(instanceID string, flavor *compute.Flavor) error {
	flavorID, err := common.GetMatchingFlavorID(do, flavor)
	if err != nil {
		return err
	}

	return do.doAction(instanceID, func(id int) (*godo.Action, *godo.Response, error) {
		return do.client.DropletActions.Resize(id, flavorID, true)
	})
}
Beispiel #3
0
func (lobster *Lobster) ResizeInstance(instanceID string, flavor *compute.Flavor) error {
	flavorID, err := common.GetMatchingFlavorID(lobster, flavor)
	if err != nil {
		return err
	}
	flavorIDInt, err := strconv.Atoi(flavorID)
	if err != nil {
		return fmt.Errorf("invalid flavor ID: %s", flavorID)
	}

	return lobster.instanceAction(instanceID, func(id int) error {
		return lobster.client.VmResize(id, flavorIDInt)
	})
}
Beispiel #4
0
func (lobster *Lobster) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	if instance.PublicKey.ID == "" && len(instance.PublicKey.Key) > 0 {
		return common.KeypairServiceCreateWrapper(lobster, lobster, instance)
	}

	imageID, err := common.GetMatchingImageID(lobster, &instance.Image)
	if err != nil {
		return nil, err
	}
	flavorID, err := common.GetMatchingFlavorID(lobster, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	imageIDInt, err := strconv.Atoi(imageID)
	if err != nil {
		return nil, fmt.Errorf("invalid image ID: %s", imageID)
	}
	flavorIDInt, err := strconv.Atoi(flavorID)
	if err != nil {
		return nil, fmt.Errorf("invalid flavor ID: %s", flavorID)
	}

	name := instance.Name
	if name == "" {
		name = DEFAULT_NAME
	}

	var clientOptions api.VmCreateOptions
	if instance.PublicKey.ID != "" {
		clientOptions.KeyId, err = strconv.Atoi(instance.PublicKey.ID)
		if err != nil {
			return nil, fmt.Errorf("invalid key ID: %s", instance.PublicKey.ID)
		}
	}

	vmID, err := lobster.client.VmCreate(name, flavorIDInt, imageIDInt, &clientOptions)
	if err != nil {
		return nil, err
	} else {
		return &compute.Instance{
			ID: strconv.Itoa(vmID),
		}, nil
	}
}
Beispiel #5
0
func (ln *Linode) findMatchingPlan(flavor *compute.Flavor) (*linode.Plan, error) {
	flavorID, err := common.GetMatchingFlavorID(ln, flavor)
	if err != nil {
		return nil, err
	}
	planID, err := strconv.Atoi(flavorID)
	if err != nil {
		return nil, fmt.Errorf("invalid flavor ID %s", flavorID)
	}
	plans, err := ln.client.ListPlans()
	if err != nil {
		return nil, fmt.Errorf("failed to list plans")
	}
	for _, plan := range plans {
		if plan.ID == planID {
			return plan, nil
		}
	}
	return nil, fmt.Errorf("could not find plan with id=%d", planID)
}
Beispiel #6
0
func (ln *LunaNode) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	imageID, err := common.GetMatchingImageID(ln, &instance.Image)
	if err != nil {
		return nil, err
	}
	flavorID, err := common.GetMatchingFlavorID(ln, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	imageIDInt, err := strconv.Atoi(imageID)
	if err != nil {
		return nil, fmt.Errorf("invalid image ID: %s", imageID)
	}
	flavorIDInt, err := strconv.Atoi(flavorID)
	if err != nil {
		return nil, fmt.Errorf("invalid flavor ID: %s", flavorID)
	}

	region := instance.Region
	if region == "" {
		region = DEFAULT_REGION
	}

	name := instance.Name
	if name == "" {
		name = DEFAULT_NAME
	}

	vmId, err := ln.api.VmCreateImage(region, name, flavorIDInt, imageIDInt)
	if err != nil {
		return nil, err
	} else {
		return &compute.Instance{
			ID: fmt.Sprintf("%d", vmId),
		}, nil
	}
}
Beispiel #7
0
func (vt *Vultr) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	if instance.PublicKey.ID == "" && len(instance.PublicKey.Key) > 0 {
		return common.KeypairServiceCreateWrapper(vt, vt, instance)
	}

	imageID, err := common.GetMatchingImageID(vt, &instance.Image)
	if err != nil {
		return nil, err
	}
	flavorID, err := common.GetMatchingFlavorID(vt, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	flavorIDInt, err := strconv.Atoi(flavorID)
	if err != nil {
		return nil, fmt.Errorf("invalid flavor ID: %s", flavorID)
	}

	name := instance.Name
	if name == "" {
		name = DEFAULT_NAME
	}

	serverOptions := &vultr.ServerOptions{
		PrivateNetworking:    instance.Detail("private_networking", "yes") == "yes",
		IPV6:                 instance.Detail("ipv6", "yes") == "yes",
		AutoBackups:          instance.Detail("auto_backups", "no") == "yes",
		DontNotifyOnActivate: instance.Detail("dont_notify_on_activate", "no") == "yes",
	}

	imageParts := strings.SplitN(imageID, ":", 2)
	if len(imageParts) != 2 {
		return nil, fmt.Errorf("malformed image ID: missing colon")
	}
	if imageParts[0] == "iso" {
		customOSID, err := vt.findOSByName("Custom")
		if err != nil {
			return nil, fmt.Errorf("failed to get custom OS for creation from ISO: %v", err)
		}
		serverOptions.OS = customOSID
		serverOptions.ISO, _ = strconv.Atoi(imageParts[1])
	} else if imageParts[0] == "os" {
		serverOptions.OS, _ = strconv.Atoi(imageParts[1])
	} else if imageParts[0] == "snapshot" {
		snapshotOSID, err := vt.findOSByName("Snapshot")
		if err != nil {
			return nil, fmt.Errorf("failed to get snapshot OS for creation from snapshot: %v", err)
		}
		serverOptions.OS = snapshotOSID
		serverOptions.Snapshot = imageParts[1]
	} else if imageParts[0] == "app" {
		appOSID, err := vt.findOSByName("Application")
		if err != nil {
			return nil, fmt.Errorf("failed to get application OS for creation from application: %v", err)
		}
		serverOptions.OS = appOSID
		serverOptions.Application, _ = strconv.Atoi(imageParts[1])
	} else {
		return nil, fmt.Errorf("invalid image type " + imageParts[0])
	}

	if instance.PublicKey.ID != "" {
		serverOptions.SSHKey = instance.PublicKey.ID
	}

	region := DEFAULT_REGION
	if instance.Region != "" {
		region = instance.Region
	}
	regionID, err := vt.findRegion(region)
	if err != nil {
		return nil, fmt.Errorf("failed to identify region ID: %v", err)
	}

	server, err := vt.client.CreateServer(name, regionID, flavorIDInt, serverOptions)
	if err != nil {
		return nil, err
	} else {
		return &compute.Instance{
			ID: server.ID,
		}, nil
	}
}
Beispiel #8
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
}
Beispiel #9
0
func (e *EC2) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	imageID, err := common.GetMatchingImageID(e, &instance.Image)
	if err != nil {
		return nil, err
	}
	flavorID, err := common.GetMatchingFlavorID(e, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	region := DEFAULT_REGION
	if instance.Region != "" {
		region = instance.Region
	}
	svc := e.getService(region)

	opts := ec2.RunInstancesInput{
		ImageId:      aws.String(imageID),
		InstanceType: aws.String(flavorID),
		MinCount:     aws.Int64(1),
		MaxCount:     aws.Int64(1),
	}

	password := instance.Password
	if password == "" {
		password = utils.Uid(16)
	}
	userData := "#cloud-config\npassword: "******"\nchpasswd: { expire: False }\nssh_pwauth: True\n"
	opts.UserData = aws.String(base64.StdEncoding.EncodeToString([]byte(userData)))

	if instance.Flavor.DiskGB > 0 {
		opts.BlockDeviceMappings = []*ec2.BlockDeviceMapping{
			{
				Ebs: &ec2.EbsBlockDevice{
					VolumeSize:          aws.Int64(int64(instance.Flavor.DiskGB)),
					DeleteOnTermination: aws.Bool(true),
					VolumeType:          aws.String("gp2"),
				},
			},
		}
	}

	if len(instance.PublicKey.Key) > 0 {
		keyName := utils.Uid(8)
		_, err := svc.ImportKeyPair(&ec2.ImportKeyPairInput{
			KeyName:           aws.String(keyName),
			PublicKeyMaterial: instance.PublicKey.Key,
		})
		if err != nil {
			return nil, fmt.Errorf("failed to import public key: %v", err)
		}
		defer svc.DeleteKeyPair(&ec2.DeleteKeyPairInput{
			KeyName: aws.String(keyName),
		})
		opts.KeyName = aws.String(keyName)
	}

	res, err := svc.RunInstances(&opts)
	if err != nil {
		return nil, err
	} else if len(res.Instances) != 1 {
		return nil, fmt.Errorf("attempted to provision a single instance, but reservation contains %d instances", len(res.Instances))
	}
	resInstance := res.Instances[0]

	return &compute.Instance{
		ID:       encodeID(String(resInstance.InstanceId), region),
		Status:   e.mapInstanceStatus(String(resInstance.State.Name)),
		Password: password,
	}, nil
}
Beispiel #10
0
func (gc *GoogleCompute) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	imageID, err := common.GetMatchingImageID(gc, &instance.Image)
	if err != nil {
		return nil, err
	}
	flavorID, err := common.GetMatchingFlavorID(gc, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	name := utils.UidAlphabet(24, []rune("abcdefghijklmnopqrstuvwxyz"))

	region := instance.Region
	if region == "" {
		region = DEFAULT_REGION
	}

	apiInstance := gcompute.Instance{
		Name:        name,
		MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", region, flavorID),
		Disks: []*gcompute.AttachedDisk{
			&gcompute.AttachedDisk{
				AutoDelete: true,
				Boot:       true,
				Type:       "PERSISTENT",
				InitializeParams: &gcompute.AttachedDiskInitializeParams{
					SourceImage: imageID,
					DiskSizeGb:  int64(instance.Flavor.DiskGB),
				},
			},
		},
		NetworkInterfaces: []*gcompute.NetworkInterface{
			&gcompute.NetworkInterface{
				Network: "global/networks/default",
				AccessConfigs: []*gcompute.AccessConfig{
					&gcompute.AccessConfig{
						Type: "ONE_TO_ONE_NAT",
						Name: "External NAT",
					},
				},
			},
		},
	}

	password := instance.Password
	if password == "" {
		password = utils.Uid(16)
	}
	userData := "#cloud-config\npassword: "******"\nchpasswd: { expire: False }\nssh_pwauth: True\n"
	apiInstance.Metadata = &gcompute.Metadata{
		Items: []*gcompute.MetadataItems{
			&gcompute.MetadataItems{
				Key:   "user-data",
				Value: &userData,
			},
		},
	}

	operation, err := gc.waitForOperation(gc.service.Instances.Insert(gc.project, region, &apiInstance))
	if err != nil {
		return nil, err
	} else {
		return &compute.Instance{
			ID:       fmt.Sprintf("%s:%s", basename(operation.Zone), name),
			Password: password,
		}, nil
	}
}
Beispiel #11
0
func (do *DigitalOcean) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	if instance.PublicKey.ID == "" && len(instance.PublicKey.Key) > 0 {
		return common.KeypairServiceCreateWrapper(do, do, instance)
	}

	imageID, err := do.imageID(&instance.Image)
	if err != nil {
		return nil, err
	}

	flavorID, err := common.GetMatchingFlavorID(do, &instance.Flavor)
	if err != nil {
		return nil, err
	}

	password := instance.Password
	if password == "" {
		password = utils.Uid(16)
	}

	createRequest := &godo.DropletCreateRequest{
		Name:   instance.Name,
		Region: instance.Region,
		Size:   flavorID,
		Image: godo.DropletCreateImage{
			ID: imageID,
		},
		IPv6:              true,
		PrivateNetworking: true,
		UserData:          fmt.Sprintf("#cloud-config\nchpasswd:\n list: |\n  root:%s\n expire: False\n", password),
	}

	if createRequest.Name == "" {
		createRequest.Name = DEFAULT_NAME
	}

	if createRequest.Region == "" {
		createRequest.Region = DEFAULT_REGION
	}

	if instance.PublicKey.ID != "" {
		keyID, err := strconv.Atoi(instance.PublicKey.ID)
		if err != nil {
			return nil, fmt.Errorf("invalid key ID")
		}
		createRequest.SSHKeys = []godo.DropletCreateSSHKey{godo.DropletCreateSSHKey{
			ID: keyID,
		}}
	}

	droplet, _, err := do.client.Droplets.Create(createRequest)

	if err != nil {
		return nil, err
	} else {
		return &compute.Instance{
			ID:       fmt.Sprintf("%d", droplet.ID),
			Name:     droplet.Name,
			Status:   do.mapInstanceStatus(droplet.Status),
			Username: "******",
			Password: password,
		}, nil
	}
}