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  }