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