package ecs import ( "context" "fmt" "io/ioutil" "log" "github.com/denverdino/aliyungo/common" "github.com/denverdino/aliyungo/ecs" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) type stepCreateAlicloudInstance struct { IOOptimized bool InstanceType string UserData string UserDataFile string instanceId string RegionId string InternetChargeType string InternetMaxBandwidthOut int InstanceName string ZoneId string instance *ecs.InstanceAttributesType } func (s *stepCreateAlicloudInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { client := state.Get("client").(*ecs.Client) config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) source_image := state.Get("source_image").(*ecs.ImageType) network_type := state.Get("networktype").(InstanceNetWork) securityGroupId := state.Get("securitygroupid").(string) var instanceId string var err error ioOptimized := ecs.IoOptimizedNone if s.IOOptimized { ioOptimized = ecs.IoOptimizedOptimized } password := config.Comm.SSHPassword if password == "" && config.Comm.WinRMPassword != "" { password = config.Comm.WinRMPassword } ui.Say("Creating instance.") if network_type == VpcNet { userData, err := s.getUserData(state) if err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vswitchId := state.Get("vswitchid").(string) instanceId, err = client.CreateInstance(&ecs.CreateInstanceArgs{ RegionId: common.Region(s.RegionId), ImageId: source_image.ImageId, InstanceType: s.InstanceType, InternetChargeType: common.InternetChargeType(s.InternetChargeType), //"PayByTraffic", InternetMaxBandwidthOut: s.InternetMaxBandwidthOut, UserData: userData, IoOptimized: ioOptimized, VSwitchId: vswitchId, SecurityGroupId: securityGroupId, InstanceName: s.InstanceName, Password: password, ZoneId: s.ZoneId, SystemDisk: systemDeviceToDiskType(config.AlicloudImageConfig.ECSSystemDiskMapping), DataDisk: diskDeviceToDiskType(config.AlicloudImageConfig.ECSImagesDiskMappings), }) if err != nil { err := fmt.Errorf("Error creating instance: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } else { if s.InstanceType == "" { s.InstanceType = "PayByTraffic" } if s.InternetMaxBandwidthOut == 0 { s.InternetMaxBandwidthOut = 5 } instanceId, err = client.CreateInstance(&ecs.CreateInstanceArgs{ RegionId: common.Region(s.RegionId), ImageId: source_image.ImageId, InstanceType: s.InstanceType, InternetChargeType: common.InternetChargeType(s.InternetChargeType), //"PayByTraffic", InternetMaxBandwidthOut: s.InternetMaxBandwidthOut, IoOptimized: ioOptimized, SecurityGroupId: securityGroupId, InstanceName: s.InstanceName, Password: password, ZoneId: s.ZoneId, DataDisk: diskDeviceToDiskType(config.AlicloudImageConfig.ECSImagesDiskMappings), }) if err != nil { err := fmt.Errorf("Error creating instance: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } err = client.WaitForInstance(instanceId, ecs.Stopped, ALICLOUD_DEFAULT_TIMEOUT) if err != nil { err := fmt.Errorf("Error creating instance: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } instance, err := client.DescribeInstanceAttribute(instanceId) if err != nil { ui.Say(err.Error()) return multistep.ActionHalt } s.instance = instance state.Put("instance", instance) return multistep.ActionContinue } func (s *stepCreateAlicloudInstance) Cleanup(state multistep.StateBag) { if s.instance == nil { return } message(state, "instance") client := state.Get("client").(*ecs.Client) ui := state.Get("ui").(packer.Ui) err := client.DeleteInstance(s.instance.InstanceId) if err != nil { ui.Say(fmt.Sprintf("Failed to clean up instance %s: %v", s.instance.InstanceId, err.Error())) } } func (s *stepCreateAlicloudInstance) getUserData(state multistep.StateBag) (string, error) { userData := s.UserData if s.UserDataFile != "" { data, err := ioutil.ReadFile(s.UserDataFile) if err != nil { return "", err } userData = string(data) } log.Printf(userData) return userData, nil } func systemDeviceToDiskType(systemDisk AlicloudDiskDevice) ecs.SystemDiskType { return ecs.SystemDiskType{ DiskName: systemDisk.DiskName, Category: ecs.DiskCategory(systemDisk.DiskCategory), Size: systemDisk.DiskSize, Description: systemDisk.Description, } } func diskDeviceToDiskType(diskDevices []AlicloudDiskDevice) []ecs.DataDiskType { result := make([]ecs.DataDiskType, len(diskDevices)) for _, diskDevice := range diskDevices { result = append(result, ecs.DataDiskType{ DiskName: diskDevice.DiskName, Category: ecs.DiskCategory(diskDevice.DiskCategory), Size: diskDevice.DiskSize, SnapshotId: diskDevice.SnapshotId, Description: diskDevice.Description, DeleteWithInstance: diskDevice.DeleteWithInstance, Device: diskDevice.Device, }) } return result }