vagrant-vcloud 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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