vagrant-vcloud 0.2.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9481686204d161ed6766034bed50ba9e5591dbca
4
- data.tar.gz: 19946c9cd8111f6e375c61b15b68ca38fdb7187f
3
+ metadata.gz: ffdaef92decaf313b306add8bc6f4809fd96aa10
4
+ data.tar.gz: 7a92c5b464e12b4c1a00b0d61288eb1967f23e61
5
5
  SHA512:
6
- metadata.gz: ce9057ebddf373a0df383f07cba284c2cd67ec4943eb858f7a583c5cbbd39ccc0005905647b80c6e2aae8f1255db71ebf99774b553a9a6f7c4b35a83df9bd547
7
- data.tar.gz: 284e9b7bd5a7f095d2aeaec1ddf78e3a933a8ad39f5b993c8dd89ce69d368fe0a437aaa393b637346b01ac6f3e59c419c34b34e1ba25ecbc73bbb954017e9de5
6
+ metadata.gz: 8823a60a23a6426b230abc79d99e2765f29a1bb173a135aa7a85a684288c4b91c844d2db340cfedb0c9913723972c86719610098af67985b631e8cf0f3771b4b
7
+ data.tar.gz: cf31bea829c6972bfcf5ef88b50333cec048bf9b50931f8576306b31fed4fd1ab320a2c482c54771332042e7856fdcca16c6d692fa90d5a3455b5316b97e7b4d
data/README.md CHANGED
@@ -1,13 +1,24 @@
1
1
  [Vagrant](http://www.vagrantup.com) provider for VMware vCloud Director®
2
2
  =============
3
3
 
4
- [Version 0.2.2](https://github.com/frapposelli/vagrant-vcloud/releases/tag/v0.2.2) has been released!
4
+ [Version 0.3.0](https://github.com/frapposelli/vagrant-vcloud/releases/tag/v0.3.0) has been released!
5
5
  -------------
6
6
 
7
7
  Please note that this software is still Alpha/Beta quality and is not recommended for production usage.
8
8
 
9
9
  Right now a [Precise32](http://vagrant.tsugliani.fr/precise32.box) is available for use, or you can roll your own as you please, make sure to install VMware tools in it.
10
10
 
11
+ Features of Version 0.3.0 are:
12
+
13
+ A substantial release, major kudos to Stefan Scherer who submitted some substantious PRs!
14
+
15
+ - Added support for port mapping at the Organization Edge Gateway.
16
+ - Added a new configuration options ```vapp_prefix``` to change vApp prefix (defaults to Vagrant).
17
+ - Improved vcloud-status command.
18
+ - Fixed cygdrive path for rsync on Windows.
19
+ - Fixed Issue #33 - Error removing/creating NAT rules on second vagrant up.
20
+ - Fixed Issue #43 - Destroy fails if VMs are halted.
21
+
11
22
  Features of Version 0.2.2 are:
12
23
 
13
24
  - Fixed Issue #32 - Port Forwarding rules are deleted when Halting a VM.
@@ -94,6 +105,8 @@ Vagrant.configure("2") do |config|
94
105
 
95
106
  # vCloud Director provider settings
96
107
  config.vm.provider :vcloud do |vcloud|
108
+ vcloud.vapp_prefix = "multibox-sample"
109
+
97
110
  vcloud.hostname = "https://my.cloudprovider.com"
98
111
  vcloud.username = "MyUserName"
99
112
  vcloud.password = "MySup3rS3cr3tPassw0rd!"
@@ -111,9 +111,14 @@ module VagrantPlugins
111
111
  if env[:machine].get_vapp_id.nil?
112
112
  env[:ui].info('Building vApp...')
113
113
 
114
+ vapp_prefix = cfg.vapp_prefix
115
+ if vapp_prefix.nil?
116
+ vapp_prefix = "Vagrant"
117
+ end
118
+
114
119
  compose = cnx.compose_vapp_from_vm(
115
120
  cfg.vdc_id,
116
- "Vagrant-#{Etc.getlogin}-#{Socket.gethostname.downcase}-" +
121
+ "#{vapp_prefix}-#{Etc.getlogin}-#{Socket.gethostname.downcase}-" +
117
122
  "#{SecureRandom.hex(4)}",
118
123
  "vApp created by #{Etc.getlogin} running on " +
119
124
  "#{Socket.gethostname.downcase} using vagrant-vcloud on " +
@@ -0,0 +1,54 @@
1
+ module VagrantPlugins
2
+ module VCloud
3
+ module Action
4
+ class DestroyVApp
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloud::action::destroy_vapp')
8
+ end
9
+
10
+ def call(env)
11
+ cfg = env[:machine].provider_config
12
+ cnx = cfg.vcloud_cnx.driver
13
+ vapp_id = env[:machine].get_vapp_id
14
+
15
+ cfg.org = cnx.get_organization_by_name(cfg.org_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(
26
+ "Removing NAT rules on [#{cfg.vdc_edge_gateway}] " +
27
+ "for 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('Destroying 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 VCloud
3
+ module Action
4
+ class DestroyVM
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloud::action::destroy_vm')
8
+ end
9
+
10
+ def call(env)
11
+ cfg = env[:machine].provider_config
12
+ cnx = cfg.vcloud_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.org_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('Destroying 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
@@ -24,6 +24,7 @@ module VagrantPlugins
24
24
 
25
25
  def forward_ports
26
26
  ports = []
27
+ edge_ports = []
27
28
 
28
29
  cfg = @env[:machine].provider_config
29
30
  cnx = cfg.vcloud_cnx.driver
@@ -42,12 +43,6 @@ module VagrantPlugins
42
43
  vm_info = vm[:vms_hash][vm_name.to_sym]
43
44
 
44
45
  @env[:forwarded_ports].each do |fp|
45
- # FIXME: Useless variable assignement 'message_attributes'
46
- # (tsugliani)
47
- message_attributes = {
48
- :guest_port => fp.guest_port,
49
- :host_port => fp.host_port
50
- }
51
46
 
52
47
  @env[:ui].info(
53
48
  "Forwarding Ports: VM port #{fp.guest_port} -> " +
@@ -64,6 +59,8 @@ module VagrantPlugins
64
59
  :nat_protocol => fp.protocol.upcase,
65
60
  :vapp_scoped_local_id => vm_info[:vapp_scoped_local_id]
66
61
  }
62
+
63
+ edge_ports << fp.host_port
67
64
  end
68
65
 
69
66
  if !ports.empty?
@@ -89,8 +86,36 @@ module VagrantPlugins
89
86
  raise Errors::ComposeVAppError, :message => wait[:errormsg]
90
87
  end
91
88
 
92
- end
93
89
 
90
+ if cfg.vdc_edge_gateway_ip && \
91
+ cfg.vdc_edge_gateway && \
92
+ cfg.network_bridge.nil?
93
+
94
+
95
+ edge_ports.each do |port|
96
+ @env[:ui].info(
97
+ "Creating NAT rules on [#{cfg.vdc_edge_gateway}] " +
98
+ "for IP [#{cfg.vdc_edge_gateway_ip}] port #{port}."
99
+ )
100
+ end
101
+
102
+ # Add the vShield Edge Gateway rules
103
+ add_ports = cnx.add_edge_gateway_rules(
104
+ cfg.vdc_edge_gateway,
105
+ cfg.vdc_id,
106
+ cfg.vdc_edge_gateway_ip,
107
+ vapp_id,
108
+ edge_ports
109
+ )
110
+
111
+ wait = cnx.wait_task_completion(add_ports)
112
+
113
+ if !wait[:errormsg].nil?
114
+ raise Errors::ComposeVAppError, :message => wait[:errormsg]
115
+ end
116
+
117
+ end
118
+ end
94
119
  end
95
120
  end
96
121
  end
@@ -42,67 +42,103 @@ module VagrantPlugins
42
42
  cnx = cfg.vcloud_cnx.driver
43
43
  vapp_id = env[:machine].get_vapp_id
44
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
+ @logger.debug('Getting edge gateway port forwarding rules...')
51
+ edge_gateway_rules = cnx.get_edge_gateway_rules(cfg.vdc_edge_gateway,
52
+ cfg.vdc_id)
53
+ edge_dnat_rules = edge_gateway_rules.select {|r| (r[:rule_type] == 'DNAT')}
54
+ edge_ports_in_use = edge_dnat_rules.map{|r| r[:original_port].to_i}.to_set
55
+
45
56
  @logger.debug('Getting port forwarding rules...')
46
- rules = cnx.get_vapp_port_forwarding_external_ports(vapp_id)
57
+ vapp_nat_rules = cnx.get_vapp_port_forwarding_rules(vapp_id)
58
+ ports_in_use = vapp_nat_rules.map{|r| r[:nat_external_port].to_i}.to_set
59
+
60
+ # merge the vapp ports and the edge gateway ports together, all are in use
61
+ ports_in_use = ports_in_use | edge_ports_in_use
47
62
 
48
63
  # Pass two, detect/handle any collisions
49
64
  with_forwarded_ports(env) do |options|
50
65
  guest_port = options[:guest]
51
66
  host_port = options[:host]
52
67
 
53
- # If the port is open (listening for TCP connections)
54
- if rules.include?(host_port)
55
- if !options[:auto_correct]
56
- raise Errors::ForwardPortCollision,
57
- :guest_port => guest_port.to_s,
58
- :host_port => host_port.to_s
59
- end
60
-
61
- @logger.info("Attempting to repair FP collision: #{host_port}")
68
+ # Find if there already is a DNAT rule to this vApp
69
+ if r = edge_dnat_rules.find { |rule| (rule[:translated_ip] == vm_info[:ip] &&
70
+ rule[:translated_port] == guest_port.to_s) }
62
71
 
63
- repaired_port = nil
64
- while !usable_ports.empty?
65
- # Attempt to repair the forwarded port
66
- repaired_port = usable_ports.to_a.sort[0]
67
- usable_ports.delete(repaired_port)
72
+ @logger.info(
73
+ "Found existing edge gateway port forwarding rule #r[:original_port] to #{guest_port}"
74
+ )
75
+ options[:already_exists_on_edge] = true
76
+ end
68
77
 
69
- # If the port is in use, then we can't use this either...
70
- if rules.include?(repaired_port)
71
- @logger.info(
72
- "Repaired port also in use: #{repaired_port}." +
73
- 'Trying another...'
74
- )
75
- next
78
+ # Find if there already is a NAT rule to guest_port of this VM
79
+ if r = vapp_nat_rules.find { |rule| (rule[:vapp_scoped_local_id] == vm_info[:vapp_scoped_local_id] &&
80
+ rule[:nat_internal_port] == guest_port.to_s) }
81
+ host_port = r[:nat_external_port].to_i
82
+ @logger.info(
83
+ "Found existing port forwarding rule #{host_port} to #{guest_port}"
84
+ )
85
+ options[:host] = host_port
86
+ options[:already_exists] = true
87
+ else
88
+ # If the port is open (listening for TCP connections)
89
+ if ports_in_use.include?(host_port)
90
+ if !options[:auto_correct]
91
+ raise Errors::ForwardPortCollision,
92
+ :guest_port => guest_port.to_s,
93
+ :host_port => host_port.to_s
76
94
  end
77
95
 
78
- # We have a port so break out
79
- break
80
- end
96
+ @logger.info("Attempting to repair FP collision: #{host_port}")
97
+
98
+ repaired_port = nil
99
+ while !usable_ports.empty?
100
+ # Attempt to repair the forwarded port
101
+ repaired_port = usable_ports.to_a.sort[0]
102
+ usable_ports.delete(repaired_port)
103
+
104
+ # If the port is in use, then we can't use this either...
105
+ if ports_in_use.include?(repaired_port)
106
+ @logger.info(
107
+ "Repaired port also in use: #{repaired_port}." +
108
+ 'Trying another...'
109
+ )
110
+ next
111
+ end
112
+
113
+ # We have a port so break out
114
+ break
115
+ end
81
116
 
82
- # If we have no usable ports then we can't repair
83
- if !repaired_port && usable_ports.empty?
84
- raise Errors::ForwardPortAutolistEmpty,
85
- :vm_name => env[:machine].name,
86
- :guest_port => guest_port.to_s,
87
- :host_port => host_port.to_s
88
- end
117
+ # If we have no usable ports then we can't repair
118
+ if !repaired_port && usable_ports.empty?
119
+ raise Errors::ForwardPortAutolistEmpty,
120
+ :vm_name => env[:machine].name,
121
+ :guest_port => guest_port.to_s,
122
+ :host_port => host_port.to_s
123
+ end
89
124
 
90
- # Modify the args in place
91
- options[:host] = repaired_port
125
+ # Modify the args in place
126
+ options[:host] = repaired_port
92
127
 
93
- @logger.info(
94
- "Repaired FP collision: #{host_port} to #{repaired_port}"
95
- )
128
+ @logger.info(
129
+ "Repaired FP collision: #{host_port} to #{repaired_port}"
130
+ )
96
131
 
97
- # Notify the user
98
- env[:ui].info(
99
- I18n.t(
100
- 'vagrant.actions.vm.forward_ports.fixed_collision',
101
- :host_port => host_port.to_s,
102
- :guest_port => guest_port.to_s,
103
- :new_port => repaired_port.to_s
132
+ # Notify the user
133
+ env[:ui].info(
134
+ I18n.t(
135
+ 'vagrant.actions.vm.forward_ports.fixed_collision',
136
+ :host_port => host_port.to_s,
137
+ :guest_port => guest_port.to_s,
138
+ :new_port => repaired_port.to_s
139
+ )
104
140
  )
105
- )
141
+ end
106
142
  end
107
143
  end
108
144
 
@@ -0,0 +1,31 @@
1
+ module VagrantPlugins
2
+ module VCloud
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.vcloud_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
@@ -20,23 +20,10 @@ module VagrantPlugins
20
20
  "Number of VMs in the vApp: #{test_vapp[:vms_hash].count}"
21
21
  )
22
22
 
23
- if test_vapp[:vms_hash].count == 1
24
-
25
- # Poweroff vApp
26
- env[:ui].info('Powering off vApp...')
27
- vapp_stop_task = cnx.poweroff_vapp(vapp_id)
28
- vapp_stop_wait = cnx.wait_task_completion(vapp_stop_task)
29
-
30
- unless vapp_stop_wait[:errormsg].nil?
31
- fail Errors::StopVAppError, :message => vapp_stop_wait[:errormsg]
32
- end
33
-
34
- else
35
- # Poweroff VM
36
- env[:ui].info('Powering off VM...')
37
- task_id = cnx.poweroff_vm(vm_id)
38
- cnx.wait_task_completion(task_id)
39
- end
23
+ # Poweroff VM
24
+ env[:ui].info('Powering off VM...')
25
+ task_id = cnx.poweroff_vm(vm_id)
26
+ cnx.wait_task_completion(task_id)
40
27
 
41
28
  @app.call env
42
29
  end
@@ -0,0 +1,40 @@
1
+ module VagrantPlugins
2
+ module VCloud
3
+ module Action
4
+ class PowerOffVApp
5
+ def initialize(app, env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new('vagrant_vcloud::action::poweroff_vapp')
8
+ end
9
+
10
+ def call(env)
11
+ cfg = env[:machine].provider_config
12
+ cnx = cfg.vcloud_cnx.driver
13
+
14
+ vapp_id = env[:machine].get_vapp_id
15
+
16
+ test_vapp = cnx.get_vapp(vapp_id)
17
+
18
+ @logger.debug(
19
+ "Number of VMs in the vApp: #{test_vapp[:vms_hash].count}"
20
+ )
21
+
22
+ # this is a helper to get vapp_edge_ip into cache for later destroy
23
+ # of edge gateway rules
24
+ vapp_edge_ip = cnx.get_vapp_edge_public_ip(vapp_id)
25
+
26
+ # Poweroff vApp
27
+ env[:ui].info('Single VM left in the vApp, Powering off vApp...')
28
+ vapp_stop_task = cnx.poweroff_vapp(vapp_id)
29
+ vapp_stop_wait = cnx.wait_task_completion(vapp_stop_task)
30
+
31
+ unless vapp_stop_wait[:errormsg].nil?
32
+ fail Errors::StopVAppError, :message => vapp_stop_wait[:errormsg]
33
+ end
34
+
35
+ @app.call env
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -12,70 +12,12 @@ module VagrantPlugins
12
12
 
13
13
  cfg = env[:machine].provider_config
14
14
  cnx = cfg.vcloud_cnx.driver
15
- vapp_id = env[:machine].get_vapp_id
16
15
 
17
- env[:ui].info('Booting VM...')
18
-
19
- if cfg.network_bridge.nil?
20
- test_ip = cnx.get_vapp_edge_public_ip(vapp_id)
21
- end
16
+ env[:ui].info('Powering on VM...')
22
17
 
23
18
  poweron_vm = cnx.poweron_vm(env[:machine].id)
24
19
  cnx.wait_task_completion(poweron_vm)
25
20
 
26
- if test_ip.nil? && \
27
- cfg.vdc_edge_gateway_ip && \
28
- cfg.vdc_edge_gateway && \
29
- cfg.network_bridge.nil?
30
-
31
- @logger.debug(
32
- 'This is our first boot, we should map ports on the ' \
33
- 'Organization vDC vShield Edge Gateway!'
34
- )
35
-
36
- ### TMP FIX: tsugliani
37
- ### We need to verify the vShield Edge Gateway rules don't already
38
- ### exist.
39
- ### Removing any rule previously set for that same source IP
40
-
41
- # ----
42
- if cfg.vdc_edge_gateway_ip && cfg.vdc_edge_gateway
43
- env[:ui].info(
44
- "Removing NAT rules on [#{cfg.vdc_edge_gateway}] " +
45
- "for IP [#{cfg.vdc_edge_gateway_ip}]."
46
- )
47
- @logger.debug(
48
- 'Cleaning possible conflicting Edge Gateway rules - ' +
49
- "Organization vDC id: #{cfg.vdc_id}"
50
- )
51
-
52
- edge_remove = cnx.remove_edge_gateway_rules(
53
- cfg.vdc_edge_gateway,
54
- cfg.vdc_id,
55
- cfg.vdc_edge_gateway_ip,
56
- vapp_id
57
- )
58
- cnx.wait_task_completion(edge_remove)
59
- end
60
- # ----
61
-
62
- env[:ui].info(
63
- "Creating NAT rules on [#{cfg.vdc_edge_gateway}] " +
64
- "for IP [#{cfg.vdc_edge_gateway_ip}]."
65
- )
66
-
67
- # Set the vShield Edge Gateway rules
68
- edge_map = cnx.set_edge_gateway_rules(
69
- cfg.vdc_edge_gateway,
70
- cfg.vdc_id,
71
- cfg.vdc_edge_gateway_ip,
72
- vapp_id
73
- )
74
-
75
- # Wait for task to complete.
76
- cnx.wait_task_completion(edge_map)
77
- end
78
-
79
21
  @app.call(env)
80
22
  end
81
23
  end
@@ -77,7 +77,7 @@ module VagrantPlugins
77
77
 
78
78
  # on windows rsync.exe requires cygdrive-style paths
79
79
  if Vagrant::Util::Platform.windows?
80
- hostpath = hostpath.gsub(/^(\w):/) { "/cygdrive/\1" }
80
+ hostpath = hostpath.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
81
81
  end
82
82
 
83
83
  env[:ui].info(
@@ -53,14 +53,14 @@ module VagrantPlugins
53
53
  b2.use MessageAlreadyRunning
54
54
  next
55
55
  end
56
- b2.use Call, IsPaused do |env2, b3|
57
- if env2[:result]
58
- b3.use Resume
59
- next
60
- end
61
- b3.use action_boot
56
+ end
57
+ b.use Call, IsPaused do |env, b2|
58
+ if env[:result]
59
+ b3.use Resume
60
+ next
62
61
  end
63
62
  end
63
+ b.use PowerOn
64
64
  end
65
65
  end
66
66
 
@@ -105,12 +105,19 @@ module VagrantPlugins
105
105
  b2.use Call, IsRunning do |env2, b3|
106
106
  # If the VM is running, must power off
107
107
  b3.use action_halt if env2[:result]
108
- # Check if the network is bridged
109
- b3.use Call, IsBridged do |env3, b4|
110
- # if it's not, delete port forwardings.
111
- b4.use UnmapPortForwardings unless env3[:bridged_network]
108
+ end
109
+ b2.use Call, IsLastVM do |env2, b3|
110
+ if env2[:result]
111
+ # Check if the network is bridged
112
+ b3.use Call, IsBridged do |env3, b4|
113
+ # if it's not, delete port forwardings.
114
+ b4.use UnmapPortForwardings unless env3[:bridged_network]
115
+ end
116
+ b3.use PowerOffVApp
117
+ b3.use DestroyVApp
118
+ else
119
+ b3.use DestroyVM
112
120
  end
113
- b3.use Destroy
114
121
  end
115
122
  else
116
123
  b2.use MessageWillNotDestroy
@@ -191,13 +198,15 @@ module VagrantPlugins
191
198
  b2.use HandleBox unless env[:result]
192
199
  end
193
200
  b.use ConnectVCloud
201
+ b.use InventoryCheck
194
202
  b.use Call, IsCreated do |env, b2|
195
- unless env[:result]
196
- b2.use InventoryCheck
203
+ if env[:result]
204
+ b2.use action_start
205
+ else
197
206
  b2.use BuildVApp
207
+ b2.use action_boot
198
208
  end
199
209
  end
200
- b.use action_start
201
210
  b.use DisconnectVCloud
202
211
  end
203
212
  end
@@ -210,8 +219,10 @@ module VagrantPlugins
210
219
  action_root.join('build_vapp')
211
220
  autoload :ConnectVCloud,
212
221
  action_root.join('connect_vcloud')
213
- autoload :Destroy,
214
- action_root.join('destroy')
222
+ autoload :DestroyVM,
223
+ action_root.join('destroy_vm')
224
+ autoload :DestroyVApp,
225
+ action_root.join('destroy_vapp')
215
226
  autoload :DisconnectVCloud,
216
227
  action_root.join('disconnect_vcloud')
217
228
  autoload :ForwardPorts,
@@ -228,6 +239,8 @@ module VagrantPlugins
228
239
  action_root.join('is_paused')
229
240
  autoload :IsRunning,
230
241
  action_root.join('is_running')
242
+ autoload :IsLastVM,
243
+ action_root.join('is_last_vm')
231
244
  autoload :MessageAlreadyRunning,
232
245
  action_root.join('message_already_running')
233
246
  autoload :MessageCannotSuspend,
@@ -238,6 +251,8 @@ module VagrantPlugins
238
251
  action_root.join('message_will_not_destroy')
239
252
  autoload :PowerOff,
240
253
  action_root.join('power_off')
254
+ autoload :PowerOffVApp,
255
+ action_root.join('power_off_vapp')
241
256
  autoload :PowerOn,
242
257
  action_root.join('power_on')
243
258
  autoload :ReadSSHInfo,
@@ -118,35 +118,44 @@ module VagrantPlugins
118
118
  network_table << :separator
119
119
 
120
120
  # Fetching Destination NAT Rules for each vApp/Edge/VM/Mapping
121
- edge_gateway_rules.each do |edge_gateway_rule|
122
- vapp_edge_rules.each do |vapp_edge_rule|
123
-
124
- # Only check DNAT and src/dst
125
- if edge_gateway_rule[:rule_type] == 'DNAT' &&
126
- edge_gateway_rule[:original_ip] == cfg.vdc_edge_gateway_ip &&
127
- edge_gateway_rule[:translated_ip] == vapp_edge_ip
128
-
129
- # Loop on every VM in the vApp
130
- vapp[:vms_hash].each do |vm|
131
- # Only Map valid vAppEdge scope to VM scope
132
- vm_scope = vm[1][:vapp_scoped_local_id]
133
- vapp_edge_scope = vapp_edge_rule[:vapp_scoped_local_id]
134
-
135
- if vm_scope == vapp_edge_scope
136
-
137
- # Generate DNAT Mappings for the valid machines
138
- # If rules don't match, you will not see them !
139
- network_table << [
140
- "#{vm[0]}",
141
- "#{cfg.vdc_edge_gateway_ip}:" +
142
- "#{vapp_edge_rule[:nat_external_port]}" +
143
- " -> #{vapp_edge_ip}:" +
144
- "#{vapp_edge_rule[:nat_external_port]}" +
145
- " -> #{vm[1][:addresses][0]}:" +
146
- "#{vapp_edge_rule[:nat_internal_port]}",
147
- edge_gateway_rule[:is_enabled]
148
- ]
149
- end
121
+ vapp_edge_rules.each do |vapp_edge_rule|
122
+ edge_gateway_rule = edge_gateway_rules.find {|r|
123
+ (r[:rule_type] == 'DNAT' &&
124
+ r[:original_ip] == cfg.vdc_edge_gateway_ip &&
125
+ r[:translated_ip] == vapp_edge_ip)}
126
+
127
+ # Loop on every VM in the vApp
128
+ vapp[:vms_hash].each do |vm|
129
+ # Only Map valid vAppEdge scope to VM scope
130
+ vm_scope = vm[1][:vapp_scoped_local_id]
131
+ vapp_edge_scope = vapp_edge_rule[:vapp_scoped_local_id]
132
+
133
+ if vm_scope == vapp_edge_scope
134
+
135
+ # Generate DNAT Mappings for the valid machines
136
+ # If rules don't match, you will not see them !
137
+ if edge_gateway_rule
138
+ # DNAT rule from edge to vapp to vm
139
+ network_table << [
140
+ "#{vm[0]}",
141
+ "#{cfg.vdc_edge_gateway_ip}:" +
142
+ "#{vapp_edge_rule[:nat_external_port]}" +
143
+ " -> #{vapp_edge_ip}:" +
144
+ "#{vapp_edge_rule[:nat_external_port]}" +
145
+ " -> #{vm[1][:addresses][0]}:" +
146
+ "#{vapp_edge_rule[:nat_internal_port]}",
147
+ edge_gateway_rule[:is_enabled]
148
+ ]
149
+ else
150
+ # DNAT rule only from vapp to vm
151
+ network_table << [
152
+ "#{vm[0]}",
153
+ "#{vapp_edge_ip}:" +
154
+ "#{vapp_edge_rule[:nat_external_port]}" +
155
+ " -> #{vm[1][:addresses][0]}:" +
156
+ "#{vapp_edge_rule[:nat_internal_port]}",
157
+ true
158
+ ]
150
159
  end
151
160
  end
152
161
  end
@@ -93,6 +93,12 @@ module VagrantPlugins
93
93
  # @return [String]
94
94
  attr_accessor :vdc_edge_gateway_ip
95
95
 
96
+ # Name of the vApp prefix [optional, defaults to 'Vagrant' ]
97
+ #
98
+ # @return [String]
99
+ attr_accessor :vapp_prefix
100
+
101
+
96
102
  ##
97
103
  ## vCloud Director config runtime values
98
104
  ##
@@ -309,7 +309,7 @@ module VagrantPlugins
309
309
  # Massive debug when LOG=DEBUG
310
310
  # Using awesome_print to get nice XML output for better readability
311
311
  if @logger.level == 1
312
- ap "SEND #{url}"
312
+ ap "SEND #{params['method'].upcase} #{url}"
313
313
  if payload
314
314
  payload_xml = Nokogiri.XML(payload)
315
315
  ap payload_xml
@@ -39,6 +39,7 @@ module VagrantPlugins
39
39
  @org_name = org_name
40
40
  @api_version = '5.1'
41
41
  @id = nil
42
+ @cached_vapp_edge_public_ips = {}
42
43
  end
43
44
 
44
45
  ##
@@ -630,19 +631,6 @@ module VagrantPlugins
630
631
  task_id
631
632
  end
632
633
 
633
- ##
634
- # Boot a given vm
635
- def poweron_vm(vm_id)
636
- params = {
637
- 'method' => :post,
638
- 'command' => "/vApp/vm-#{vm_id}/power/action/powerOn"
639
- }
640
-
641
- _response, headers = send_request(params)
642
- task_id = headers['Location'].gsub("#{@api_url}/task/", '')
643
- task_id
644
- end
645
-
646
634
  ##
647
635
  # Create a catalog in an organization
648
636
  def create_catalog(org_id, catalog_name, catalog_description)
@@ -1091,46 +1079,6 @@ module VagrantPlugins
1091
1079
  nat_rules
1092
1080
  end
1093
1081
 
1094
- ##
1095
- # Get vApp port forwarding rules external ports used and returns a set
1096
- # instead of an HASH.
1097
- #
1098
- # - vapp_id: id of the vApp
1099
- def get_vapp_port_forwarding_external_ports(vapp_id)
1100
- params = {
1101
- 'method' => :get,
1102
- 'command' => "/vApp/vapp-#{vapp_id}/networkConfigSection"
1103
- }
1104
-
1105
- response, _headers = send_request(params)
1106
-
1107
- # FIXME: this will return nil if the vApp uses multiple vApp Networks
1108
- # with Edge devices in natRouted/portForwarding mode.
1109
- config = response.css(
1110
- 'NetworkConfigSection/NetworkConfig/Configuration'
1111
- )
1112
- fence_mode = config.css('/FenceMode').text
1113
- nat_type = config.css('/Features/NatService/NatType').text
1114
-
1115
- unless fence_mode == 'natRouted'
1116
- raise InvalidStateError,
1117
- 'Invalid request because FenceMode must be natRouted.'
1118
- end
1119
-
1120
- unless nat_type == 'portForwarding'
1121
- raise InvalidStateError,
1122
- 'Invalid request because NatType must be portForwarding.'
1123
- end
1124
-
1125
- nat_rules = Set.new
1126
- config.css('/Features/NatService/NatRule').each do |rule|
1127
- # portforwarding rules information
1128
- vm_rule = rule.css('VmRule')
1129
- nat_rules.add(vm_rule.css('ExternalPort').text.to_i)
1130
- end
1131
- nat_rules
1132
- end
1133
-
1134
1082
  ##
1135
1083
  # Find an edge gateway id from the edge name and vdc_id
1136
1084
  #
@@ -1217,195 +1165,6 @@ module VagrantPlugins
1217
1165
  end
1218
1166
  end
1219
1167
 
1220
- ##
1221
- # Set Org Edge port forwarding and firewall rules
1222
- #
1223
- # - vapp_id: id of the vapp to be modified
1224
- # - network_name: name of the vapp network to be modified
1225
- # - config: hash with network configuration specifications,
1226
- # must contain an array inside :nat_rules with the nat rules
1227
- # to be applied.
1228
- def set_edge_gateway_rules(edge_gateway_name, vdc_id, edge_gateway_ip, vapp_id)
1229
- edge_vapp_ip = get_vapp_edge_public_ip(vapp_id)
1230
- edge_network_id = find_edge_gateway_network(
1231
- edge_gateway_name,
1232
- vdc_id,
1233
- edge_gateway_ip
1234
- )
1235
- edge_gateway_id = find_edge_gateway_id(edge_gateway_name, vdc_id)
1236
-
1237
- ### FIXME: tsugliani
1238
- # We need to check the previous variables, especially (edge_*)
1239
- # which can fail in some *weird* situations.
1240
- params = {
1241
- 'method' => :get,
1242
- 'command' => "/admin/edgeGateway/#{edge_gateway_id}"
1243
- }
1244
-
1245
- response, _headers = send_request(params)
1246
-
1247
- interesting = response.css(
1248
- 'EdgeGateway Configuration EdgeGatewayServiceConfiguration'
1249
- )
1250
-
1251
- nat_rule_1 = Nokogiri::XML::Node.new 'NatRule', response
1252
- rule_type = Nokogiri::XML::Node.new 'RuleType', response
1253
- rule_type.content = 'DNAT'
1254
- nat_rule_1.add_child rule_type
1255
-
1256
- is_enabled = Nokogiri::XML::Node.new 'IsEnabled', response
1257
- is_enabled.content = 'true'
1258
- nat_rule_1.add_child is_enabled
1259
-
1260
- gateway_nat_rule = Nokogiri::XML::Node.new 'GatewayNatRule',
1261
- response
1262
- nat_rule_1.add_child gateway_nat_rule
1263
-
1264
- interface = Nokogiri::XML::Node.new 'Interface', response
1265
- interface['href'] = edge_network_id
1266
-
1267
- gateway_nat_rule.add_child interface
1268
-
1269
- original_ip = Nokogiri::XML::Node.new 'OriginalIp', response
1270
- original_ip.content = edge_gateway_ip
1271
- gateway_nat_rule.add_child original_ip
1272
-
1273
- original_port = Nokogiri::XML::Node.new 'OriginalPort', response
1274
- original_port.content = 'any'
1275
- gateway_nat_rule.add_child original_port
1276
-
1277
- translated_ip = Nokogiri::XML::Node.new 'TranslatedIp', response
1278
- translated_ip.content = edge_vapp_ip
1279
- gateway_nat_rule.add_child translated_ip
1280
-
1281
- translated_port = Nokogiri::XML::Node.new 'TranslatedPort',
1282
- response
1283
- translated_port.content = 'any'
1284
- gateway_nat_rule.add_child translated_port
1285
-
1286
- protocol = Nokogiri::XML::Node.new 'Protocol', response
1287
- protocol.content = 'any'
1288
- gateway_nat_rule.add_child protocol
1289
-
1290
- # FIXME: frapposelli/tsugliani we should be able to remove this
1291
- # FIXME: test this against a vCloud Director 5.1.x installation
1292
- # icmpSubType = Nokogiri::XML::Node.new 'IcmpSubType', response
1293
- # icmpSubType.content = "any"
1294
- # gatewayNatRule.add_child icmpSubType
1295
-
1296
- nat_rule_2 = Nokogiri::XML::Node.new 'NatRule', response
1297
-
1298
- rule_type = Nokogiri::XML::Node.new 'RuleType', response
1299
- rule_type.content = 'SNAT'
1300
- nat_rule_2.add_child rule_type
1301
-
1302
- is_enabled = Nokogiri::XML::Node.new 'IsEnabled', response
1303
- is_enabled.content = 'true'
1304
- nat_rule_2.add_child is_enabled
1305
-
1306
- gateway_nat_rule = Nokogiri::XML::Node.new 'GatewayNatRule',
1307
- response
1308
- nat_rule_2.add_child gateway_nat_rule
1309
-
1310
- interface = Nokogiri::XML::Node.new 'Interface', response
1311
- interface['href'] = edge_network_id
1312
-
1313
- gateway_nat_rule.add_child interface
1314
-
1315
- original_ip = Nokogiri::XML::Node.new 'OriginalIp', response
1316
- original_ip.content = edge_vapp_ip
1317
- gateway_nat_rule.add_child original_ip
1318
-
1319
- translated_ip = Nokogiri::XML::Node.new 'TranslatedIp', response
1320
- translated_ip.content = edge_gateway_ip
1321
- gateway_nat_rule.add_child translated_ip
1322
-
1323
- protocol = Nokogiri::XML::Node.new 'Protocol', response
1324
- protocol.content = 'any'
1325
- gateway_nat_rule.add_child protocol
1326
-
1327
- firewall_rule_1 = Nokogiri::XML::Node.new 'FirewallRule', response
1328
-
1329
- is_enabled = Nokogiri::XML::Node.new 'IsEnabled', response
1330
- is_enabled.content = 'true'
1331
- firewall_rule_1.add_child is_enabled
1332
-
1333
- description = Nokogiri::XML::Node.new 'Description', response
1334
- description.content = 'Allow Vagrant Communications'
1335
- firewall_rule_1.add_child description
1336
-
1337
- policy = Nokogiri::XML::Node.new 'Policy', response
1338
- policy.content = 'allow'
1339
- firewall_rule_1.add_child policy
1340
-
1341
- protocols = Nokogiri::XML::Node.new 'Protocols', response
1342
- firewall_rule_1.add_child protocols
1343
-
1344
- any = Nokogiri::XML::Node.new 'Any', response
1345
- any.content = 'true'
1346
- protocols.add_child any
1347
-
1348
- destination_port_range =
1349
- Nokogiri::XML::Node.new 'DestinationPortRange', response
1350
- destination_port_range.content = 'Any'
1351
- firewall_rule_1.add_child destination_port_range
1352
-
1353
- destination_ip = Nokogiri::XML::Node.new 'DestinationIp', response
1354
- destination_ip.content = edge_gateway_ip
1355
- firewall_rule_1.add_child destination_ip
1356
- source_port_range = Nokogiri::XML::Node.new 'SourcePortRange',
1357
-
1358
- response
1359
- source_port_range.content = 'Any'
1360
- firewall_rule_1.add_child source_port_range
1361
-
1362
- source_ip = Nokogiri::XML::Node.new 'SourceIp', response
1363
- source_ip.content = 'Any'
1364
- firewall_rule_1.add_child source_ip
1365
-
1366
- enable_logging = Nokogiri::XML::Node.new 'EnableLogging', response
1367
- enable_logging.content = 'false'
1368
- firewall_rule_1.add_child enable_logging
1369
-
1370
- # FIXME: Think about adding an outgoing rule
1371
- # (which could not be available)
1372
- # by default in all cases vapp_edge_ip -> any
1373
- # Especially for provisionners using apt-get, internet, etc...
1374
- # (tsugliani)
1375
-
1376
- builder = Nokogiri::XML::Builder.new
1377
- builder << interesting
1378
-
1379
- set_edge_rules = Nokogiri::XML(builder.to_xml) do |config|
1380
- config.default_xml.noblanks
1381
- end
1382
-
1383
- nat_rules = set_edge_rules.at_css('NatService')
1384
- nat_rules << nat_rule_1
1385
- nat_rules << nat_rule_2
1386
-
1387
- fw_rules = set_edge_rules.at_css('FirewallService')
1388
- fw_rules << firewall_rule_1
1389
-
1390
- xml = set_edge_rules.at_css 'EdgeGatewayServiceConfiguration'
1391
- xml['xmlns'] = 'http://www.vmware.com/vcloud/v1.5'
1392
-
1393
- params = {
1394
- 'method' => :post,
1395
- 'command' => "/admin/edgeGateway/#{edge_gateway_id}/action/" +
1396
- 'configureServices'
1397
- }
1398
-
1399
- _response, headers = send_request(
1400
- params,
1401
- set_edge_rules.to_xml,
1402
- 'application/vnd.vmware.admin.edgeGatewayServiceConfiguration+xml'
1403
- )
1404
-
1405
- task_id = headers['Location'].gsub("#{@api_url}/task/", '')
1406
- task_id
1407
- end
1408
-
1409
1168
  ##
1410
1169
  # Get Org Edge port forwarding and firewall rules
1411
1170
  #
@@ -1541,6 +1300,145 @@ module VagrantPlugins
1541
1300
  task_id
1542
1301
  end
1543
1302
 
1303
+ #
1304
+ # Add Org Edge port forwarding and firewall rules
1305
+ #
1306
+ # - vapp_id: id of the vapp to be modified
1307
+ # - network_name: name of the vapp network to be modified
1308
+ # - ports: array with port numbers to forward 1:1 to vApp.
1309
+ def add_edge_gateway_rules(edge_gateway_name, vdc_id, edge_gateway_ip, vapp_id, ports)
1310
+ edge_vapp_ip = get_vapp_edge_public_ip(vapp_id)
1311
+ edge_network_id = find_edge_gateway_network(
1312
+ edge_gateway_name,
1313
+ vdc_id,
1314
+ edge_gateway_ip
1315
+ )
1316
+ edge_gateway_id = find_edge_gateway_id(edge_gateway_name, vdc_id)
1317
+
1318
+ ### FIXME: tsugliani
1319
+ # We need to check the previous variables, especially (edge_*)
1320
+ # which can fail in some *weird* situations.
1321
+ params = {
1322
+ 'method' => :get,
1323
+ 'command' => "/admin/edgeGateway/#{edge_gateway_id}"
1324
+ }
1325
+
1326
+ response, _headers = send_request(params)
1327
+
1328
+ interesting = response.css(
1329
+ 'EdgeGateway Configuration EdgeGatewayServiceConfiguration'
1330
+ )
1331
+
1332
+ add_snat_rule = true
1333
+ interesting.css('NatService NatRule').each do |node|
1334
+ if node.css('RuleType').text == 'DNAT' &&
1335
+ node.css('GatewayNatRule/OriginalIp').text == edge_gateway_ip &&
1336
+ node.css('GatewayNatRule/TranslatedIp').text == edge_vapp_ip &&
1337
+ node.css('GatewayNatRule/OriginalPort').text == 'any'
1338
+ # remove old DNAT rule any -> any from older vagrant-vcloud versions
1339
+ node.remove
1340
+ end
1341
+ if node.css('RuleType').text == 'SNAT' &&
1342
+ node.css('GatewayNatRule/OriginalIp').text == edge_vapp_ip &&
1343
+ node.css('GatewayNatRule/TranslatedIp').text == edge_gateway_ip
1344
+ add_snat_rule = false
1345
+ end
1346
+ end
1347
+
1348
+ add_firewall_rule = true
1349
+ interesting.css('FirewallService FirewallRule').each do |node|
1350
+ if node.css('Port').text == '-1' &&
1351
+ node.css('DestinationIp').text == edge_gateway_ip &&
1352
+ node.css('DestinationPortRange').text == 'Any'
1353
+ add_firewall_rule = false
1354
+ end
1355
+ end
1356
+
1357
+ builder = Nokogiri::XML::Builder.new
1358
+ builder << interesting
1359
+
1360
+ set_edge_rules = Nokogiri::XML(builder.to_xml) do |config|
1361
+ config.default_xml.noblanks
1362
+ end
1363
+
1364
+ nat_rules = set_edge_rules.at_css('NatService')
1365
+
1366
+ # Add all DNAT port rules edge -> vApp for the given list
1367
+ ports.each do |port|
1368
+ nat_rule = Nokogiri::XML::Builder.new do |xml|
1369
+ xml.NatRule {
1370
+ xml.RuleType 'DNAT'
1371
+ xml.IsEnabled 'true'
1372
+ xml.GatewayNatRule {
1373
+ xml.Interface('href' => edge_network_id )
1374
+ xml.OriginalIp edge_gateway_ip
1375
+ xml.OriginalPort port
1376
+ xml.TranslatedIp edge_vapp_ip
1377
+ xml.TranslatedPort port
1378
+ xml.Protocol 'tcpudp'
1379
+ }
1380
+ }
1381
+ end
1382
+ nat_rules << nat_rule.doc.root.to_xml
1383
+ end
1384
+
1385
+ if (add_snat_rule)
1386
+ snat_rule = Nokogiri::XML::Builder.new do |xml|
1387
+ xml.NatRule {
1388
+ xml.RuleType 'SNAT'
1389
+ xml.IsEnabled 'true'
1390
+ xml.GatewayNatRule {
1391
+ xml.Interface('href' => edge_network_id )
1392
+ xml.OriginalIp edge_vapp_ip
1393
+ xml.TranslatedIp edge_gateway_ip
1394
+ xml.Protocol 'any'
1395
+ }
1396
+ }
1397
+ end
1398
+ nat_rules << snat_rule.doc.root.to_xml
1399
+ end
1400
+
1401
+
1402
+ if (add_firewall_rule)
1403
+ firewall_rule_1 = Nokogiri::XML::Builder.new do |xml|
1404
+ xml.FirewallRule {
1405
+ xml.IsEnabled 'true'
1406
+ xml.Description 'Allow Vagrant Communications'
1407
+ xml.Policy 'allow'
1408
+ xml.Protocols {
1409
+ xml.Any 'true'
1410
+ }
1411
+ xml.DestinationPortRange 'Any'
1412
+ xml.DestinationIp edge_gateway_ip
1413
+ xml.SourcePortRange 'Any'
1414
+ xml.SourceIp 'Any'
1415
+ xml.EnableLogging 'false'
1416
+ }
1417
+ end
1418
+ fw_rules = set_edge_rules.at_css('FirewallService')
1419
+ fw_rules << firewall_rule_1.doc.root.to_xml
1420
+ end
1421
+
1422
+ xml = set_edge_rules.at_css 'EdgeGatewayServiceConfiguration'
1423
+ xml['xmlns'] = 'http://www.vmware.com/vcloud/v1.5'
1424
+
1425
+ params = {
1426
+ 'method' => :post,
1427
+ 'command' => "/admin/edgeGateway/#{edge_gateway_id}/action/" +
1428
+ 'configureServices'
1429
+ }
1430
+
1431
+ _response, headers = send_request(
1432
+ params,
1433
+ set_edge_rules.to_xml,
1434
+ 'application/vnd.vmware.admin.edgeGatewayServiceConfiguration+xml'
1435
+ )
1436
+
1437
+ task_id = headers['Location'].gsub("#{@api_url}/task/", '')
1438
+ task_id
1439
+ end
1440
+
1441
+
1544
1442
  ##
1545
1443
  # get vApp edge public IP from the vApp ID
1546
1444
  # Only works when:
@@ -1550,6 +1448,8 @@ module VagrantPlugins
1550
1448
  # This will be required to know how to connect to VMs behind the Edge
1551
1449
  # device.
1552
1450
  def get_vapp_edge_public_ip(vapp_id)
1451
+ return @cached_vapp_edge_public_ips[vapp_id] unless @cached_vapp_edge_public_ips[vapp_id].nil?
1452
+
1553
1453
  # Check the network configuration section
1554
1454
  params = {
1555
1455
  'method' => :get,
@@ -1583,6 +1483,7 @@ module VagrantPlugins
1583
1483
  if edge_ip == ''
1584
1484
  return nil
1585
1485
  else
1486
+ @cached_vapp_edge_public_ips[vapp_id] = edge_ip
1586
1487
  return edge_ip
1587
1488
  end
1588
1489
  end
@@ -18,6 +18,9 @@ module VagrantPlugins
18
18
  options = scoped_hash_override(options, :vcloud)
19
19
  id = options[:id]
20
20
 
21
+ # skip forwarded rules already found in handle_nat_port_collisions
22
+ next if options[:already_exists]
23
+
21
24
  mappings[host_port] =
22
25
  Model::ForwardedPort.new(id, host_port, guest_port, options)
23
26
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module VCloud
3
- VERSION = '0.2.2'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-vcloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabio Rapposelli
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-09 00:00:00.000000000 Z
12
+ date: 2014-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: i18n
@@ -201,13 +201,15 @@ files:
201
201
  - lib/vagrant-vcloud/action/announce_ssh_exec.rb
202
202
  - lib/vagrant-vcloud/action/build_vapp.rb
203
203
  - lib/vagrant-vcloud/action/connect_vcloud.rb
204
- - lib/vagrant-vcloud/action/destroy.rb
204
+ - lib/vagrant-vcloud/action/destroy_vapp.rb
205
+ - lib/vagrant-vcloud/action/destroy_vm.rb
205
206
  - lib/vagrant-vcloud/action/disconnect_vcloud.rb
206
207
  - lib/vagrant-vcloud/action/forward_ports.rb
207
208
  - lib/vagrant-vcloud/action/handle_nat_port_collisions.rb
208
209
  - lib/vagrant-vcloud/action/inventory_check.rb
209
210
  - lib/vagrant-vcloud/action/is_bridged.rb
210
211
  - lib/vagrant-vcloud/action/is_created.rb
212
+ - lib/vagrant-vcloud/action/is_last_vm.rb
211
213
  - lib/vagrant-vcloud/action/is_paused.rb
212
214
  - lib/vagrant-vcloud/action/is_running.rb
213
215
  - lib/vagrant-vcloud/action/message_already_running.rb
@@ -215,6 +217,7 @@ files:
215
217
  - lib/vagrant-vcloud/action/message_not_created.rb
216
218
  - lib/vagrant-vcloud/action/message_will_not_destroy.rb
217
219
  - lib/vagrant-vcloud/action/power_off.rb
220
+ - lib/vagrant-vcloud/action/power_off_vapp.rb
218
221
  - lib/vagrant-vcloud/action/power_on.rb
219
222
  - lib/vagrant-vcloud/action/read_ssh_info.rb
220
223
  - lib/vagrant-vcloud/action/read_state.rb
@@ -1,66 +0,0 @@
1
- module VagrantPlugins
2
- module VCloud
3
- module Action
4
- class Destroy
5
- def initialize(app, env)
6
- @app = app
7
- @logger = Log4r::Logger.new('vagrant_vcloud::action::destroy')
8
- end
9
-
10
- def call(env)
11
- cfg = env[:machine].provider_config
12
- cnx = cfg.vcloud_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.org_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
- if test_vapp[:vms_hash].count == 1
26
- env[:ui].info('Single VM left in the vApp, destroying the vApp...')
27
-
28
- if cfg.vdc_edge_gateway_ip && cfg.vdc_edge_gateway
29
- env[:ui].info(
30
- "Removing NAT rules on [#{cfg.vdc_edge_gateway}] " +
31
- "for IP [#{cfg.vdc_edge_gateway_ip}]."
32
- )
33
- @logger.debug(
34
- "Deleting Edge Gateway rules - vdc id: #{cfg.vdc_id}"
35
- )
36
- edge_remove = cnx.remove_edge_gateway_rules(
37
- cfg.vdc_edge_gateway,
38
- cfg.vdc_id,
39
- cfg.vdc_edge_gateway_ip,
40
- vapp_id
41
- )
42
- cnx.wait_task_completion(edge_remove)
43
- end
44
-
45
- env[:ui].info('Destroying vApp...')
46
- vapp_delete_task = cnx.delete_vapp(vapp_id)
47
- @logger.debug("vApp Delete task id #{vapp_delete_task}")
48
- cnx.wait_task_completion(vapp_delete_task)
49
-
50
- env[:machine].id = nil
51
- env[:machine].vappid = nil
52
- else
53
- env[:ui].info('Destroying VM...')
54
- vm_delete_task = cnx.delete_vm(vm_id)
55
- @logger.debug("VM Delete task id #{vm_delete_task}")
56
- cnx.wait_task_completion(vm_delete_task)
57
-
58
- env[:machine].id = nil
59
- end
60
-
61
- @app.call env
62
- end
63
- end
64
- end
65
- end
66
- end