github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/alicloud/ecs/step_config_vswitch.go (about) 1 package ecs 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/denverdino/aliyungo/common" 9 "github.com/denverdino/aliyungo/ecs" 10 "github.com/hashicorp/packer/packer" 11 "github.com/mitchellh/multistep" 12 ) 13 14 type stepConfigAlicloudVSwitch struct { 15 VSwitchId string 16 ZoneId string 17 isCreate bool 18 CidrBlock string 19 VSwitchName string 20 } 21 22 func (s *stepConfigAlicloudVSwitch) Run(state multistep.StateBag) multistep.StepAction { 23 client := state.Get("client").(*ecs.Client) 24 ui := state.Get("ui").(packer.Ui) 25 vpcId := state.Get("vpcid").(string) 26 config := state.Get("config").(Config) 27 28 if len(s.VSwitchId) != 0 { 29 vswitchs, _, err := client.DescribeVSwitches(&ecs.DescribeVSwitchesArgs{ 30 VpcId: vpcId, 31 VSwitchId: s.VSwitchId, 32 ZoneId: s.ZoneId, 33 }) 34 if err != nil { 35 ui.Say(fmt.Sprintf("Failed querying vswitch: %s", err)) 36 state.Put("error", err) 37 return multistep.ActionHalt 38 } 39 if len(vswitchs) > 0 { 40 vswitch := vswitchs[0] 41 state.Put("vswitchid", vswitch.VSwitchId) 42 s.isCreate = false 43 return multistep.ActionContinue 44 } 45 s.isCreate = false 46 message := fmt.Sprintf("The specified vswitch {%s} doesn't exist.", s.VSwitchId) 47 state.Put("error", errors.New(message)) 48 ui.Say(message) 49 return multistep.ActionHalt 50 51 } 52 if s.ZoneId == "" { 53 54 zones, err := client.DescribeZones(common.Region(config.AlicloudRegion)) 55 if err != nil { 56 ui.Say(fmt.Sprintf("Query for available zones failed: %s", err)) 57 state.Put("error", err) 58 return multistep.ActionHalt 59 } 60 var instanceTypes []string 61 for _, zone := range zones { 62 isVSwitchSupported := false 63 for _, resourceType := range zone.AvailableResourceCreation.ResourceTypes { 64 if resourceType == ecs.ResourceTypeVSwitch { 65 isVSwitchSupported = true 66 } 67 } 68 if isVSwitchSupported { 69 for _, instanceType := range zone.AvailableInstanceTypes.InstanceTypes { 70 if instanceType == config.InstanceType { 71 s.ZoneId = zone.ZoneId 72 break 73 } 74 instanceTypes = append(instanceTypes, instanceType) 75 } 76 } 77 } 78 79 if s.ZoneId == "" { 80 if len(instanceTypes) > 0 { 81 ui.Say(fmt.Sprintf("The instance type %s isn't available in this region."+ 82 "\n You can either change the instance to one of following: %v \n"+ 83 "or choose another region.", config.InstanceType, instanceTypes)) 84 85 state.Put("error", fmt.Errorf("The instance type %s isn't available in this region."+ 86 "\n You can either change the instance to one of following: %v \n"+ 87 "or choose another region.", config.InstanceType, instanceTypes)) 88 return multistep.ActionHalt 89 } else { 90 ui.Say(fmt.Sprintf("The instance type %s isn't available in this region."+ 91 "\n You can change to other regions.", config.InstanceType)) 92 93 state.Put("error", fmt.Errorf("The instance type %s isn't available in this region."+ 94 "\n You can change to other regions.", config.InstanceType)) 95 return multistep.ActionHalt 96 } 97 } 98 } 99 if config.CidrBlock == "" { 100 s.CidrBlock = "172.16.0.0/24" //use the default CirdBlock 101 } 102 ui.Say("Creating vswitch...") 103 vswitchId, err := client.CreateVSwitch(&ecs.CreateVSwitchArgs{ 104 CidrBlock: s.CidrBlock, 105 ZoneId: s.ZoneId, 106 VpcId: vpcId, 107 VSwitchName: s.VSwitchName, 108 }) 109 if err != nil { 110 state.Put("error", err) 111 ui.Say(fmt.Sprintf("Create vswitch failed %v", err)) 112 return multistep.ActionHalt 113 } 114 if err := client.WaitForVSwitchAvailable(vpcId, s.VSwitchId, ALICLOUD_DEFAULT_TIMEOUT); err != nil { 115 state.Put("error", err) 116 ui.Error(fmt.Sprintf("Timeout waiting for vswitch to become available: %v", err)) 117 return multistep.ActionHalt 118 } 119 state.Put("vswitchid", vswitchId) 120 s.isCreate = true 121 s.VSwitchId = vswitchId 122 return multistep.ActionContinue 123 } 124 125 func (s *stepConfigAlicloudVSwitch) Cleanup(state multistep.StateBag) { 126 if !s.isCreate { 127 return 128 } 129 130 client := state.Get("client").(*ecs.Client) 131 ui := state.Get("ui").(packer.Ui) 132 message(state, "vSwitch") 133 timeoutPoint := time.Now().Add(10 * time.Second) 134 for { 135 if err := client.DeleteVSwitch(s.VSwitchId); err != nil { 136 e, _ := err.(*common.Error) 137 if (e.Code == "IncorrectVSwitchStatus" || e.Code == "DependencyViolation" || 138 e.Code == "DependencyViolation.HaVip" || 139 e.Code == "IncorretRouteEntryStatus") && time.Now().Before(timeoutPoint) { 140 time.Sleep(1 * time.Second) 141 continue 142 } 143 ui.Error(fmt.Sprintf("Error deleting vswitch, it may still be around: %s", err)) 144 return 145 } 146 break 147 } 148 }