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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE +20 -0
  5. data/README.md +80 -0
  6. data/Rakefile +17 -0
  7. data/example_box/README.md +13 -0
  8. data/example_box/Vagrantfile +6 -0
  9. data/example_box/metadata.json +1 -0
  10. data/lib/vagrant-vcloud.rb +65 -0
  11. data/lib/vagrant-vcloud/action.rb +226 -0
  12. data/lib/vagrant-vcloud/action/announce_ssh_exec.rb +17 -0
  13. data/lib/vagrant-vcloud/action/build_vapp.rb +197 -0
  14. data/lib/vagrant-vcloud/action/connect_vcloud.rb +68 -0
  15. data/lib/vagrant-vcloud/action/destroy.rb +69 -0
  16. data/lib/vagrant-vcloud/action/disconnect_vcloud.rb +33 -0
  17. data/lib/vagrant-vcloud/action/forward_ports.rb +127 -0
  18. data/lib/vagrant-vcloud/action/handle_nat_port_collisions.rb +129 -0
  19. data/lib/vagrant-vcloud/action/inventory_check.rb +156 -0
  20. data/lib/vagrant-vcloud/action/is_created.rb +36 -0
  21. data/lib/vagrant-vcloud/action/is_paused.rb +22 -0
  22. data/lib/vagrant-vcloud/action/is_running.rb +22 -0
  23. data/lib/vagrant-vcloud/action/message_already_running.rb +17 -0
  24. data/lib/vagrant-vcloud/action/message_cannot_suspend.rb +17 -0
  25. data/lib/vagrant-vcloud/action/message_not_created.rb +17 -0
  26. data/lib/vagrant-vcloud/action/message_will_not_destroy.rb +17 -0
  27. data/lib/vagrant-vcloud/action/power_off.rb +33 -0
  28. data/lib/vagrant-vcloud/action/power_on.rb +46 -0
  29. data/lib/vagrant-vcloud/action/read_ssh_info.rb +69 -0
  30. data/lib/vagrant-vcloud/action/read_state.rb +59 -0
  31. data/lib/vagrant-vcloud/action/resume.rb +33 -0
  32. data/lib/vagrant-vcloud/action/suspend.rb +33 -0
  33. data/lib/vagrant-vcloud/action/sync_folders.rb +82 -0
  34. data/lib/vagrant-vcloud/action/unmap_port_forwardings.rb +75 -0
  35. data/lib/vagrant-vcloud/config.rb +132 -0
  36. data/lib/vagrant-vcloud/driver/base.rb +459 -0
  37. data/lib/vagrant-vcloud/driver/meta.rb +151 -0
  38. data/lib/vagrant-vcloud/driver/version_5_1.rb +1669 -0
  39. data/lib/vagrant-vcloud/errors.rb +62 -0
  40. data/lib/vagrant-vcloud/model/forwarded_port.rb +64 -0
  41. data/lib/vagrant-vcloud/plugin.rb +78 -0
  42. data/lib/vagrant-vcloud/provider.rb +41 -0
  43. data/lib/vagrant-vcloud/util/compile_forwarded_ports.rb +31 -0
  44. data/lib/vagrant-vcloud/version.rb +5 -0
  45. data/locales/en.yml +55 -0
  46. data/vagrant-vcloud.gemspec +34 -0
  47. 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