Пример #1
0
func (do *DigitalOcean) CreateImage(image *compute.Image) (*compute.Image, error) {
	if image.SourceInstance != "" {
		snapshotName := fmt.Sprintf("%s.%s", image.Name, utils.Uid(16))

		err := do.doAction(image.SourceInstance, func(id int) (*godo.Action, *godo.Response, error) {
			return do.client.DropletActions.Snapshot(id, snapshotName)
		})

		if err != nil {
			return nil, err
		} else {
			return &compute.Image{
				ID:             "snapshot:" + snapshotName,
				Name:           snapshotName,
				SourceInstance: image.SourceInstance,
			}, nil
		}
	} else if image.SourceURL != "" {
		return nil, errors.New("fetching image from URL is not supported")
	} else {
		return nil, errors.New("neither source instance nor source URL is set")
	}
}
Пример #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
}
Пример #3
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
}
Пример #4
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
	}
}
Пример #5
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
	}
}
Пример #6
0
func (ln *Linode) CreateInstance(instance *compute.Instance) (*compute.Instance, error) {
	imageID, err := common.GetMatchingImageID(ln, &instance.Image)
	if err != nil {
		return nil, err
	}
	plan, err := ln.findMatchingPlan(&instance.Flavor)
	if err != nil {
		return nil, err
	}
	kernelID, err := ln.findKernel()
	if err != nil {
		return nil, err
	}
	password := instance.Password
	if password == "" {
		password = utils.Uid(16)
	}

	datacenterAbbrev := instance.Region
	if datacenterAbbrev == "" {
		datacenterAbbrev = DEFAULT_DATACENTER
	}
	datacenterID, err := ln.findDatacenter(datacenterAbbrev)
	if err != nil {
		return nil, err
	}

	// create linode
	linodeID, err := ln.client.CreateLinode(datacenterID, plan.ID)
	if err != nil {
		return nil, err
	}

	// create disks
	storage := instance.Flavor.DiskGB
	if storage == 0 {
		storage = DEFAULT_STORAGE
	}

	totalDiskMB := storage * 1024
	swapSize := plan.RAM / 2
	diskSize := totalDiskMB - swapSize

	var diskID int
	imageParts := strings.SplitN(imageID, ":", 2)
	if len(imageParts) != 2 {
		return nil, errors.New("malformed image ID: missing colon")
	}
	if imageParts[0] == "distribution" {
		distributionID, _ := strconv.Atoi(imageParts[1])
		diskID, _, err = ln.client.CreateDiskFromDistribution(linodeID, "cloug", distributionID, diskSize, password, "")
		if err != nil {
			ln.client.DeleteLinode(linodeID, false)
			return nil, err
		}
	} else if imageParts[0] == "image" {
		imageID, _ := strconv.Atoi(imageParts[1])
		diskID, _, err = ln.client.CreateDiskFromImage(linodeID, "cloug", imageID, diskSize, password, "")
		if err != nil {
			ln.client.DeleteLinode(linodeID, false)
			return nil, err
		}
	} else {
		return nil, errors.New("invalid image type " + imageParts[0])
	}

	swapID, _, err := ln.client.CreateDisk(linodeID, "cloug-swap", "swap", swapSize, linode.CreateDiskOptions{})
	if err != nil {
		ln.client.DeleteLinode(linodeID, false)
		return nil, err
	}

	_, err = ln.client.CreateConfig(linodeID, kernelID, "cloug", []int{diskID, swapID}, linode.CreateConfigOptions{})
	if err != nil {
		ln.client.DeleteLinode(linodeID, false)
		return nil, err
	} else {
		ln.client.BootLinode(linodeID)
		return &compute.Instance{
			ID:       strconv.Itoa(linodeID),
			Password: password,
		}, nil
	}
}