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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/.rubocop.yml +34 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +21 -0
  6. data/README.md +109 -0
  7. data/lib/vagrant-vcloudair.rb +63 -0
  8. data/lib/vagrant-vcloudair/action.rb +298 -0
  9. data/lib/vagrant-vcloudair/action/announce_ssh_exec.rb +22 -0
  10. data/lib/vagrant-vcloudair/action/build_vapp.rb +235 -0
  11. data/lib/vagrant-vcloudair/action/connect_vcloud.rb +54 -0
  12. data/lib/vagrant-vcloudair/action/destroy_vapp.rb +54 -0
  13. data/lib/vagrant-vcloudair/action/destroy_vm.rb +37 -0
  14. data/lib/vagrant-vcloudair/action/disconnect_vcloud.rb +31 -0
  15. data/lib/vagrant-vcloudair/action/forward_ports.rb +132 -0
  16. data/lib/vagrant-vcloudair/action/handle_nat_port_collisions.rb +153 -0
  17. data/lib/vagrant-vcloudair/action/inventory_check.rb +210 -0
  18. data/lib/vagrant-vcloudair/action/is_bridged.rb +29 -0
  19. data/lib/vagrant-vcloudair/action/is_created.rb +35 -0
  20. data/lib/vagrant-vcloudair/action/is_last_vm.rb +31 -0
  21. data/lib/vagrant-vcloudair/action/is_paused.rb +20 -0
  22. data/lib/vagrant-vcloudair/action/is_running.rb +20 -0
  23. data/lib/vagrant-vcloudair/action/message_already_running.rb +16 -0
  24. data/lib/vagrant-vcloudair/action/message_cannot_suspend.rb +16 -0
  25. data/lib/vagrant-vcloudair/action/message_not_created.rb +16 -0
  26. data/lib/vagrant-vcloudair/action/message_not_running.rb +16 -0
  27. data/lib/vagrant-vcloudair/action/message_will_not_destroy.rb +21 -0
  28. data/lib/vagrant-vcloudair/action/power_off.rb +33 -0
  29. data/lib/vagrant-vcloudair/action/power_off_vapp.rb +40 -0
  30. data/lib/vagrant-vcloudair/action/power_on.rb +39 -0
  31. data/lib/vagrant-vcloudair/action/read_ssh_info.rb +153 -0
  32. data/lib/vagrant-vcloudair/action/read_state.rb +51 -0
  33. data/lib/vagrant-vcloudair/action/resume.rb +25 -0
  34. data/lib/vagrant-vcloudair/action/suspend.rb +25 -0
  35. data/lib/vagrant-vcloudair/action/unmap_port_forwardings.rb +74 -0
  36. data/lib/vagrant-vcloudair/cap/forwarded_ports.rb +38 -0
  37. data/lib/vagrant-vcloudair/cap/public_address.rb +18 -0
  38. data/lib/vagrant-vcloudair/cap/rdp_info.rb +18 -0
  39. data/lib/vagrant-vcloudair/cap/winrm_info.rb +15 -0
  40. data/lib/vagrant-vcloudair/command.rb +285 -0
  41. data/lib/vagrant-vcloudair/config.rb +205 -0
  42. data/lib/vagrant-vcloudair/driver/base.rb +643 -0
  43. data/lib/vagrant-vcloudair/driver/meta.rb +202 -0
  44. data/lib/vagrant-vcloudair/driver/version_5_1.rb +2019 -0
  45. data/lib/vagrant-vcloudair/errors.rb +77 -0
  46. data/lib/vagrant-vcloudair/model/forwarded_port.rb +66 -0
  47. data/lib/vagrant-vcloudair/plugin.rb +111 -0
  48. data/lib/vagrant-vcloudair/provider.rb +41 -0
  49. data/lib/vagrant-vcloudair/util/compile_forwarded_ports.rb +34 -0
  50. data/lib/vagrant-vcloudair/version.rb +5 -0
  51. data/locales/en.yml +169 -0
  52. data/vagrant-vcloudair.gemspec +33 -0
  53. metadata +266 -0
@@ -0,0 +1,22 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ # Override the builtin SSHExec action to show the IP used to connect
5
+ class AnnounceSSHExec < Vagrant::Action::Builtin::SSHExec
6
+ def initialize(app, env)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ ssh_info = env[:machine].ssh_info
12
+ env[:ui].success(
13
+ I18n.t('vagrant_vcloudair.vm.ssh_announce',
14
+ machine_name: env[:machine].name,
15
+ ip: ssh_info[:host])
16
+ )
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,235 @@
1
+ require 'securerandom'
2
+ require 'etc'
3
+ require 'netaddr'
4
+
5
+ module VagrantPlugins
6
+ module VCloudAir
7
+ module Action
8
+ class BuildVApp
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new('vagrant_vcloudair::action::build_vapp')
12
+ end
13
+
14
+ def call(env)
15
+ # FIXME: we need to find a way to clean things up when a SIGINT get
16
+ # called... see env[:interrupted] in the vagrant code
17
+
18
+ cfg = env[:machine].provider_config
19
+ cnx = cfg.vcloudair_cnx.driver
20
+ vm_name = env[:machine].name
21
+
22
+ if cfg.ip_dns.nil?
23
+ dns_address1 = '8.8.8.8'
24
+ dns_address2 = '8.8.4.4'
25
+ else
26
+ dns_address1 = NetAddr::CIDR.create(cfg.ip_dns.shift).base
27
+ dns_address2 = NetAddr::CIDR.create(cfg.ip_dns.shift).base
28
+ end
29
+
30
+ if !cfg.ip_subnet.nil?
31
+ @logger.debug("Input address: #{cfg.ip_subnet}")
32
+
33
+ range_addresses = cidr.range(0)
34
+
35
+ @logger.debug("Range: #{range_addresses}")
36
+
37
+ # Delete the "network" address from the range.
38
+ range_addresses.shift
39
+ # Retrieve the first usable IP, to be used as a gateway.
40
+ gateway_ip = range_addresses.shift
41
+ # Reverse the array in place.
42
+ range_addresses.reverse!
43
+ # Delete the "broadcast" address from the range.
44
+ range_addresses.shift
45
+ # Reverse back the array.
46
+ range_addresses.reverse!
47
+
48
+ @logger.debug("Gateway IP: #{gateway_ip.to_s}")
49
+ @logger.debug("Netmask: #{cidr.wildcard_mask}")
50
+ @logger.debug(
51
+ "IP Pool: #{range_addresses.first}-#{range_addresses.last}"
52
+ )
53
+ @logger.debug("DNS1: #{dns_address1} DNS2: #{dns_address2}")
54
+
55
+ network_options = {
56
+ :name => 'Vagrant-vApp-Net',
57
+ :gateway => gateway_ip.to_s,
58
+ :netmask => cidr.wildcard_mask,
59
+ :start_address => range_addresses.first,
60
+ :end_address => range_addresses.last,
61
+ :fence_mode => 'natRouted',
62
+ :ip_allocation_mode => 'POOL',
63
+ :parent_network => cfg.vdc_network_id,
64
+ :enable_firewall => 'false',
65
+ :dns1 => dns_address1,
66
+ :dns2 => dns_address2
67
+ }
68
+
69
+ elsif !cfg.network_bridge.nil?
70
+ # Bridged mode, avoid deploying a vShield Edge altogether.
71
+ network_options = {
72
+ :name => 'Vagrant-vApp-Net',
73
+ :fence_mode => 'bridged',
74
+ :ip_allocation_mode => 'POOL',
75
+ :parent_network => cfg.vdc_network_id
76
+ }
77
+
78
+ env[:bridged_network] = true
79
+
80
+ else
81
+
82
+ @logger.debug("DNS1: #{dns_address1} DNS2: #{dns_address2}")
83
+ # No IP subnet specified, reverting to defaults
84
+ network_options = {
85
+ :name => 'Vagrant-vApp-Net',
86
+ :gateway => '10.1.1.1',
87
+ :netmask => '255.255.255.0',
88
+ :start_address => '10.1.1.2',
89
+ :end_address => '10.1.1.254',
90
+ :fence_mode => 'natRouted',
91
+ :ip_allocation_mode => 'POOL',
92
+ :parent_network => cfg.vdc_network_id,
93
+ :enable_firewall => 'false',
94
+ :dns1 => dns_address1,
95
+ :dns2 => dns_address2
96
+ }
97
+
98
+ end
99
+
100
+ if env[:machine].get_vapp_id.nil?
101
+ env[:ui].info(I18n.t('vagrant_vcloudair.vapp.build_vapp'))
102
+
103
+ vapp_prefix = cfg.vapp_prefix
104
+ vapp_prefix = 'Vagrant' if vapp_prefix.nil?
105
+
106
+ compose = cnx.compose_vapp_from_vm(
107
+ cfg.vdc_id,
108
+ "#{vapp_prefix}-#{Etc.getlogin}-#{Socket.gethostname.downcase}-" +
109
+ "#{SecureRandom.hex(4)}",
110
+ "vApp created by #{Etc.getlogin} running on " +
111
+ "#{Socket.gethostname.downcase} using vagrant-vcloudair on " +
112
+ "#{Time.now.strftime("%B %d, %Y")}",
113
+ {
114
+ vm_name => cfg.catalog_item[:vms_hash].first.last[:id]
115
+ },
116
+ network_options
117
+ )
118
+ @logger.debug('Launch Compose vApp...')
119
+
120
+ # Fetch thenewly created vApp ID
121
+ vapp_id = compose[:vapp_id]
122
+
123
+ # putting the vApp Id in a globally reachable var and file.
124
+ env[:machine].vappid = vapp_id
125
+
126
+ # Wait for the task to finish.
127
+ wait = cnx.wait_task_completion(compose[:task_id])
128
+
129
+ unless wait[:errormsg].nil?
130
+ fail Errors::ComposeVAppError, :message => wait[:errormsg]
131
+ end
132
+
133
+ # Fetching new vApp object to check stuff.
134
+ new_vapp = cnx.get_vapp(vapp_id)
135
+
136
+ if new_vapp
137
+ env[:ui].success(I18n.t('vagrant_vcloudair.vapp.vapp_created',
138
+ vapp_name: new_vapp[:name]))
139
+
140
+ # Add the vm id as machine.id
141
+ new_vm_properties = new_vapp[:vms_hash].fetch(vm_name)
142
+ env[:machine].id = new_vm_properties[:id]
143
+
144
+ ### SET GUEST CONFIG
145
+ @logger.info(
146
+ "Setting Guest Customization on ID: [#{vm_name}] " +
147
+ "of vApp [#{new_vapp[:name]}]"
148
+ )
149
+
150
+ set_custom = cnx.set_vm_guest_customization(
151
+ new_vm_properties[:id],
152
+ vm_name,
153
+ {
154
+ :enabled => true,
155
+ :admin_passwd_enabled => false
156
+ }
157
+ )
158
+ wait = cnx.wait_task_completion(set_custom)
159
+
160
+ unless wait[:errormsg].nil?
161
+ fail Errors::ComposeVAppError, :message => wait[:errormsg]
162
+ end
163
+
164
+ else
165
+ env[:ui].error(I18n.t(
166
+ 'vagrant_vcloudair.vapp.vapp_creation_failed'),
167
+ vapp_name: new_vapp[:name])
168
+ fail Errors::ComposeVAppError,
169
+ :message => 'vApp created but cannot get a working id, \
170
+ please report this error'
171
+ end
172
+
173
+ else
174
+ env[:ui].info(I18n.t('vagrant_vcloudair.vapp.adding_vm'))
175
+
176
+ recompose = cnx.recompose_vapp_from_vm(
177
+ env[:machine].get_vapp_id,
178
+ {
179
+ vm_name => cfg.catalog_item[:vms_hash].first.last[:id]
180
+ },
181
+ network_options
182
+ )
183
+
184
+ @logger.info('Waiting for the recompose task to complete ...')
185
+
186
+ # Wait for the task to finish.
187
+ wait = cnx.wait_task_completion(recompose[:task_id])
188
+
189
+ unless wait[:errormsg].nil?
190
+ fail Errors::ComposeVAppError, :message => wait[:errormsg]
191
+ end
192
+
193
+ new_vapp = cnx.get_vapp(env[:machine].get_vapp_id)
194
+
195
+ if new_vapp
196
+ new_vm_properties = new_vapp[:vms_hash].fetch(vm_name)
197
+ env[:machine].id = new_vm_properties[:id]
198
+
199
+ ### SET GUEST CONFIG
200
+ @logger.info(
201
+ 'Setting Guest Customization on ID: ' +
202
+ "[#{new_vm_properties[:id]}] of vApp [#{new_vapp[:name]}]"
203
+ )
204
+
205
+ set_custom = cnx.set_vm_guest_customization(
206
+ new_vm_properties[:id],
207
+ vm_name,
208
+ {
209
+ :enabled => true,
210
+ :admin_passwd_enabled => false
211
+ }
212
+ )
213
+ wait = cnx.wait_task_completion(set_custom)
214
+
215
+ unless wait[:errormsg].nil?
216
+ fail Errors::ComposeVAppError, :message => wait[:errormsg]
217
+ end
218
+
219
+ else
220
+ # env[:ui].error("VM #{vm_name} add to #{new_vapp[:name]} failed!")
221
+ env[:ui].error(I18n.t('vagrant_vcloudair.vapp.vm_add_failed',
222
+ vm_name: vm_name,
223
+ vapp_name: new_vapp[:name]))
224
+ fail Errors::ComposeVAppError,
225
+ :message => 'VM added to vApp but cannot get a working id, \
226
+ please report this error'
227
+ end
228
+ end
229
+
230
+ @app.call env
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,54 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ class ConnectVCloudAir
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloudair::action::connect_vcloud')
8
+ end
9
+
10
+ def call(env)
11
+ config = env[:machine].provider_config
12
+
13
+ if !config.vcloudair_cnx || !config.vcloudair_cnx.driver.auth_key
14
+ @logger.info('Connecting to vCloud Air...')
15
+
16
+ @logger.debug("config.cloud_id: #{config.cloud_id}") unless config.cloud_id.nil?
17
+ @logger.debug("config.username: #{config.username}")
18
+ @logger.debug('config.password: <hidden>')
19
+ @logger.debug("config.vdc_name: #{config.vdc_name}")
20
+
21
+ # Create the vcloud-rest connection object with the configuration
22
+ # information.
23
+ config.vcloudair_cnx = Driver::Meta.new(
24
+ config.cloud_id,
25
+ config.username,
26
+ config.password,
27
+ config.vdc_name
28
+ )
29
+
30
+ @logger.info('Logging into vCloud Air...')
31
+ # config.vcloudair_cnx.login
32
+
33
+ # Check for the vCloud Air authentication token
34
+ if config.vcloudair_cnx.driver.auth_key
35
+ @logger.info('Logged in successfully!')
36
+ @logger.debug(
37
+ "x-vcloud-authorization=#{config.vcloudair_cnx.driver.auth_key}"
38
+ )
39
+ else
40
+ @logger.info("Login failed in to #{config.hostname}.")
41
+ fail Errors::UnauthorizedAccess
42
+ end
43
+ else
44
+ @logger.info('Already logged in, using current session')
45
+ @logger.debug(
46
+ "x-vcloud-authorization=#{config.vcloudair_cnx.driver.auth_key}"
47
+ )
48
+ end
49
+ @app.call env
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ class DestroyVApp
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloudair::action::destroy_vapp')
8
+ end
9
+
10
+ def call(env)
11
+ cfg = env[:machine].provider_config
12
+ cnx = cfg.vcloudair_cnx.driver
13
+ vapp_id = env[:machine].get_vapp_id
14
+
15
+ cfg.org = cnx.get_organization_by_name(cfg.vdc_name)
16
+ cfg.vdc_id = cnx.get_vdc_id_by_name(cfg.org, cfg.vdc_name)
17
+
18
+ test_vapp = cnx.get_vapp(vapp_id)
19
+
20
+ @logger.debug(
21
+ "Number of VMs in the vApp: #{test_vapp[:vms_hash].count}"
22
+ )
23
+
24
+ if cfg.vdc_edge_gateway_ip && cfg.vdc_edge_gateway
25
+ env[:ui].info(I18n.t('vagrant_vcloudair.edge.removing_nat_rules',
26
+ vdc_edge_gateway: cfg.vdc_edge_gateway,
27
+ vdc_edge_gateway_ip: cfg.vdc_edge_gateway_ip))
28
+
29
+ @logger.debug(
30
+ "Deleting Edge Gateway rules - vdc id: #{cfg.vdc_id}"
31
+ )
32
+ edge_remove = cnx.remove_edge_gateway_rules(
33
+ cfg.vdc_edge_gateway,
34
+ cfg.vdc_id,
35
+ cfg.vdc_edge_gateway_ip,
36
+ vapp_id
37
+ )
38
+ cnx.wait_task_completion(edge_remove)
39
+ end
40
+
41
+ env[:ui].info(I18n.t('vagrant_vcloudair.vapp.destroy_vapp'))
42
+ vapp_delete_task = cnx.delete_vapp(vapp_id)
43
+ @logger.debug("vApp Delete task id #{vapp_delete_task}")
44
+ cnx.wait_task_completion(vapp_delete_task)
45
+
46
+ env[:machine].id = nil
47
+ env[:machine].vappid = nil
48
+
49
+ @app.call env
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ class DestroyVM
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloudair::action::destroy_vm')
8
+ end
9
+
10
+ def call(env)
11
+ cfg = env[:machine].provider_config
12
+ cnx = cfg.vcloudair_cnx.driver
13
+ vapp_id = env[:machine].get_vapp_id
14
+ vm_id = env[:machine].id
15
+
16
+ cfg.org = cnx.get_organization_by_name(cfg.vdc_name)
17
+ cfg.vdc_id = cnx.get_vdc_id_by_name(cfg.org, cfg.vdc_name)
18
+
19
+ test_vapp = cnx.get_vapp(vapp_id)
20
+
21
+ @logger.debug(
22
+ "Number of VMs in the vApp: #{test_vapp[:vms_hash].count}"
23
+ )
24
+
25
+ env[:ui].info(I18n.t('vagrant_vcloudair.vm.destroy_vm'))
26
+ vm_delete_task = cnx.delete_vm(vm_id)
27
+ @logger.debug("VM Delete task id #{vm_delete_task}")
28
+ cnx.wait_task_completion(vm_delete_task)
29
+
30
+ env[:machine].id = nil
31
+
32
+ @app.call env
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ class DisconnectVCloudAir
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new(
8
+ 'vagrant_vcloudair::action::disconnect_vcloud'
9
+ )
10
+ end
11
+
12
+ def call(env)
13
+ @logger.info('Disconnecting from vCloud Air...')
14
+
15
+ # Fetch the global vCloud Air connection handle
16
+ cnx = env[:machine].provider_config.vcloudair_cnx.driver
17
+
18
+ # Delete the current vCloud Air Session
19
+ cnx.logout
20
+
21
+ # If session key doesn't exist, we are disconnected
22
+ if !cnx.auth_key
23
+ @logger.info('Disconnected from vCloud Air successfully!')
24
+ else
25
+ fail Errors::VCloudAirGenericError, :message => e.message
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,132 @@
1
+ module VagrantPlugins
2
+ module VCloudAir
3
+ module Action
4
+ class ForwardPorts
5
+ include Util::CompileForwardedPorts
6
+
7
+ def initialize(app, env)
8
+ @app = app
9
+ @logger = Log4r::Logger.new('vagrant_vcloudair::action::forward_ports')
10
+ end
11
+
12
+ def call(env)
13
+ @env = env
14
+
15
+ # Get the ports we are forwarding
16
+ env[:forwarded_ports] ||= compile_forwarded_ports(
17
+ env[:machine].config
18
+ )
19
+
20
+ forward_ports
21
+
22
+ @app.call(env)
23
+ end
24
+
25
+ def forward_ports
26
+ ports = []
27
+ edge_ports = []
28
+
29
+ cfg = @env[:machine].provider_config
30
+ cnx = cfg.vcloudair_cnx.driver
31
+ vapp_id = @env[:machine].get_vapp_id
32
+ vm_name = @env[:machine].name
33
+
34
+ # FIXME: why are we overriding this here ?
35
+ # It's already been taken care during the initial
36
+ # InventoryCheck. (tsugliani)
37
+ #
38
+ # cfg.org = cnx.get_organization_by_name(cfg.vdc_name)
39
+ # cfg.vdc_network_id = cfg.org[:networks][cfg.vdc_network_name]
40
+
41
+ @logger.debug('Getting VM info...')
42
+ vm = cnx.get_vapp(vapp_id)
43
+ vm_info = vm[:vms_hash][vm_name.to_sym]
44
+
45
+ @env[:forwarded_ports].each do |fp|
46
+
47
+ @env[:ui].info(I18n.t('vagrant_vcloudair.edge.port_forwarding',
48
+ guest_port: fp.guest_port,
49
+ host_port: fp.host_port))
50
+
51
+ # Add the options to the ports array to send to the driver later
52
+ ports << {
53
+ :guestip => fp.guest_ip,
54
+ :nat_internal_port => fp.guest_port,
55
+ :hostip => fp.host_ip,
56
+ :nat_external_port => fp.host_port,
57
+ :name => fp.id,
58
+ :nat_protocol => fp.protocol.upcase,
59
+ :vapp_scoped_local_id => vm_info[:vapp_scoped_local_id]
60
+ }
61
+ end
62
+
63
+ unless ports.empty?
64
+ # We only need to forward ports if there are any to forward
65
+ @logger.debug("Port object to be passed: #{ports.inspect}")
66
+ @logger.debug("Current network id #{cfg.vdc_network_id}")
67
+
68
+ ### Here we apply the nat_rules to the vApp we just built
69
+ add_ports = cnx.add_vapp_port_forwarding_rules(
70
+ vapp_id,
71
+ 'Vagrant-vApp-Net',
72
+ {
73
+ :fence_mode => 'natRouted',
74
+ :parent_network => cfg.vdc_network_id,
75
+ :nat_policy_type => 'allowTraffic',
76
+ :nat_rules => ports
77
+ }
78
+ )
79
+
80
+ wait = cnx.wait_task_completion(add_ports)
81
+
82
+ unless wait[:errormsg].nil?
83
+ fail Errors::ComposeVAppError, :message => wait[:errormsg]
84
+ end
85
+
86
+ if cfg.vdc_edge_gateway_ip && \
87
+ cfg.vdc_edge_gateway && \
88
+ cfg.network_bridge.nil?
89
+
90
+ vapp_edge_ip = cnx.get_vapp_edge_public_ip(vapp_id)
91
+ @logger.debug('Getting edge gateway port forwarding rules...')
92
+ edge_gateway_rules = cnx.get_edge_gateway_rules(cfg.vdc_edge_gateway,
93
+ cfg.vdc_id)
94
+ vapp_edge_dnat_rules = edge_gateway_rules.select {|r| (r[:rule_type] == 'DNAT' &&
95
+ r[:translated_ip] == vapp_edge_ip)}
96
+ vapp_edge_ports_in_use = vapp_edge_dnat_rules.map{|r| r[:original_port].to_i}.to_set
97
+
98
+ ports.each do |port|
99
+ if port[:vapp_scoped_local_id] == vm_info[:vapp_scoped_local_id] &&
100
+ !vapp_edge_ports_in_use.include?(port[:nat_external_port])
101
+
102
+ @env[:ui].info(I18n.t(
103
+ 'vagrant_vcloudair.edge.nat_rules_creation',
104
+ vdc_edge_gateway: cfg.vdc_edge_gateway,
105
+ vapp_edge_ip: vapp_edge_ip,
106
+ port: port[:nat_external_port]))
107
+
108
+ edge_ports << port[:nat_external_port]
109
+ end
110
+ end
111
+
112
+ unless edge_ports.empty?
113
+ # Add the vShield Edge Gateway rules
114
+ add_ports = cnx.add_edge_gateway_rules(
115
+ cfg.vdc_edge_gateway,
116
+ cfg.vdc_id,
117
+ cfg.vdc_edge_gateway_ip,
118
+ vapp_id,
119
+ edge_ports
120
+ )
121
+
122
+ wait = cnx.wait_task_completion(add_ports)
123
+
124
+ fail Errors::ComposeVAppError, :message => wait[:errormsg] unless wait[:errormsg].nil?
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end