func (aws *RealAWSService) RunInstances(idef *InstancesDefinition) ([]string, error) { count := int64(idef.Count) rs := int64(20) vt := "gp2" rdn := "/dev/xvda" ud, err := encodeUserData(idef.UserData) if err != nil { return []string{}, err } if idef.RootSizeGB != 0 { rs = int64(idef.RootSizeGB) } root := ec2.BlockDeviceMapping{ DeviceName: &rdn, Ebs: &ec2.EbsBlockDevice{ DeleteOnTermination: &True, VolumeSize: &rs, VolumeType: &vt, }, } if idef.EncryptedRoot { root.Ebs.Encrypted = &idef.EncryptedRoot // leave nil otherwise } bdm := []*ec2.BlockDeviceMapping{&root} for _, bd := range idef.BlockDevices { vt := strings.ToLower(bd.Type.String()) nbd := &ec2.BlockDeviceMapping{ DeviceName: &bd.Name, Ebs: &ec2.EbsBlockDevice{ DeleteOnTermination: &bd.DeleteOnTermination, Encrypted: &bd.Encrypted, Iops: &bd.Iops, SnapshotId: &bd.SnapshotID, VolumeSize: &bd.Size, VolumeType: &vt, }, } bdm = append(bdm, nbd) } ri := ec2.RunInstancesInput{ ImageId: &idef.AMI, MinCount: &count, MaxCount: &count, KeyName: &idef.Keypair, InstanceType: &idef.Type, BlockDeviceMappings: bdm, UserData: &ud, } if idef.GetPublicIP { devindx := int64(0) ri.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{&ec2.InstanceNetworkInterfaceSpecification{ AssociatePublicIpAddress: &True, Groups: []*string{&idef.SecurityGroup}, DeviceIndex: &devindx, SubnetId: &idef.Subnet, }} } else { ri.SubnetId = &idef.Subnet ri.SecurityGroupIds = []*string{&idef.SecurityGroup} } r, err := aws.ec2.RunInstances(&ri) if err != nil { return []string{}, err } instances := []string{} for _, inst := range r.Instances { instances = append(instances, *(inst.InstanceId)) } return instances, nil }
func (i *EC2IaaS) buildRunInstancesOptions(params map[string]string) (ec2.RunInstancesInput, error) { result := ec2.RunInstancesInput{ MaxCount: aws.Int64(1), MinCount: aws.Int64(1), } forbiddenFields := []string{ "maxcount", "mincount", "dryrun", "monitoring", } aliases := map[string]string{ "image": "imageid", "type": "instancetype", "securitygroup": "securitygroups", "ebs-optimized": "ebsoptimized", } refType := reflect.TypeOf(result) refValue := reflect.ValueOf(&result) for key, value := range params { field, ok := refType.FieldByNameFunc(func(name string) bool { lowerName := strings.ToLower(name) for _, field := range forbiddenFields { if lowerName == field { return false } } lowerKey := strings.ToLower(key) if aliased, ok := aliases[lowerKey]; ok { lowerKey = aliased } return lowerName == lowerKey }) if !ok { continue } fieldType := field.Type fieldValue := refValue.Elem().FieldByIndex(field.Index) if !fieldValue.IsValid() || !fieldValue.CanSet() { continue } switch fieldType.Kind() { case reflect.Ptr: switch fieldType.Elem().Kind() { case reflect.String: copy := value fieldValue.Set(reflect.ValueOf(©)) case reflect.Int64: intValue, err := strconv.ParseInt(value, 10, 64) if err != nil { return result, &invalidFieldError{ fieldName: key, convertError: err, } } fieldValue.Set(reflect.ValueOf(&intValue)) case reflect.Bool: boolValue, err := strconv.ParseBool(value) if err != nil { return result, &invalidFieldError{ fieldName: key, convertError: err, } } fieldValue.Set(reflect.ValueOf(&boolValue)) case reflect.Struct: err := i.loadStruct(fieldValue, fieldType, []byte(value)) if err != nil { return result, &invalidFieldError{ fieldName: key, convertError: err, } } } case reflect.Slice: switch fieldType.Elem().Elem().Kind() { case reflect.String: parts := strings.Split(value, ",") values := make([]*string, len(parts)) for i, part := range parts { values[i] = aws.String(part) } fieldValue.Set(reflect.ValueOf(values)) case reflect.Struct: var raw []map[string]interface{} err := json.Unmarshal([]byte(value), &raw) if err != nil { return result, &invalidFieldError{ fieldName: key, convertError: err, } } val, err := i.translateSlice(raw, fieldType) if err != nil { return result, &invalidFieldError{ fieldName: key, convertError: err, } } fieldValue.Set(val) } } } // Manual configuration if monitoring, ok := params["monitoring-enabled"]; ok { value, _ := strconv.ParseBool(monitoring) result.Monitoring = &ec2.RunInstancesMonitoringEnabled{ Enabled: aws.Bool(value), } } return result, nil }
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 }