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  }