summaryrefslogtreecommitdiff
path: root/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go
blob: dfa858d0b7137694bf7b2a81f085a45f2424240d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package ecs

import (
	"errors"
	"fmt"
	"time"

	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"github.com/hashicorp/packer/packer"
	"github.com/mitchellh/multistep"
)

type stepConfigAlicloudVSwitch struct {
	VSwitchId   string
	ZoneId      string
	isCreate    bool
	CidrBlock   string
	VSwitchName string
}

func (s *stepConfigAlicloudVSwitch) Run(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 == "IncorretRouteEntryStatus") && 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
	}
}