vagrant-vcloud 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.md +80 -0
- data/Rakefile +17 -0
- data/example_box/README.md +13 -0
- data/example_box/Vagrantfile +6 -0
- data/example_box/metadata.json +1 -0
- data/lib/vagrant-vcloud.rb +65 -0
- data/lib/vagrant-vcloud/action.rb +226 -0
- data/lib/vagrant-vcloud/action/announce_ssh_exec.rb +17 -0
- data/lib/vagrant-vcloud/action/build_vapp.rb +197 -0
- data/lib/vagrant-vcloud/action/connect_vcloud.rb +68 -0
- data/lib/vagrant-vcloud/action/destroy.rb +69 -0
- data/lib/vagrant-vcloud/action/disconnect_vcloud.rb +33 -0
- data/lib/vagrant-vcloud/action/forward_ports.rb +127 -0
- data/lib/vagrant-vcloud/action/handle_nat_port_collisions.rb +129 -0
- data/lib/vagrant-vcloud/action/inventory_check.rb +156 -0
- data/lib/vagrant-vcloud/action/is_created.rb +36 -0
- data/lib/vagrant-vcloud/action/is_paused.rb +22 -0
- data/lib/vagrant-vcloud/action/is_running.rb +22 -0
- data/lib/vagrant-vcloud/action/message_already_running.rb +17 -0
- data/lib/vagrant-vcloud/action/message_cannot_suspend.rb +17 -0
- data/lib/vagrant-vcloud/action/message_not_created.rb +17 -0
- data/lib/vagrant-vcloud/action/message_will_not_destroy.rb +17 -0
- data/lib/vagrant-vcloud/action/power_off.rb +33 -0
- data/lib/vagrant-vcloud/action/power_on.rb +46 -0
- data/lib/vagrant-vcloud/action/read_ssh_info.rb +69 -0
- data/lib/vagrant-vcloud/action/read_state.rb +59 -0
- data/lib/vagrant-vcloud/action/resume.rb +33 -0
- data/lib/vagrant-vcloud/action/suspend.rb +33 -0
- data/lib/vagrant-vcloud/action/sync_folders.rb +82 -0
- data/lib/vagrant-vcloud/action/unmap_port_forwardings.rb +75 -0
- data/lib/vagrant-vcloud/config.rb +132 -0
- data/lib/vagrant-vcloud/driver/base.rb +459 -0
- data/lib/vagrant-vcloud/driver/meta.rb +151 -0
- data/lib/vagrant-vcloud/driver/version_5_1.rb +1669 -0
- data/lib/vagrant-vcloud/errors.rb +62 -0
- data/lib/vagrant-vcloud/model/forwarded_port.rb +64 -0
- data/lib/vagrant-vcloud/plugin.rb +78 -0
- data/lib/vagrant-vcloud/provider.rb +41 -0
- data/lib/vagrant-vcloud/util/compile_forwarded_ports.rb +31 -0
- data/lib/vagrant-vcloud/version.rb +5 -0
- data/locales/en.yml +55 -0
- data/vagrant-vcloud.gemspec +34 -0
- metadata +273 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
require "set"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module VCloud
|
6
|
+
module Action
|
7
|
+
# This middleware class will detect and handle collisions with
|
8
|
+
# forwarded ports, whether that means raising an error or repairing
|
9
|
+
# them automatically.
|
10
|
+
#
|
11
|
+
# Parameters it takes from the environment hash:
|
12
|
+
#
|
13
|
+
# * `:port_collision_repair` - If true, it will attempt to repair
|
14
|
+
# port collisions. If false, it will raise an exception when
|
15
|
+
# there is a collision.
|
16
|
+
#
|
17
|
+
# * `:port_collision_extra_in_use` - An array of ports that are
|
18
|
+
# considered in use.
|
19
|
+
#
|
20
|
+
# * `:port_collision_remap` - A hash remapping certain host ports
|
21
|
+
# to other host ports.
|
22
|
+
#
|
23
|
+
class HandleNATPortCollisions
|
24
|
+
|
25
|
+
def initialize(app, env)
|
26
|
+
@app = app
|
27
|
+
@logger = Log4r::Logger.new("vagrant_vcloud::action::handle_port_collisions")
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
@logger.info("Detecting any forwarded port collisions...")
|
32
|
+
|
33
|
+
# Determine a list of usable ports for repair
|
34
|
+
usable_ports = Set.new(env[:machine].config.vm.usable_port_range)
|
35
|
+
|
36
|
+
@logger.debug("USABLE PORTS: #{usable_ports.inspect}")
|
37
|
+
|
38
|
+
# Pass one, remove all defined host ports from usable ports
|
39
|
+
with_forwarded_ports(env) do |options|
|
40
|
+
usable_ports.delete(options[:host])
|
41
|
+
end
|
42
|
+
|
43
|
+
@logger.debug("USABLE PORTS AFTER IN USE DELETION: #{usable_ports.inspect}")
|
44
|
+
|
45
|
+
cfg = env[:machine].provider_config
|
46
|
+
cnx = cfg.vcloud_cnx.driver
|
47
|
+
vmName = env[:machine].name
|
48
|
+
vAppId = env[:machine].get_vapp_id
|
49
|
+
|
50
|
+
@logger.debug("Getting vapp info...")
|
51
|
+
vm = cnx.get_vapp(vAppId)
|
52
|
+
myhash = vm[:vms_hash][vmName.to_sym]
|
53
|
+
|
54
|
+
@logger.debug("Getting port forwarding rules...")
|
55
|
+
rules = cnx.get_vapp_port_forwarding_external_ports(vAppId)
|
56
|
+
|
57
|
+
# Pass two, detect/handle any collisions
|
58
|
+
with_forwarded_ports(env) do |options|
|
59
|
+
guest_port = options[:guest]
|
60
|
+
host_port = options[:host]
|
61
|
+
|
62
|
+
#testHash = rules.flatten
|
63
|
+
@logger.debug("DEBUGGING NETWORKS: rules: #{rules.inspect}")
|
64
|
+
|
65
|
+
# If the port is open (listening for TCP connections)
|
66
|
+
if rules.include?(host_port)
|
67
|
+
@logger.debug("SO OUR PORT IS INCLUDED IN RULES BUT WHAT'S IN OPTIONS?: #{options.inspect}")
|
68
|
+
if !options[:auto_correct]
|
69
|
+
raise Errors::ForwardPortCollision,
|
70
|
+
:guest_port => guest_port.to_s,
|
71
|
+
:host_port => host_port.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
@logger.info("Attempting to repair FP collision: #{host_port}")
|
75
|
+
|
76
|
+
repaired_port = nil
|
77
|
+
while !usable_ports.empty?
|
78
|
+
# Attempt to repair the forwarded port
|
79
|
+
repaired_port = usable_ports.to_a.sort[0]
|
80
|
+
usable_ports.delete(repaired_port)
|
81
|
+
|
82
|
+
# If the port is in use, then we can't use this either...
|
83
|
+
if rules.include?(repaired_port)
|
84
|
+
@logger.info("Repaired port also in use: #{repaired_port}. Trying another...")
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
# We have a port so break out
|
89
|
+
break
|
90
|
+
end
|
91
|
+
|
92
|
+
# If we have no usable ports then we can't repair
|
93
|
+
if !repaired_port && usable_ports.empty?
|
94
|
+
raise Errors::ForwardPortAutolistEmpty,
|
95
|
+
:vm_name => env[:machine].name,
|
96
|
+
:guest_port => guest_port.to_s,
|
97
|
+
:host_port => host_port.to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
# Modify the args in place
|
101
|
+
options[:host] = repaired_port
|
102
|
+
|
103
|
+
@logger.info("Repaired FP collision: #{host_port} to #{repaired_port}")
|
104
|
+
|
105
|
+
# Notify the user
|
106
|
+
env[:ui].info(I18n.t("vagrant.actions.vm.forward_ports.fixed_collision",
|
107
|
+
:host_port => host_port.to_s,
|
108
|
+
:guest_port => guest_port.to_s,
|
109
|
+
:new_port => repaired_port.to_s))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
@app.call(env)
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
def with_forwarded_ports(env)
|
119
|
+
env[:machine].config.vm.networks.each do |type, options|
|
120
|
+
# Ignore anything but forwarded ports
|
121
|
+
next if type != :forwarded_port
|
122
|
+
|
123
|
+
yield options
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require "etc"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module VCloud
|
6
|
+
module Action
|
7
|
+
class InventoryCheck
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_vcloud::action::inventory_check")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
vcloud_check_inventory(env)
|
16
|
+
|
17
|
+
@app.call env
|
18
|
+
end
|
19
|
+
|
20
|
+
def vcloud_upload_box(env)
|
21
|
+
|
22
|
+
cfg = env[:machine].provider_config
|
23
|
+
cnx = cfg.vcloud_cnx.driver
|
24
|
+
|
25
|
+
boxDir = env[:machine].box.directory.to_s
|
26
|
+
boxFile = env[:machine].box.name.to_s
|
27
|
+
|
28
|
+
boxOVF = "#{boxDir}/#{boxFile}.ovf"
|
29
|
+
|
30
|
+
### Still relying on ruby-progressbar because report_progress basically sucks.
|
31
|
+
|
32
|
+
@logger.debug("OVF File: #{boxOVF}")
|
33
|
+
uploadOVF = cnx.upload_ovf(
|
34
|
+
cfg.vdc_id,
|
35
|
+
env[:machine].box.name.to_s,
|
36
|
+
"Vagrant Box",
|
37
|
+
boxOVF,
|
38
|
+
cfg.catalog_id,
|
39
|
+
{
|
40
|
+
:progressbar_enable => true
|
41
|
+
#:chunksize => 262144
|
42
|
+
}
|
43
|
+
)
|
44
|
+
|
45
|
+
env[:ui].info("Adding [#{env[:machine].box.name.to_s}] to Catalog [#{cfg.catalog_name}]")
|
46
|
+
addOVFtoCatalog = cnx.wait_task_completion(uploadOVF)
|
47
|
+
|
48
|
+
if !addOVFtoCatalog[:errormsg].nil?
|
49
|
+
raise Errors::CatalogAddError, :message => addOVFtoCatalog[:errormsg]
|
50
|
+
end
|
51
|
+
|
52
|
+
## Retrieve catalog_item ID
|
53
|
+
cfg.catalog_item = cnx.get_catalog_item_by_name(cfg.catalog_id, env[:machine].box.name.to_s)
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def vcloud_create_catalog(env)
|
58
|
+
cfg = env[:machine].provider_config
|
59
|
+
cnx = cfg.vcloud_cnx.driver
|
60
|
+
|
61
|
+
catalogCreation = cnx.create_catalog(cfg.org_id, cfg.catalog_name, "Created by #{Etc.getlogin} running on #{Socket.gethostname.downcase} using vagrant-vcloud on #{Time.now.strftime("%B %d, %Y")}")
|
62
|
+
cnx.wait_task_completion(catalogCreation[:task_id])
|
63
|
+
|
64
|
+
@logger.debug("Catalog Creation result: #{catalogCreation.inspect}")
|
65
|
+
|
66
|
+
env[:ui].info("Catalog [#{cfg.catalog_name}] created successfully.")
|
67
|
+
|
68
|
+
cfg.catalog_id = catalogCreation[:catalog_id]
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def vcloud_check_inventory(env)
|
73
|
+
# Will check each mandatory config value against the vCloud Director
|
74
|
+
# Instance and will setup the global environment config values
|
75
|
+
cfg = env[:machine].provider_config
|
76
|
+
cnx = cfg.vcloud_cnx.driver
|
77
|
+
|
78
|
+
cfg.org = cnx.get_organization_by_name(cfg.org_name)
|
79
|
+
cfg.org_id = cnx.get_organization_id_by_name(cfg.org_name)
|
80
|
+
|
81
|
+
cfg.vdc = cnx.get_vdc_by_name(cfg.org, cfg.vdc_name)
|
82
|
+
cfg.vdc_id = cnx.get_vdc_id_by_name(cfg.org, cfg.vdc_name)
|
83
|
+
|
84
|
+
cfg.catalog = cnx.get_catalog_by_name(cfg.org, cfg.catalog_name)
|
85
|
+
|
86
|
+
|
87
|
+
@logger.debug("BEFORE get_catalog_id_by_name")
|
88
|
+
cfg.catalog_id = cnx.get_catalog_id_by_name(cfg.org, cfg.catalog_name)
|
89
|
+
@logger.debug("AFTER get_catalog_id_by_name: #{cfg.catalog_id}")
|
90
|
+
|
91
|
+
|
92
|
+
if cfg.catalog_id.nil?
|
93
|
+
env[:ui].warn("Catalog [#{cfg.catalog_name}] does not exist!")
|
94
|
+
|
95
|
+
user_input = env[:ui].ask(
|
96
|
+
"Would you like to create the [#{cfg.catalog_name}] catalog?\nChoice (yes/no): "
|
97
|
+
)
|
98
|
+
|
99
|
+
# FIXME: add an OR clause for just Y
|
100
|
+
if user_input.downcase == "yes"
|
101
|
+
vcloud_create_catalog(env)
|
102
|
+
else
|
103
|
+
env[:ui].error("Catalog not created, exiting...")
|
104
|
+
|
105
|
+
raise VagrantPlugins::VCloud::Errors::VCloudError,
|
106
|
+
:message => "Catalog not available, exiting..."
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
@logger.debug("Getting catalog item with cfg.catalog_id: [#{cfg.catalog_id}] and machine name [#{env[:machine].box.name.to_s}]")
|
113
|
+
cfg.catalog_item = cnx.get_catalog_item_by_name(cfg.catalog_id, env[:machine].box.name.to_s)
|
114
|
+
@logger.debug("Catalog item is now #{cfg.catalog_item}")
|
115
|
+
cfg.vdc_network_id = cfg.org[:networks][cfg.vdc_network_name]
|
116
|
+
|
117
|
+
|
118
|
+
# Checking Catalog mandatory requirements
|
119
|
+
if !cfg.catalog_id
|
120
|
+
@logger.info("Catalog [#{cfg.catalog_name}] STILL does not exist!")
|
121
|
+
raise VagrantPlugins::VCloud::Errors::VCloudError,
|
122
|
+
:message => "Catalog not available, exiting..."
|
123
|
+
|
124
|
+
else
|
125
|
+
@logger.info("Catalog [#{cfg.catalog_name}] exists")
|
126
|
+
end
|
127
|
+
|
128
|
+
if !cfg.catalog_item
|
129
|
+
env[:ui].warn("Catalog item [#{env[:machine].box.name.to_s}] in Catalog [#{cfg.catalog_name}] does not exist!")
|
130
|
+
|
131
|
+
user_input = env[:ui].ask(
|
132
|
+
"Would you like to upload the [#{env[:machine].box.name.to_s}] box to "\
|
133
|
+
"[#{cfg.catalog_name}] Catalog?\nChoice (yes/no): "
|
134
|
+
)
|
135
|
+
|
136
|
+
# FIXME: add an OR clause for just Y
|
137
|
+
if user_input.downcase == "yes"
|
138
|
+
env[:ui].info("Uploading [#{env[:machine].box.name.to_s}]...")
|
139
|
+
vcloud_upload_box(env)
|
140
|
+
else
|
141
|
+
env[:ui].error("Catalog item not available, exiting...")
|
142
|
+
|
143
|
+
raise VagrantPlugins::VCloud::Errors::VCloudError,
|
144
|
+
:message => "Catalog item not available, exiting..."
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
else
|
149
|
+
#env[:ui].info("Using catalog item [#{env[:machine].box.name.to_s}] in Catalog [#{cfg.catalog_name}]...")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloud
|
3
|
+
module Action
|
4
|
+
class IsCreated
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@logger = Log4r::Logger.new("vagrant_vcloud::action::is_created")
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
|
12
|
+
vAppId = env[:machine].get_vapp_id
|
13
|
+
|
14
|
+
if vAppId.nil?
|
15
|
+
@logger.warn("vApp has not been created")
|
16
|
+
env[:result] = false
|
17
|
+
else
|
18
|
+
@logger.info("vApp has been created and ID is: [#{vAppId}]")
|
19
|
+
|
20
|
+
vmId = env[:machine].id
|
21
|
+
if vmId
|
22
|
+
@logger.info("VM has been added to vApp and ID is: [#{vmId}]")
|
23
|
+
env[:result] = true
|
24
|
+
else
|
25
|
+
@logger.warn("VM has not been added to vApp")
|
26
|
+
env[:result] = false
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
@app.call env
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "i18n"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VCloud
|
5
|
+
module Action
|
6
|
+
class IsPaused
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
# Set the result to be true if the machine is suspended.
|
13
|
+
env[:result] = env[:machine].state.id == :suspended
|
14
|
+
|
15
|
+
# Call the next if we have one (but we shouldn't, since this
|
16
|
+
# middleware is built to run with the Call-type middlewares)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "i18n"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VCloud
|
5
|
+
module Action
|
6
|
+
class IsRunning
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
# Set the result to be true if the machine is running.
|
13
|
+
env[:result] = env[:machine].state.id == :running
|
14
|
+
|
15
|
+
# Call the next if we have one (but we shouldn't, since this
|
16
|
+
# middleware is built to run with the Call-type middlewares)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloud
|
3
|
+
module Action
|
4
|
+
class MessageAlreadyRunning
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# FIXME: This error should be categorized
|
11
|
+
env[:ui].info(I18n.t("vagrant_vcloud.vm_already_running"))
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloud
|
3
|
+
module Action
|
4
|
+
class MessageCannotSuspend
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# FIXME: This error should be categorized
|
11
|
+
env[:ui].info(I18n.t("vagrant_vcloud.vm_halted_cannot_suspend"))
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloud
|
3
|
+
module Action
|
4
|
+
class MessageNotCreated
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# FIXME: this error should be categorized
|
11
|
+
env[:ui].info(I18n.t("vcloud.vm_not_created"))
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VCloud
|
3
|
+
module Action
|
4
|
+
class MessageWillNotDestroy
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# FIXME: This error should be categorized
|
11
|
+
env[:ui].info(I18n.t("vagrant_vcloud.will_not_destroy", name: env[:machine].name))
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|