150 lines
4.4 KiB
Go
150 lines
4.4 KiB
Go
package ecs
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/denverdino/aliyungo/common"
|
|
"github.com/denverdino/aliyungo/ecs"
|
|
"github.com/hashicorp/packer/helper/multistep"
|
|
"github.com/hashicorp/packer/packer"
|
|
)
|
|
|
|
type stepConfigAlicloudVSwitch struct {
|
|
VSwitchId string
|
|
ZoneId string
|
|
isCreate bool
|
|
CidrBlock string
|
|
VSwitchName string
|
|
}
|
|
|
|
func (s *stepConfigAlicloudVSwitch) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
|
client := state.Get("client").(*ecs.Client)
|
|
ui := state.Get("ui").(packer.Ui)
|
|
vpcId := state.Get("vpcid").(string)
|
|
config := state.Get("config").(Config)
|
|
|
|
if len(s.VSwitchId) != 0 {
|
|
vswitchs, _, err := client.DescribeVSwitches(&ecs.DescribeVSwitchesArgs{
|
|
VpcId: vpcId,
|
|
VSwitchId: s.VSwitchId,
|
|
ZoneId: s.ZoneId,
|
|
})
|
|
if err != nil {
|
|
ui.Say(fmt.Sprintf("Failed querying vswitch: %s", err))
|
|
state.Put("error", err)
|
|
return multistep.ActionHalt
|
|
}
|
|
if len(vswitchs) > 0 {
|
|
vswitch := vswitchs[0]
|
|
state.Put("vswitchid", vswitch.VSwitchId)
|
|
s.isCreate = false
|
|
return multistep.ActionContinue
|
|
}
|
|
s.isCreate = false
|
|
message := fmt.Sprintf("The specified vswitch {%s} doesn't exist.", s.VSwitchId)
|
|
state.Put("error", errors.New(message))
|
|
ui.Say(message)
|
|
return multistep.ActionHalt
|
|
|
|
}
|
|
if s.ZoneId == "" {
|
|
|
|
zones, err := client.DescribeZones(common.Region(config.AlicloudRegion))
|
|
if err != nil {
|
|
ui.Say(fmt.Sprintf("Query for available zones failed: %s", err))
|
|
state.Put("error", err)
|
|
return multistep.ActionHalt
|
|
}
|
|
var instanceTypes []string
|
|
for _, zone := range zones {
|
|
isVSwitchSupported := false
|
|
for _, resourceType := range zone.AvailableResourceCreation.ResourceTypes {
|
|
if resourceType == ecs.ResourceTypeVSwitch {
|
|
isVSwitchSupported = true
|
|
}
|
|
}
|
|
if isVSwitchSupported {
|
|
for _, instanceType := range zone.AvailableInstanceTypes.InstanceTypes {
|
|
if instanceType == config.InstanceType {
|
|
s.ZoneId = zone.ZoneId
|
|
break
|
|
}
|
|
instanceTypes = append(instanceTypes, instanceType)
|
|
}
|
|
}
|
|
}
|
|
|
|
if s.ZoneId == "" {
|
|
if len(instanceTypes) > 0 {
|
|
ui.Say(fmt.Sprintf("The instance type %s isn't available in this region."+
|
|
"\n You can either change the instance to one of following: %v \n"+
|
|
"or choose another region.", config.InstanceType, instanceTypes))
|
|
|
|
state.Put("error", fmt.Errorf("The instance type %s isn't available in this region."+
|
|
"\n You can either change the instance to one of following: %v \n"+
|
|
"or choose another region.", config.InstanceType, instanceTypes))
|
|
return multistep.ActionHalt
|
|
} else {
|
|
ui.Say(fmt.Sprintf("The instance type %s isn't available in this region."+
|
|
"\n You can change to other regions.", config.InstanceType))
|
|
|
|
state.Put("error", fmt.Errorf("The instance type %s isn't available in this region."+
|
|
"\n You can change to other regions.", config.InstanceType))
|
|
return multistep.ActionHalt
|
|
}
|
|
}
|
|
}
|
|
if config.CidrBlock == "" {
|
|
s.CidrBlock = "172.16.0.0/24" //use the default CirdBlock
|
|
}
|
|
ui.Say("Creating vswitch...")
|
|
vswitchId, err := client.CreateVSwitch(&ecs.CreateVSwitchArgs{
|
|
CidrBlock: s.CidrBlock,
|
|
ZoneId: s.ZoneId,
|
|
VpcId: vpcId,
|
|
VSwitchName: s.VSwitchName,
|
|
})
|
|
if err != nil {
|
|
state.Put("error", err)
|
|
ui.Say(fmt.Sprintf("Create vswitch failed %v", err))
|
|
return multistep.ActionHalt
|
|
}
|
|
if err := client.WaitForVSwitchAvailable(vpcId, s.VSwitchId, ALICLOUD_DEFAULT_TIMEOUT); err != nil {
|
|
state.Put("error", err)
|
|
ui.Error(fmt.Sprintf("Timeout waiting for vswitch to become available: %v", err))
|
|
return multistep.ActionHalt
|
|
}
|
|
state.Put("vswitchid", vswitchId)
|
|
s.isCreate = true
|
|
s.VSwitchId = vswitchId
|
|
return multistep.ActionContinue
|
|
}
|
|
|
|
func (s *stepConfigAlicloudVSwitch) Cleanup(state multistep.StateBag) {
|
|
if !s.isCreate {
|
|
return
|
|
}
|
|
|
|
client := state.Get("client").(*ecs.Client)
|
|
ui := state.Get("ui").(packer.Ui)
|
|
message(state, "vSwitch")
|
|
timeoutPoint := time.Now().Add(10 * time.Second)
|
|
for {
|
|
if err := client.DeleteVSwitch(s.VSwitchId); err != nil {
|
|
e, _ := err.(*common.Error)
|
|
if (e.Code == "IncorrectVSwitchStatus" || e.Code == "DependencyViolation" ||
|
|
e.Code == "DependencyViolation.HaVip" ||
|
|
e.Code == "IncorrectRouteEntryStatus") && time.Now().Before(timeoutPoint) {
|
|
time.Sleep(1 * time.Second)
|
|
continue
|
|
}
|
|
ui.Error(fmt.Sprintf("Error deleting vswitch, it may still be around: %s", err))
|
|
return
|
|
}
|
|
break
|
|
}
|
|
}
|