vagrant-veertu 0.0.12

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +31 -0
  5. data/Rakefile +5 -0
  6. data/lib/vagrant-veertu.rb +18 -0
  7. data/lib/vagrant-veertu/action.rb +330 -0
  8. data/lib/vagrant-veertu/action/boot.rb +21 -0
  9. data/lib/vagrant-veertu/action/check_accessible.rb +22 -0
  10. data/lib/vagrant-veertu/action/check_created.rb +21 -0
  11. data/lib/vagrant-veertu/action/check_running.rb +21 -0
  12. data/lib/vagrant-veertu/action/check_veertu.rb +22 -0
  13. data/lib/vagrant-veertu/action/clear_forwarded_ports.rb +20 -0
  14. data/lib/vagrant-veertu/action/clear_network_interfaces.rb +31 -0
  15. data/lib/vagrant-veertu/action/created.rb +20 -0
  16. data/lib/vagrant-veertu/action/customize.rb +44 -0
  17. data/lib/vagrant-veertu/action/destroy.rb +19 -0
  18. data/lib/vagrant-veertu/action/discard_state.rb +20 -0
  19. data/lib/vagrant-veertu/action/export.rb +41 -0
  20. data/lib/vagrant-veertu/action/forced_halt.rb +25 -0
  21. data/lib/vagrant-veertu/action/forward_ports.rb +91 -0
  22. data/lib/vagrant-veertu/action/import.rb +96 -0
  23. data/lib/vagrant-veertu/action/is_paused.rb +20 -0
  24. data/lib/vagrant-veertu/action/is_running.rb +20 -0
  25. data/lib/vagrant-veertu/action/is_saved.rb +20 -0
  26. data/lib/vagrant-veertu/action/message_already_running.rb +16 -0
  27. data/lib/vagrant-veertu/action/message_not_created.rb +16 -0
  28. data/lib/vagrant-veertu/action/message_not_running.rb +16 -0
  29. data/lib/vagrant-veertu/action/message_will_not_destroy.rb +17 -0
  30. data/lib/vagrant-veertu/action/network.rb +556 -0
  31. data/lib/vagrant-veertu/action/network_fix_ipv6.rb +81 -0
  32. data/lib/vagrant-veertu/action/package.rb +44 -0
  33. data/lib/vagrant-veertu/action/package_vagrantfile.rb +33 -0
  34. data/lib/vagrant-veertu/action/prepare_forwarded_port_collision_params.rb +35 -0
  35. data/lib/vagrant-veertu/action/prepare_nfs_settings.rb +119 -0
  36. data/lib/vagrant-veertu/action/prepare_nfs_valid_ids.rb +17 -0
  37. data/lib/vagrant-veertu/action/resume.rb +21 -0
  38. data/lib/vagrant-veertu/action/sane_defaults.rb +89 -0
  39. data/lib/vagrant-veertu/action/set_name.rb +55 -0
  40. data/lib/vagrant-veertu/action/setup_package_files.rb +51 -0
  41. data/lib/vagrant-veertu/action/snapshot_delete.rb +32 -0
  42. data/lib/vagrant-veertu/action/snapshot_restore.rb +28 -0
  43. data/lib/vagrant-veertu/action/snapshot_save.rb +25 -0
  44. data/lib/vagrant-veertu/action/suspend.rb +20 -0
  45. data/lib/vagrant-veertu/cap.rb +23 -0
  46. data/lib/vagrant-veertu/cap/public_address.rb +15 -0
  47. data/lib/vagrant-veertu/config.rb +199 -0
  48. data/lib/vagrant-veertu/driver/base.rb +240 -0
  49. data/lib/vagrant-veertu/driver/meta.rb +143 -0
  50. data/lib/vagrant-veertu/driver/version_5_0.rb +284 -0
  51. data/lib/vagrant-veertu/errors.rb +18 -0
  52. data/lib/vagrant-veertu/model/forwarded_port.rb +70 -0
  53. data/lib/vagrant-veertu/plugin.rb +76 -0
  54. data/lib/vagrant-veertu/provider.rb +121 -0
  55. data/lib/vagrant-veertu/synced_folder.rb +120 -0
  56. data/lib/vagrant-veertu/util/compile_forwarded_ports.rb +35 -0
  57. data/lib/vagrant-veertu/version.rb +5 -0
  58. data/locales/en.yml +19 -0
  59. data/vagrant-veertu.gemspec +22 -0
  60. metadata +130 -0
@@ -0,0 +1,240 @@
1
+ require 'log4r'
2
+ require 'inifile'
3
+
4
+ require 'vagrant/util/busy'
5
+ require 'vagrant/util/platform'
6
+ require 'vagrant/util/retryable'
7
+ require 'vagrant/util/subprocess'
8
+ require 'vagrant/util/which'
9
+
10
+ module VagrantPlugins
11
+ module ProviderVeertu
12
+ module Driver
13
+ # Base class for all VeertuManage drivers.
14
+ #
15
+ # This class provides useful tools for things such as executing
16
+ # VeertuManage and handling SIGINTs and so on.
17
+ class Base
18
+ # Include this so we can use `Subprocess` more easily.
19
+ include Vagrant::Util::Retryable
20
+
21
+ def initialize
22
+ @logger = Log4r::Logger.new("vagrant::provider::veertu::base")
23
+
24
+ # This flag is used to keep track of interrupted state (SIGINT)
25
+ @interrupted = false
26
+
27
+ ini_file = File.expand_path("~/.veertu_config")
28
+ if File.exist?(ini_file) then
29
+ file = IniFile.load(ini_file)
30
+ @veertumanage_path = file['VAGRANT']['manage_path']
31
+ end
32
+ @veertumanage_path ||= "/Applications/Veertu.app/Contents/SharedSupport/VeertuManage"
33
+
34
+ @logger.info("VeertuManage path: #{@veertumanage_path}")
35
+ end
36
+
37
+ # Clears the forwarded ports that have been set on the virtual machine.
38
+ def clear_forwarded_ports
39
+ end
40
+
41
+ def max_network_adapters
42
+ 36
43
+ end
44
+
45
+ # Deletes the virtual machine references by this driver.
46
+ def delete
47
+ end
48
+
49
+ # Execute a raw command straight through to VeertuManage.
50
+ #
51
+ # Accepts a retryable: true option if the command should be retried
52
+ # upon failure.
53
+ #
54
+ # Raises a VeertuManage error if it fails.
55
+ #
56
+ # @param [Array] command Command to execute.
57
+ def execute_command(command)
58
+ end
59
+
60
+ # Exports the virtual machine to the given path.
61
+ #
62
+ # @param [String] path Path to the OVF file.
63
+ # @yield [progress] Yields the block with the progress of the export.
64
+ def export(path)
65
+ raise NotImplementedError("please export manually")
66
+ end
67
+
68
+ # Forwards a set of ports for a VM.
69
+ #
70
+ # This will not affect any previously set forwarded ports,
71
+ # so be sure to delete those if you need to.
72
+ #
73
+ # The format of each port hash should be the following:
74
+ #
75
+ # {
76
+ # name: "foo",
77
+ # hostport: 8500,
78
+ # guestport: 80,
79
+ # adapter: 1,
80
+ # protocol: "tcp"
81
+ # }
82
+ #
83
+ # Note that "adapter" and "protocol" are optional and will default
84
+ # to 1 and "tcp" respectively.
85
+ #
86
+ # @param [Array<Hash>] ports An array of ports to set. See documentation
87
+ # for more information on the format.
88
+ def forward_ports(ports)
89
+ end
90
+
91
+ # Halts the virtual machine (pulls the plug).
92
+ def halt
93
+ end
94
+
95
+ # Imports the VM from an box file.
96
+ #
97
+ # @param [String] box Path to the box file.
98
+ # @return [String] UUID of the imported VM.
99
+ def import(box)
100
+ end
101
+
102
+
103
+ # Returns a list of forwarded ports for a VM.
104
+ #
105
+ # @param [String] uuid UUID of the VM to read from, or `nil` if this
106
+ # VM.
107
+ # @param [Boolean] active_only If true, only VMs that are running will
108
+ # be checked.
109
+ # @return [Array<Array>]
110
+ def read_forwarded_ports(uuid=nil, active_only=false)
111
+ end
112
+
113
+ # Returns the current state of this VM.
114
+ #
115
+ # @return [Symbol]
116
+ def read_state
117
+ end
118
+
119
+ # Returns a list of all forwarded ports in use by active
120
+ # virtual machines.
121
+ #
122
+ # @return [Array]
123
+ def read_used_ports
124
+ end
125
+
126
+ # Returns a list of all UUIDs of virtual machines currently
127
+ # known by VirtualBox.
128
+ #
129
+ # @return [Array<String>]
130
+ def read_vms
131
+ end
132
+
133
+ # Share a set of folders on this VM.
134
+ #
135
+ # @param [Array<Hash>] folders
136
+ def share_folders(folders)
137
+ end
138
+
139
+ # Reads the SSH port of this VM.
140
+ #
141
+ # @param [Integer] expected Expected guest port of SSH.
142
+ def ssh_port(expected)
143
+ end
144
+
145
+ # Starts the virtual machine.
146
+ #
147
+ # @param [String] mode Mode to boot the VM. Either "headless"
148
+ # or "gui"
149
+ def start(mode)
150
+ end
151
+
152
+ # Suspend the virtual machine.
153
+ def suspend
154
+ end
155
+
156
+
157
+ # Verifies that the driver is ready to accept work.
158
+ #
159
+ # This should raise a VagrantError if things are not ready.
160
+ def verify!
161
+ end
162
+
163
+
164
+ # Checks if a VM with the given UUID exists.
165
+ #
166
+ # @return [Boolean]
167
+ def vm_exists?(uuid)
168
+ end
169
+
170
+ # Execute the given subcommand for VeertuManage and return the output.
171
+ def execute(*command, &block)
172
+ # Get the options hash if it exists
173
+ opts = {}
174
+ opts = command.pop if command.last.is_a?(Hash)
175
+
176
+ tries = 0
177
+ tries = 3 if opts[:retryable]
178
+
179
+ # Variable to store our execution result
180
+ r = nil
181
+
182
+ retryable(on: VagrantPlugins::ProviderVeertu::Errors::VeertuManageError, tries: tries, sleep: 1) do
183
+ # If there is an error with VeertuManage, this gets set to true
184
+ errored = false
185
+
186
+ # Execute the command
187
+ r = raw(*command, &block)
188
+
189
+ # If the command was a failure, then raise an exception that is
190
+ # nicely handled by Vagrant.
191
+ if r.exit_code != 0
192
+ if @interrupted
193
+ @logger.info("Exit code != 0, but interrupted. Ignoring.")
194
+ elsif r.exit_code == 126
195
+ # This exit code happens if VeertuManage is on the PATH,
196
+ # but another executable it tries to execute is missing.
197
+ raise Errors::VeertuManageNotFoundError
198
+ else
199
+ errored = true
200
+ end
201
+ end
202
+
203
+ # If there was an error running VeertuManage, show the error and the
204
+ # output.
205
+ if errored
206
+ raise VagrantPlugins::ProviderVeertu::Errors::VeertuManageError,
207
+ command: command.inspect,
208
+ stderr: r.stderr,
209
+ stdout: r.stdout
210
+ end
211
+ end
212
+
213
+ r.stdout.gsub("\r\n", "\n")
214
+ end
215
+
216
+ # Executes a command and returns the raw result object.
217
+ def raw(*command, &block)
218
+ int_callback = lambda do
219
+ @interrupted = true
220
+
221
+ # We have to execute this in a thread due to trap contexts
222
+ # and locks.
223
+ Thread.new { @logger.info("Interrupted.") }.join
224
+ end
225
+
226
+ # Append in the options for subprocess
227
+ command << { notify: [:stdout, :stderr] }
228
+
229
+ Vagrant::Util::Busy.busy(int_callback) do
230
+ @logger.debug(YAML::dump(command))
231
+ Vagrant::Util::Subprocess.execute(@veertumanage_path, *command, &block)
232
+ end
233
+ rescue Vagrant::Util::Subprocess::LaunchError => e
234
+ raise Vagrant::Errors::VBoxManageLaunchError,
235
+ message: e.to_s
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,143 @@
1
+ require "forwardable"
2
+ require "thread"
3
+
4
+ require "log4r"
5
+
6
+ require "vagrant/util/retryable"
7
+
8
+ require File.expand_path("../base", __FILE__)
9
+
10
+ module VagrantPlugins
11
+ module ProviderVeertu
12
+ module Driver
13
+ class Meta < Base
14
+ # This is raised if the VM is not found when initializing a driver
15
+ # with a UUID.
16
+ class VMNotFound < StandardError; end
17
+
18
+ # We use forwardable to do all our driver forwarding
19
+ extend Forwardable
20
+
21
+ # We cache the read VirtualBox version here once we have one,
22
+ # since during the execution of Vagrant, it likely doesn't change.
23
+ @@version = nil
24
+ @@version_lock = Mutex.new
25
+
26
+ # The UUID of the virtual machine we represent
27
+ attr_reader :uuid
28
+
29
+ # The version of virtualbox that is running.
30
+ attr_reader :version
31
+
32
+ include Vagrant::Util::Retryable
33
+
34
+ def initialize(uuid=nil)
35
+ # Setup the base
36
+ super()
37
+
38
+ @logger = Log4r::Logger.new("vagrant::provider::veertu::meta")
39
+ @uuid = uuid
40
+
41
+ @@version_lock.synchronize do
42
+ if !@@version
43
+ # Read and assign the version of VirtualBox we know which
44
+ # specific driver to instantiate.
45
+ begin
46
+ @@version = read_version
47
+ rescue Vagrant::Errors::CommandUnavailable,
48
+ Vagrant::Errors::CommandUnavailableWindows
49
+ # This means that VirtualBox was not found, so we raise this
50
+ # error here.
51
+ raise Vagrant::Errors::VirtualBoxNotDetected
52
+ end
53
+ end
54
+ end
55
+
56
+ # Instantiate the proper version driver for Veertu
57
+ @logger.debug("Finding driver for Veertu version: #{@@version}")
58
+ driver_map = {
59
+ "5.0" => Version_5_0,
60
+ }
61
+
62
+ driver_klass = nil
63
+ driver_map.each do |key, klass|
64
+ if @@version.start_with?(key)
65
+ driver_klass = klass
66
+ break
67
+ end
68
+ end
69
+
70
+ if !driver_klass
71
+ supported_versions = driver_map.keys.sort.join(", ")
72
+ raise Vagrant::Errors::VirtualBoxInvalidVersion,
73
+ supported_versions: supported_versions
74
+ end
75
+
76
+ @logger.info("Using VirtualBox driver: #{driver_klass}")
77
+ @driver = driver_klass.new(@uuid)
78
+ @version = @@version
79
+
80
+ if @uuid
81
+ # Verify the VM exists, and if it doesn't, then don't worry
82
+ # about it (mark the UUID as nil)
83
+ raise VMNotFound if !@driver.vm_exists?(@uuid)
84
+ end
85
+ end
86
+
87
+ def_delegators :@driver, :clear_forwarded_ports,
88
+ :clear_shared_folders,
89
+ :clonevm,
90
+ :create_dhcp_server,
91
+ :create_host_only_network,
92
+ :create_snapshot,
93
+ :delete,
94
+ :delete_snapshot,
95
+ :delete_unused_host_only_networks,
96
+ :discard_saved_state,
97
+ :enable_adapters,
98
+ :execute_command,
99
+ :export,
100
+ :forward_ports,
101
+ :halt,
102
+ :import,
103
+ :list_snapshots,
104
+ :read_forwarded_ports,
105
+ :read_bridged_interfaces,
106
+ :read_dhcp_servers,
107
+ :read_guest_additions_version,
108
+ :read_guest_ip,
109
+ :read_guest_property,
110
+ :read_host_only_interfaces,
111
+ :read_mac_address,
112
+ :read_mac_addresses,
113
+ :read_machine_folder,
114
+ :read_network_interfaces,
115
+ :read_state,
116
+ :read_used_ports,
117
+ :read_vms,
118
+ :reconfig_host_only,
119
+ :remove_dhcp_server,
120
+ :restore_snapshot,
121
+ :resume,
122
+ :set_mac_address,
123
+ :set_name,
124
+ :share_folders,
125
+ :ssh_port,
126
+ :start,
127
+ :suspend,
128
+ :verify!,
129
+ :verify_image,
130
+ :vm_exists?
131
+
132
+ protected
133
+
134
+ # This returns the version of VirtualBox that is running.
135
+ #
136
+ # @return [String]
137
+ def read_version
138
+ '5.0'
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,284 @@
1
+ require 'log4r'
2
+ require 'json'
3
+ require "vagrant/util/platform"
4
+
5
+ require File.expand_path("../base", __FILE__)
6
+
7
+ module VagrantPlugins
8
+ module ProviderVeertu
9
+ module Driver
10
+ # Driver for Veertu 1.2.0.x
11
+ class Version_5_0 < Base
12
+ def initialize(uuid)
13
+ super()
14
+
15
+ @logger = Log4r::Logger.new("vagrant::provider::veertu_5_0")
16
+ @uuid = uuid
17
+ end
18
+
19
+ def read_bridged_interfaces
20
+ raise Errors::VeertuUnsupported, action: 'bridged interfaces'
21
+ end
22
+
23
+ def clear_forwarded_ports
24
+ read_forwarded_ports(@uuid).each do |nic, name, _, _|
25
+ execute("modify", @uuid, 'delete', '--port-forwarding', name)
26
+ end
27
+ end
28
+
29
+ def delete
30
+ execute("delete",'--yes', @uuid)
31
+ end
32
+
33
+ def execute_command(command)
34
+ execute(*command)
35
+ end
36
+
37
+ def export(path)
38
+ execute("export", @uuid, "--output", path.to_s)
39
+ end
40
+
41
+ def forward_ports(ports)
42
+ ports.each do |options|
43
+ name = options[:name]
44
+ protocol = options[:protocol] || "tcp"
45
+ host_ip = options[:hostip] || "127.0.0.1"
46
+ host_port = options[:hostport]
47
+ guest_ip = options[:guestip] || ""
48
+ guest_port = options[:guestport]
49
+ execute('--machine-readable', 'modify', @uuid, 'add', '--port-forwarding', name, '--host-ip',
50
+ host_ip, '--host-port', host_port.to_s, '--protocol', protocol, '--guest-ip',
51
+ guest_ip, '--guest-port', guest_port.to_s)
52
+
53
+ end
54
+ end
55
+
56
+ def get_machine_id(machine_name)
57
+ vm = get_vm_info(machine_name)
58
+ return vm['id']
59
+ end
60
+
61
+ def set_name(name)
62
+ execute('modify', @uuid, 'set', '--rename', '--name', name)
63
+ end
64
+
65
+ def halt
66
+ execute("shutdown", @uuid)
67
+ end
68
+
69
+ def import(box)
70
+ box = Vagrant::Util::Platform.cygwin_windows_path(box)
71
+
72
+ output = ""
73
+ total = ""
74
+ last = 0
75
+
76
+ # Dry-run the import to get the suggested name and path
77
+ @logger.debug("Doing dry-run import to determine parallel-safe name...")
78
+ output = execute("import", "-n", box)
79
+ result = /Suggested VM name "(.+?)"/.match(output)
80
+ if !result
81
+ raise Vagrant::Errors::VirtualBoxNoName, output: output
82
+ end
83
+ suggested_name = result[1].to_s
84
+
85
+ # Append millisecond plus a random to the path in case we're
86
+ # importing the same box elsewhere.
87
+ specified_name = "#{suggested_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
88
+ @logger.debug("-- Parallel safe name: #{specified_name}")
89
+
90
+ # Build the specified name param list
91
+ name_params = [
92
+ "--os-family", "0",
93
+ "--name", specified_name,
94
+ ]
95
+
96
+ # Extract the disks list and build the disk target params
97
+ disk_params = []
98
+ disks = output.scan(/(\d+): Hard disk image: source image=.+, target path=(.+),/)
99
+ disks.each do |unit_num, path|
100
+ disk_params << "--vsys"
101
+ disk_params << "0"
102
+ disk_params << "--unit"
103
+ disk_params << unit_num
104
+ disk_params << "--disk"
105
+ disk_params << path.reverse.sub("/#{suggested_name}/".reverse, "/#{specified_name}/".reverse).reverse # Replace only last occurrence
106
+ end
107
+ success_json = execute("--machine-readable", "import", box , *name_params, *disk_params)
108
+ begin
109
+ success = JSON.parse(success_json)
110
+ if success['status'] == 'ok'
111
+ puts 'imported successfully'
112
+ end
113
+ rescue JSON::ParserError
114
+ puts 'json parse error'
115
+ return nil
116
+ end
117
+ puts specified_name
118
+ machine_id = get_machine_id(specified_name)
119
+ puts machine_id
120
+ return machine_id
121
+ end
122
+
123
+ def read_forwarded_ports(uuid=nil, active_only=false)
124
+ uuid ||= @uuid
125
+
126
+ @logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}")
127
+
128
+ results = []
129
+ current_nic = 'nat'
130
+ vm_info = get_vm_info(uuid)
131
+ if active_only && vm_info['status'] != "running"
132
+ return []
133
+ end
134
+ port_forwarding_rules = vm_info['port_forwarding']
135
+
136
+ port_forwarding_rules.each do |rule|
137
+ result = [current_nic, rule['name'], rule['host_port'], rule['guest_port']]
138
+ results << result
139
+ @logger.debug(" - #{result.inspect}")
140
+ end
141
+
142
+ results
143
+ end
144
+
145
+ def read_host_only_interfaces
146
+ vms_array = get_vm_list()
147
+ info = {}
148
+ vms_array.each do |vm|
149
+ info['name'] = vm['name']
150
+ info['uuid'] = vm['id']
151
+ end
152
+ info
153
+ end
154
+
155
+ def read_network_interfaces
156
+ return { '0' => {:type => :nat}}
157
+ end
158
+
159
+ def read_state
160
+ vm = get_vm_info(@uuid)
161
+ status = vm['status']
162
+ @logger.debug('getting machine status')
163
+ @logger.debug(status)
164
+ return status.to_sym
165
+ end
166
+
167
+ def read_used_ports
168
+ ports = []
169
+ vms_array = get_vm_list()
170
+ vms_array.each do |vm|
171
+ # Ignore our own used ports
172
+ uuid = vm['uuid']
173
+ next if uuid == @uuid
174
+
175
+ read_forwarded_ports(uuid, true).each do |_, _, hostport, _|
176
+ ports << hostport
177
+ end
178
+ end
179
+
180
+ ports
181
+ end
182
+
183
+ def read_guest_ip(adapter_number)
184
+ vm_info = get_vm_info(@uuid)
185
+ return vm_info['ip']
186
+ end
187
+
188
+ def read_vms
189
+ results = {}
190
+ vms = get_vm_list()
191
+ vms.each do |vm|
192
+ results[vm[:id]] = vm[:name]
193
+ end
194
+ results
195
+ end
196
+
197
+
198
+ def ssh_port(expected_port)
199
+ expected_port = expected_port.to_s
200
+ @logger.debug("Searching for SSH port: #{expected_port.inspect}")
201
+
202
+ # Look for the forwarded port only by comparing the guest port
203
+ read_forwarded_ports.each do |_, _, hostport, guestport|
204
+ if guestport == expected_port
205
+ return hostport
206
+ end
207
+ end
208
+
209
+ nil
210
+ end
211
+
212
+ def resume
213
+ start(nil)
214
+ end
215
+
216
+ def start(mode)
217
+ if mode == 'headless'
218
+ execute('--machine-readable', 'modify', @uuid, 'set', '--headless', '1')
219
+ elsif mode == 'gui'
220
+ execute('--machine-readable', 'modify', @uuid, 'set', '--headless', '0')
221
+ end
222
+ json_success = execute('--machine-readable', 'start', @uuid)
223
+ result = JSON.parse(json_success)
224
+ if result['status'] == 'ok'
225
+ return true
226
+ end
227
+
228
+ # If we reached this point then it didn't work out.
229
+ raise Vagrant::Errors::VBoxManageError,
230
+ command: command.inspect,
231
+ stderr: r.stderr
232
+ end
233
+
234
+ def suspend
235
+ execute("pause", @uuid)
236
+ end
237
+
238
+ def verify!
239
+ # This command sometimes fails if kernel drivers aren't properly loaded
240
+ # so we just run the command and verify that it succeeded.
241
+ execute("list", retryable: true)
242
+ end
243
+
244
+ def vm_exists?(uuid)
245
+ 5.times do |i|
246
+ info = get_vm_info(uuid)
247
+ if info
248
+ return true
249
+ else
250
+ return false
251
+ end
252
+ sleep 2
253
+ end
254
+
255
+ # If we reach this point, it means that we consistently got the
256
+ # failure, do a standard vboxmanage now. This will raise an
257
+ # exception if it fails again.
258
+ execute("show", uuid)
259
+ return true
260
+ end
261
+
262
+ protected
263
+
264
+ def get_vm_list()
265
+ vms_json = execute("--machine-readable", "list", retryable: true)
266
+ vms = JSON.parse(vms_json)
267
+ return vms
268
+ end
269
+
270
+ def get_vm_info(uuid)
271
+ # puts caller
272
+ begin
273
+ vm_info_json = execute('--machine-readable', 'show', uuid, retryable: true)
274
+ vm_info = JSON.parse(vm_info_json)
275
+ return vm_info
276
+ rescue JSON::ParserError
277
+ return nil
278
+ end
279
+ end
280
+
281
+ end
282
+ end
283
+ end
284
+ end