vagrant-vcloudair 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.rubocop.yml +34 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +109 -0
- data/lib/vagrant-vcloudair.rb +63 -0
- data/lib/vagrant-vcloudair/action.rb +298 -0
- data/lib/vagrant-vcloudair/action/announce_ssh_exec.rb +22 -0
- data/lib/vagrant-vcloudair/action/build_vapp.rb +235 -0
- data/lib/vagrant-vcloudair/action/connect_vcloud.rb +54 -0
- data/lib/vagrant-vcloudair/action/destroy_vapp.rb +54 -0
- data/lib/vagrant-vcloudair/action/destroy_vm.rb +37 -0
- data/lib/vagrant-vcloudair/action/disconnect_vcloud.rb +31 -0
- data/lib/vagrant-vcloudair/action/forward_ports.rb +132 -0
- data/lib/vagrant-vcloudair/action/handle_nat_port_collisions.rb +153 -0
- data/lib/vagrant-vcloudair/action/inventory_check.rb +210 -0
- data/lib/vagrant-vcloudair/action/is_bridged.rb +29 -0
- data/lib/vagrant-vcloudair/action/is_created.rb +35 -0
- data/lib/vagrant-vcloudair/action/is_last_vm.rb +31 -0
- data/lib/vagrant-vcloudair/action/is_paused.rb +20 -0
- data/lib/vagrant-vcloudair/action/is_running.rb +20 -0
- data/lib/vagrant-vcloudair/action/message_already_running.rb +16 -0
- data/lib/vagrant-vcloudair/action/message_cannot_suspend.rb +16 -0
- data/lib/vagrant-vcloudair/action/message_not_created.rb +16 -0
- data/lib/vagrant-vcloudair/action/message_not_running.rb +16 -0
- data/lib/vagrant-vcloudair/action/message_will_not_destroy.rb +21 -0
- data/lib/vagrant-vcloudair/action/power_off.rb +33 -0
- data/lib/vagrant-vcloudair/action/power_off_vapp.rb +40 -0
- data/lib/vagrant-vcloudair/action/power_on.rb +39 -0
- data/lib/vagrant-vcloudair/action/read_ssh_info.rb +153 -0
- data/lib/vagrant-vcloudair/action/read_state.rb +51 -0
- data/lib/vagrant-vcloudair/action/resume.rb +25 -0
- data/lib/vagrant-vcloudair/action/suspend.rb +25 -0
- data/lib/vagrant-vcloudair/action/unmap_port_forwardings.rb +74 -0
- data/lib/vagrant-vcloudair/cap/forwarded_ports.rb +38 -0
- data/lib/vagrant-vcloudair/cap/public_address.rb +18 -0
- data/lib/vagrant-vcloudair/cap/rdp_info.rb +18 -0
- data/lib/vagrant-vcloudair/cap/winrm_info.rb +15 -0
- data/lib/vagrant-vcloudair/command.rb +285 -0
- data/lib/vagrant-vcloudair/config.rb +205 -0
- data/lib/vagrant-vcloudair/driver/base.rb +643 -0
- data/lib/vagrant-vcloudair/driver/meta.rb +202 -0
- data/lib/vagrant-vcloudair/driver/version_5_1.rb +2019 -0
- data/lib/vagrant-vcloudair/errors.rb +77 -0
- data/lib/vagrant-vcloudair/model/forwarded_port.rb +66 -0
- data/lib/vagrant-vcloudair/plugin.rb +111 -0
- data/lib/vagrant-vcloudair/provider.rb +41 -0
- data/lib/vagrant-vcloudair/util/compile_forwarded_ports.rb +34 -0
- data/lib/vagrant-vcloudair/version.rb +5 -0
- data/locales/en.yml +169 -0
- data/vagrant-vcloudair.gemspec +33 -0
- metadata +266 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VCloudAir
|
5
|
+
module Action
|
6
|
+
# This middleware class will detect and handle collisions with
|
7
|
+
# forwarded ports, whether that means raising an error or repairing
|
8
|
+
# them automatically.
|
9
|
+
#
|
10
|
+
# Parameters it takes from the environment hash:
|
11
|
+
#
|
12
|
+
# * `:port_collision_repair` - If true, it will attempt to repair
|
13
|
+
# port collisions. If false, it will raise an exception when
|
14
|
+
# there is a collision.
|
15
|
+
#
|
16
|
+
# * `:port_collision_extra_in_use` - An array of ports that are
|
17
|
+
# considered in use.
|
18
|
+
#
|
19
|
+
# * `:port_collision_remap` - A hash remapping certain host ports
|
20
|
+
# to other host ports.
|
21
|
+
#
|
22
|
+
class HandleNATPortCollisions
|
23
|
+
def initialize(app, env)
|
24
|
+
@app = app
|
25
|
+
@logger = Log4r::Logger.new(
|
26
|
+
'vagrant_vcloudair::action::handle_port_collisions'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
@logger.info('Detecting any forwarded port collisions...')
|
32
|
+
|
33
|
+
# Determine a list of usable ports for repair
|
34
|
+
usable_ports = Set.new(env[:machine].config.vm.usable_port_range)
|
35
|
+
|
36
|
+
# Pass one, remove all defined host ports from usable ports
|
37
|
+
with_forwarded_ports(env) do |options|
|
38
|
+
usable_ports.delete(options[:host])
|
39
|
+
end
|
40
|
+
|
41
|
+
cfg = env[:machine].provider_config
|
42
|
+
cnx = cfg.vcloudair_cnx.driver
|
43
|
+
vapp_id = env[:machine].get_vapp_id
|
44
|
+
|
45
|
+
@logger.debug('Getting VM info...')
|
46
|
+
vm_name = env[:machine].name
|
47
|
+
vm = cnx.get_vapp(vapp_id)
|
48
|
+
vm_info = vm[:vms_hash][vm_name.to_sym]
|
49
|
+
|
50
|
+
vapp_edge_ip = cnx.get_vapp_edge_public_ip(vapp_id)
|
51
|
+
|
52
|
+
@logger.debug('Getting edge gateway port forwarding rules...')
|
53
|
+
edge_gateway_rules = cnx.get_edge_gateway_rules(cfg.vdc_edge_gateway,
|
54
|
+
cfg.vdc_id)
|
55
|
+
edge_dnat_rules = edge_gateway_rules.select {|r| (r[:rule_type] == 'DNAT' && r[:translated_ip] != vapp_edge_ip)}
|
56
|
+
edge_ports_in_use = edge_dnat_rules.map{|r| r[:original_port].to_i}.to_set
|
57
|
+
|
58
|
+
@logger.debug('Getting port forwarding rules...')
|
59
|
+
vapp_nat_rules = cnx.get_vapp_port_forwarding_rules(vapp_id)
|
60
|
+
ports_in_use = vapp_nat_rules.map{|r| r[:nat_external_port].to_i}.to_set
|
61
|
+
|
62
|
+
# merge the vapp ports and the edge gateway ports together, all are in use
|
63
|
+
ports_in_use = ports_in_use | edge_ports_in_use
|
64
|
+
|
65
|
+
# Pass two, detect/handle any collisions
|
66
|
+
with_forwarded_ports(env) do |options|
|
67
|
+
guest_port = options[:guest]
|
68
|
+
host_port = options[:host]
|
69
|
+
|
70
|
+
# Find if there already is a NAT rule to guest_port of this VM
|
71
|
+
if r = vapp_nat_rules.find { |rule| (rule[:vapp_scoped_local_id] == vm_info[:vapp_scoped_local_id] &&
|
72
|
+
rule[:nat_internal_port] == guest_port.to_s) }
|
73
|
+
host_port = r[:nat_external_port].to_i
|
74
|
+
@logger.info(
|
75
|
+
"Found existing port forwarding rule #{host_port} to #{guest_port}"
|
76
|
+
)
|
77
|
+
options[:host] = host_port
|
78
|
+
options[:already_exists] = true
|
79
|
+
else
|
80
|
+
# If the port is open (listening for TCP connections)
|
81
|
+
if ports_in_use.include?(host_port)
|
82
|
+
unless options[:auto_correct]
|
83
|
+
fail Errors::ForwardPortCollision,
|
84
|
+
:guest_port => guest_port.to_s,
|
85
|
+
:host_port => host_port.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
@logger.info("Attempting to repair FP collision: #{host_port}")
|
89
|
+
|
90
|
+
repaired_port = nil
|
91
|
+
until usable_ports.empty?
|
92
|
+
# Attempt to repair the forwarded port
|
93
|
+
repaired_port = usable_ports.to_a.sort[0]
|
94
|
+
usable_ports.delete(repaired_port)
|
95
|
+
|
96
|
+
# If the port is in use, then we can't use this either...
|
97
|
+
if ports_in_use.include?(repaired_port)
|
98
|
+
@logger.info(
|
99
|
+
"Repaired port also in use: #{repaired_port}." +
|
100
|
+
'Trying another...'
|
101
|
+
)
|
102
|
+
next
|
103
|
+
end
|
104
|
+
|
105
|
+
# We have a port so break out
|
106
|
+
break
|
107
|
+
end
|
108
|
+
|
109
|
+
# If we have no usable ports then we can't repair
|
110
|
+
if !repaired_port && usable_ports.empty?
|
111
|
+
fail Errors::ForwardPortAutolistEmpty,
|
112
|
+
:vm_name => env[:machine].name,
|
113
|
+
:guest_port => guest_port.to_s,
|
114
|
+
:host_port => host_port.to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
# Modify the args in place
|
118
|
+
options[:host] = repaired_port
|
119
|
+
|
120
|
+
@logger.info(
|
121
|
+
"Repaired FP collision: #{host_port} to #{repaired_port}"
|
122
|
+
)
|
123
|
+
|
124
|
+
# Notify the user
|
125
|
+
env[:ui].info(
|
126
|
+
I18n.t(
|
127
|
+
'vagrant.actions.vm.forward_ports.fixed_collision',
|
128
|
+
:host_port => host_port.to_s,
|
129
|
+
:guest_port => guest_port.to_s,
|
130
|
+
:new_port => repaired_port.to_s
|
131
|
+
)
|
132
|
+
)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
@app.call(env)
|
138
|
+
end
|
139
|
+
|
140
|
+
protected
|
141
|
+
|
142
|
+
def with_forwarded_ports(env)
|
143
|
+
env[:machine].config.vm.networks.each do |type, options|
|
144
|
+
# Ignore anything but forwarded ports
|
145
|
+
next if type != :forwarded_port
|
146
|
+
|
147
|
+
yield options
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'etc'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VCloudAir
|
5
|
+
module Action
|
6
|
+
class InventoryCheck
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_vcloudair::action::inventory_check')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
vcloud_check_inventory(env)
|
14
|
+
|
15
|
+
@app.call env
|
16
|
+
end
|
17
|
+
|
18
|
+
def vcloud_upload_box(env)
|
19
|
+
cfg = env[:machine].provider_config
|
20
|
+
cnx = cfg.vcloudair_cnx.driver
|
21
|
+
|
22
|
+
box_dir = env[:machine].box.directory.to_s
|
23
|
+
|
24
|
+
if env[:machine].box.name.to_s.include? '/'
|
25
|
+
box_file = env[:machine].box.name.rpartition('/').last.to_s
|
26
|
+
box_name = env[:machine].box.name.to_s
|
27
|
+
else
|
28
|
+
box_file = env[:machine].box.name.to_s
|
29
|
+
box_name = box_file
|
30
|
+
end
|
31
|
+
|
32
|
+
box_ovf = "#{box_dir}/#{box_file}.ovf"
|
33
|
+
|
34
|
+
# Still relying on ruby-progressbar because report_progress
|
35
|
+
# basically sucks.
|
36
|
+
@logger.debug("OVF File: #{box_ovf}")
|
37
|
+
upload_ovf = cnx.upload_ovf(
|
38
|
+
cfg.vdc_id,
|
39
|
+
box_name,
|
40
|
+
'Vagrant Box',
|
41
|
+
box_ovf,
|
42
|
+
cfg.catalog_id,
|
43
|
+
{
|
44
|
+
:progressbar_enable => true,
|
45
|
+
# Set the chunksize for upload at the configured value or default
|
46
|
+
# to 5M
|
47
|
+
:chunksize => (cfg.upload_chunksize || 5_242_880)
|
48
|
+
}
|
49
|
+
)
|
50
|
+
|
51
|
+
env[:ui].info(I18n.t('vagrant_vcloudair.catalog.add_to_catalog',
|
52
|
+
box_name: box_name,
|
53
|
+
catalog_name: cfg.catalog_name))
|
54
|
+
|
55
|
+
add_ovf_to_catalog = cnx.wait_task_completion(upload_ovf)
|
56
|
+
|
57
|
+
unless add_ovf_to_catalog[:errormsg].nil?
|
58
|
+
fail Errors::CatalogAddError,
|
59
|
+
:message => add_ovf_to_catalog[:errormsg]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Retrieve catalog_item ID
|
63
|
+
cfg.catalog_item = cnx.get_catalog_item_by_name(
|
64
|
+
cfg.catalog_id,
|
65
|
+
box_name
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def vcloud_create_catalog(env)
|
70
|
+
cfg = env[:machine].provider_config
|
71
|
+
cnx = cfg.vcloudair_cnx.driver
|
72
|
+
|
73
|
+
catalog_creation = cnx.create_catalog(
|
74
|
+
cfg.org_id,
|
75
|
+
cfg.catalog_name,
|
76
|
+
"Created by #{Etc.getlogin} " +
|
77
|
+
"running on #{Socket.gethostname.downcase} " +
|
78
|
+
"using vagrant-vcloudair on #{Time.now.strftime("%B %d, %Y")}"
|
79
|
+
)
|
80
|
+
cnx.wait_task_completion(catalog_creation[:task_id])
|
81
|
+
|
82
|
+
@logger.debug("Catalog Creation result: #{catalog_creation.inspect}")
|
83
|
+
env[:ui].info(I18n.t('vagrant_vcloudair.catalog.create_catalog',
|
84
|
+
catalog_name: cfg.catalog_name))
|
85
|
+
|
86
|
+
cfg.catalog_id = catalog_creation[:catalog_id]
|
87
|
+
end
|
88
|
+
|
89
|
+
def vcloud_check_inventory(env)
|
90
|
+
# Will check each mandatory config value against the vCloud Air
|
91
|
+
# Instance and will setup the global environment config values
|
92
|
+
cfg = env[:machine].provider_config
|
93
|
+
cnx = cfg.vcloudair_cnx.driver
|
94
|
+
|
95
|
+
if env[:machine].box.name.to_s.include? '/'
|
96
|
+
box_file = env[:machine].box.name.rpartition('/').last.to_s
|
97
|
+
box_name = env[:machine].box.name.to_s
|
98
|
+
else
|
99
|
+
box_file = env[:machine].box.name.to_s
|
100
|
+
box_name = box_file
|
101
|
+
end
|
102
|
+
|
103
|
+
cfg.org = cnx.get_organization_by_name(cfg.vdc_name)
|
104
|
+
@logger.debug("cfg.org: #{cfg.org}")
|
105
|
+
cfg.org_id = cnx.get_organization_id_by_name(cfg.vdc_name)
|
106
|
+
@logger.debug("cfg.org_id: #{cfg.org_id}")
|
107
|
+
|
108
|
+
cfg.vdc = cnx.get_vdc_by_name(cfg.org, cfg.vdc_name)
|
109
|
+
cfg.vdc_id = cnx.get_vdc_id_by_name(cfg.org, cfg.vdc_name)
|
110
|
+
|
111
|
+
cfg.catalog = cnx.get_catalog_by_name(cfg.org, cfg.catalog_name)
|
112
|
+
cfg.catalog_id = cnx.get_catalog_id_by_name(cfg.org, cfg.catalog_name)
|
113
|
+
|
114
|
+
if cfg.catalog_id.nil?
|
115
|
+
env[:ui].warn(I18n.t(
|
116
|
+
'vagrant_vcloudair.catalog.nonexistant_catalog',
|
117
|
+
catalog_name: cfg.catalog_name))
|
118
|
+
|
119
|
+
user_input = env[:ui].ask(
|
120
|
+
I18n.t('vagrant_vcloudair.catalog.create_catalog_ask',
|
121
|
+
catalog_name: cfg.catalog_name) + ' '
|
122
|
+
)
|
123
|
+
|
124
|
+
if user_input.downcase == 'yes' || user_input.downcase == 'y'
|
125
|
+
vcloud_create_catalog(env)
|
126
|
+
else
|
127
|
+
env[:ui].error(I18n.t(
|
128
|
+
'vagrant_vcloudair.catalog.catalog_not_created'))
|
129
|
+
fail Errors::WontCreate, :item => 'Catalog'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
@logger.debug(
|
134
|
+
"Getting catalog item with cfg.catalog_id: [#{cfg.catalog_id}] " +
|
135
|
+
"and machine name [#{box_name}]"
|
136
|
+
)
|
137
|
+
cfg.catalog_item = cnx.get_catalog_item_by_name(
|
138
|
+
cfg.catalog_id,
|
139
|
+
box_name
|
140
|
+
)
|
141
|
+
|
142
|
+
@logger.debug("Catalog item is now #{cfg.catalog_item}")
|
143
|
+
|
144
|
+
# This only works with Org Admin role or higher
|
145
|
+
|
146
|
+
cfg.vdc_network_id = cfg.org[:networks][cfg.vdc_network_name]
|
147
|
+
unless cfg.vdc_network_id
|
148
|
+
# TODO: TEMP FIX: permissions issues at the Org Level for vApp
|
149
|
+
# authors to "view" Org vDC Networks but they can see them at the
|
150
|
+
# Organization vDC level (tsugliani)
|
151
|
+
cfg.vdc_network_id = cfg.vdc[:networks][cfg.vdc_network_name]
|
152
|
+
fail Errors::InvalidNetSpecification unless cfg.vdc_network_id
|
153
|
+
end
|
154
|
+
|
155
|
+
# Checking Catalog mandatory requirements
|
156
|
+
if !cfg.catalog_id
|
157
|
+
@logger.info("Catalog [#{cfg.catalog_name}] STILL does not exist!")
|
158
|
+
fail Errors::ObjectNotFound,
|
159
|
+
:message => 'Catalog not found after creation'
|
160
|
+
else
|
161
|
+
@logger.info("Catalog [#{cfg.catalog_name}] exists")
|
162
|
+
end
|
163
|
+
|
164
|
+
if !cfg.catalog_item
|
165
|
+
env[:ui].warn(I18n.t(
|
166
|
+
'vagrant_vcloudair.catalog.nonexistant_catalog_item',
|
167
|
+
catalog_item: box_name,
|
168
|
+
catalog_name: cfg.catalog_name))
|
169
|
+
|
170
|
+
user_input = env[:ui].ask(
|
171
|
+
I18n.t('vagrant_vcloudair.catalog.upload_ask',
|
172
|
+
catalog_item: box_name,
|
173
|
+
catalog_name: cfg.catalog_name) + ' ')
|
174
|
+
|
175
|
+
if user_input.downcase == 'yes' || user_input.downcase == 'y'
|
176
|
+
env[:ui].info(I18n.t('vagrant_vcloudair.catalog.uploading',
|
177
|
+
catalog_item: box_name))
|
178
|
+
vcloud_upload_box(env)
|
179
|
+
else
|
180
|
+
env[:ui].error(
|
181
|
+
I18n.t('vagrant_vcloudair.catalog.catalog_item_notavailable'))
|
182
|
+
fail Errors::WontCreate, :item => 'Box'
|
183
|
+
end
|
184
|
+
|
185
|
+
else
|
186
|
+
@logger.info(
|
187
|
+
"Using catalog item [#{box_name}] " +
|
188
|
+
"in Catalog [#{cfg.catalog_name}]..."
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Test if Gateway Edge and its IP are correct
|
193
|
+
if !cfg.vdc_edge_gateway.nil? && !cfg.vdc_edge_gateway_ip.nil?
|
194
|
+
env[:ui].info(I18n.t('vagrant_vcloudair.edge.network_test'))
|
195
|
+
# Test if Edge Gateway exists
|
196
|
+
cnx.find_edge_gateway_id(cfg.vdc_edge_gateway, cfg.vdc_id)
|
197
|
+
# Test if Edge Gateway IP exists
|
198
|
+
cnx.find_edge_gateway_network(cfg.vdc_edge_gateway,
|
199
|
+
cfg.vdc_id,
|
200
|
+
cfg.vdc_edge_gateway_ip)
|
201
|
+
# Test if Network is connected to Edge Gateway
|
202
|
+
cnx.check_edge_gateway_network(cfg.vdc_edge_gateway,
|
203
|
+
cfg.vdc_id,
|
204
|
+
cfg.vdc_network_name)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloudAir
|
3
|
+
module Action
|
4
|
+
class IsBridged
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@logger = Log4r::Logger.new('vagrant_vcloudair::action::is_bridged')
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
vapp_id = env[:machine].get_vapp_id
|
12
|
+
|
13
|
+
cfg = env[:machine].provider_config
|
14
|
+
cnx = cfg.vcloudair_cnx.driver
|
15
|
+
|
16
|
+
begin
|
17
|
+
@logger.debug('Trying to get the vApp port forwarding rules')
|
18
|
+
cnx.get_vapp_port_forwarding_rules(vapp_id)
|
19
|
+
rescue
|
20
|
+
@logger.debug('Setting the bridged_network environment var to true')
|
21
|
+
env[:bridged_network] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
@app.call env
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloudAir
|
3
|
+
module Action
|
4
|
+
class IsCreated
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@logger = Log4r::Logger.new('vagrant_vcloudair::action::is_created')
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
vapp_id = env[:machine].get_vapp_id
|
12
|
+
|
13
|
+
if vapp_id.nil?
|
14
|
+
@logger.warn('vApp has not been created')
|
15
|
+
env[:result] = false
|
16
|
+
else
|
17
|
+
@logger.info("vApp has been created and ID is: [#{vapp_id}]")
|
18
|
+
|
19
|
+
vm_id = env[:machine].id
|
20
|
+
if vm_id
|
21
|
+
@logger.info("VM has been added to vApp and ID is: [#{vm_id}]")
|
22
|
+
env[:result] = true
|
23
|
+
else
|
24
|
+
@logger.warn('VM has not been added to vApp')
|
25
|
+
env[:result] = false
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call env
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloudAir
|
3
|
+
module Action
|
4
|
+
class IsLastVM
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
cfg = env[:machine].provider_config
|
11
|
+
cnx = cfg.vcloudair_cnx.driver
|
12
|
+
|
13
|
+
vapp_id = env[:machine].get_vapp_id
|
14
|
+
|
15
|
+
test_vapp = cnx.get_vapp(vapp_id)
|
16
|
+
|
17
|
+
if test_vapp[:vms_hash].count == 1
|
18
|
+
# Set the result to be true if the machine is running.
|
19
|
+
env[:result] = true
|
20
|
+
else
|
21
|
+
env[:result] = false
|
22
|
+
end
|
23
|
+
|
24
|
+
# Call the next if we have one (but we shouldn't, since this
|
25
|
+
# middleware is built to run with the Call-type middlewares)
|
26
|
+
@app.call(env)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|