Class: VagrantPlugins::Utm::Driver::Base
- Inherits:
-
Object
- Object
- VagrantPlugins::Utm::Driver::Base
- Includes:
- Vagrant::Util::Retryable
- Defined in:
- lib/vagrant_utm/driver/base.rb
Overview
Executes commands on the host machine through the AppleScript bridge interface paired with a command line interface.
Direct Known Subclasses
Instance Method Summary collapse
-
#check_qemu_guest_agent ⇒ Boolean
Checks if the qemu-guest-agent is installed and running in this VM.
-
#clear_forwarded_ports ⇒ Object
Clears the forwarded ports that have been set on the virtual machine.
-
#delete ⇒ void
Deletes the virtual machine references by this driver.
-
#execute(*command, &block) ⇒ String
Execute the given subcommand for utmctl and return the output.
-
#execute_osa_script(command) ⇒ Object
Execute a script using the OSA interface.
-
#execute_shell(*command, &block) ⇒ Object
Execute a shell command and return the output.
-
#forward_ports(ports) ⇒ Object
Forwards a set of ports for a VM.
-
#halt ⇒ Object
Halts the virtual machine (pulls the plug).
-
#import(utm_file) ⇒ uuid
Import a virtual machine from a UTM file.
-
#initialize ⇒ Base
constructor
A new instance of Base.
-
#last_uuid ⇒ uuid
Return UUID of the last VM in the list.
-
#list ⇒ ListResult
Execute the ‘list’ command and returns the list of machines.
-
#random_mac_address ⇒ String
Generate a random MAC address.
-
#raw(*command, &block) ⇒ Object
Executes a utmctl command and returns the raw result object.
-
#raw_shell(*command, &block) ⇒ Object
Executes a command and returns the raw result object.
-
#read_forwarded_ports(uuid = nil) ⇒ Array<Array>
[nic, name(hostport), hostport, guestport].
-
#read_guest_ip ⇒ Array<String>
Returns the IP addresses of the guest machine.
-
#read_network_interfaces ⇒ Hash
Returns a list of network interfaces of the VM.
-
#read_state ⇒ Symbol
Returns the current state of this VM.
-
#read_used_ports(active_only: true) ⇒ Array
Returns a list of all forwarded ports in use by active virtual machines.
-
#read_vms ⇒ Array<String>
Returns a list of all UUIDs of virtual machines currently known by UTM.
-
#set_mac_address(mac) ⇒ Object
Sets the MAC address of the first network adapter.
-
#set_name(name) ⇒ void
Sets the name of the virtual machine.
-
#ssh_port(expected) ⇒ Object
Reads the SSH port of this VM.
-
#start ⇒ void
Starts the virtual machine referenced by this driver.
-
#start_disposable ⇒ void
Starts the virtual machine in disposable mode.
-
#suspend ⇒ Object
Suspend the virtual machine.
-
#verify! ⇒ Object
Verifies that the driver is ready to accept work.
-
#vm_exists?(uuid) ⇒ Boolean
Check if the VM with the given UUID (Name) exists.
Constructor Details
#initialize ⇒ Base
Returns a new instance of Base.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/vagrant_utm/driver/base.rb', line 19 def initialize @logger = Log4r::Logger.new("vagrant::provider::utm::base") # This flag is used to keep track of interrupted state (SIGINT) @interrupted = false # The path to the scripts directory. @script_path = Pathname.new(File.("../scripts", __dir__)) # Set 'utmctl' path @utmctl_path = Vagrant::Util::Which.which("utmctl") # if not found, fall back to /usr/local/bin/utmctl @utmctl_path ||= "/Applications/UTM.app/Contents/MacOS/utmctl" @logger.info("utmctl path: #{@utmctl_path}") end |
Instance Method Details
#check_qemu_guest_agent ⇒ Boolean
Checks if the qemu-guest-agent is installed and running in this VM.
40 |
# File 'lib/vagrant_utm/driver/base.rb', line 40 def check_qemu_guest_agent; end |
#clear_forwarded_ports ⇒ Object
Clears the forwarded ports that have been set on the virtual machine.
36 |
# File 'lib/vagrant_utm/driver/base.rb', line 36 def clear_forwarded_ports; end |
#delete ⇒ void
This method returns an undefined value.
Deletes the virtual machine references by this driver.
140 |
# File 'lib/vagrant_utm/driver/base.rb', line 140 def delete; end |
#execute(*command, &block) ⇒ String
Execute the given subcommand for utmctl and return the output. Copied from github.com/hashicorp/vagrant/blob/main/plugins/providers/virtualbox/driver/base.rb.
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/vagrant_utm/driver/base.rb', line 252 def execute(*command, &block) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity # Get the options hash if it exists opts = {} opts = command.pop if command.last.is_a?(Hash) tries = 0 tries = 3 if opts[:retryable] # Variable to store our execution result r = nil retryable(on: Errors::UtmctlError, tries: tries, sleep: 1) do # rubocop:disable Metrics/BlockLength # if there is an error with utmctl, this gets set to true errored = false # Execute the command r = raw(*command, &block) # If the command was a failure, then raise an exception that is # nicely handled by Vagrant. if r.exit_code != 0 if @interrupted @logger.info("Exit code != 0, but interrupted. Ignoring.") elsif r.exit_code == 126 # To be consistent with VBoxManage raise Errors::UtmctlNotFoundError else errored = true end else # if utmctl fails but doesn't exit with an error code # Handle those cases here if r.stderr =~ /Error/ @logger.info("Error found, assuming error.") errored = true end if r.stderr =~ /OSStatus error/ @logger.info("OSStatus error found, assuming error.") errored = true end end # If there was an error running utmctl, show the error and the output if errored raise Errors::UtmctlError, command: command.inspect, stderr: r.stderr, stdout: r.stdout end end # Return the output, making sure to replace any Windows-style # newlines with Unix-style. r.stdout.gsub("\r\n", "\n") end |
#execute_osa_script(command) ⇒ Object
Execute a script using the OSA interface.
173 |
# File 'lib/vagrant_utm/driver/base.rb', line 173 def execute_osa_script(command); end |
#execute_shell(*command, &block) ⇒ Object
Execute a shell command and return the output.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/vagrant_utm/driver/base.rb', line 176 def execute_shell(*command, &block) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity # Get the options hash if it exists opts = {} opts = command.pop if command.last.is_a?(Hash) tries = 0 tries = 3 if opts[:retryable] # Variable to store our execution result r = nil retryable(on: VagrantPlugins::Utm::Errors::CommandError, tries: tries, sleep: 1) do # If there is an error with VBoxManage, this gets set to true errored = false # Execute the command r = raw_shell(*command, &block) # If the command was a failure, then raise an exception that is # nicely handled by Vagrant. if r.exit_code != 0 if @interrupted @logger.info("Exit code != 0, but interrupted. Ignoring.") else errored = true end end if errored raise VagrantPlugins::Utm::Errors::CommandError, command: command.inspect, stderr: r.stderr, stdout: r.stdout end end # Return the output, making sure to replace any Windows-style # newlines with Unix-style. # AppleScript logs are always in stderr, so we return that # if there is any output. if r.stdout && !r.stdout.empty? r.stdout.gsub("\r\n", "\n") elsif r.stderr && !r.stderr.empty? r.stderr.gsub("\r\n", "\n") else "" end end |
#forward_ports(ports) ⇒ Object
Forwards a set of ports for a VM.
This will not affect any previously set forwarded ports, so be sure to delete those if you need to.
The format of each port hash should be the following:
{
name: "foo",
hostport: 8500,
guestport: 80,
adapter: 1,
protocol: "tcp"
}
Note that “adapter” and “protocol” are optional and will default to 1 and “tcp” respectively.
62 |
# File 'lib/vagrant_utm/driver/base.rb', line 62 def forward_ports(ports); end |
#halt ⇒ Object
Halts the virtual machine (pulls the plug).
147 |
# File 'lib/vagrant_utm/driver/base.rb', line 147 def halt; end |
#import(utm_file) ⇒ uuid
Import a virtual machine from a UTM file.
118 |
# File 'lib/vagrant_utm/driver/base.rb', line 118 def import(utm_file); end |
#last_uuid ⇒ uuid
Return UUID of the last VM in the list.
144 |
# File 'lib/vagrant_utm/driver/base.rb', line 144 def last_uuid; end |
#list ⇒ ListResult
Execute the ‘list’ command and returns the list of machines.
113 |
# File 'lib/vagrant_utm/driver/base.rb', line 113 def list; end |
#random_mac_address ⇒ String
Generate a random MAC address.
This method generates a random MAC address because it is difficult to get UTM to generate one through scripting.
163 164 165 166 167 168 169 170 |
# File 'lib/vagrant_utm/driver/base.rb', line 163 def random_mac_address # Generate 6 random bytes bytes = Array.new(6) { rand(256) } # Ensure the first byte is local bytes[0] = (bytes[0] & 0xFC) | 0x02 # Convert bytes to MAC address string bytes.map { |byte| format("%02X", byte) }.join(":") end |
#raw(*command, &block) ⇒ Object
Executes a utmctl command and returns the raw result object.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/vagrant_utm/driver/base.rb', line 312 def raw(*command, &block) int_callback = lambda do @interrupted = true # We have to execute this in a thread due to trap contexts # and locks. Thread.new { @logger.info("Interrupted.") }.join end # Append in the options for subprocess # NOTE: We include the LANG env var set to C to prevent command output # from being localized command << { notify: i[stdout stderr], env: env_lang } Vagrant::Util::Busy.busy(int_callback) do Vagrant::Util::Subprocess.execute(@utmctl_path, *command, &block) end rescue Vagrant::Util::Subprocess::LaunchError => e raise Vagrant::Errors::UtmLaunchError, message: e.to_s end |
#raw_shell(*command, &block) ⇒ Object
Executes a command and returns the raw result object.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/vagrant_utm/driver/base.rb', line 226 def raw_shell(*command, &block) int_callback = lambda do @interrupted = true # We have to execute this in a thread due to trap contexts # and locks. Thread.new { @logger.info("Interrupted.") }.join end # Append in the options for subprocess # NOTE: We include the LANG env var set to C to prevent command output # from being localized command << { notify: i[stdout stderr], env: env_lang } Vagrant::Util::Busy.busy(int_callback) do Vagrant::Util::Subprocess.execute(*command, &block) end rescue Vagrant::Util::Subprocess::LaunchError => e raise Vagrant::Errors::UtmLaunchError, message: e.to_s end |
#read_forwarded_ports(uuid = nil) ⇒ Array<Array>
- nic, name(hostport), hostport, guestport
74 |
# File 'lib/vagrant_utm/driver/base.rb', line 74 def read_forwarded_ports(uuid = nil); end |
#read_guest_ip ⇒ Array<String>
Returns the IP addresses of the guest machine. Only supported for VMs with qemu-guest-agent installed.
99 |
# File 'lib/vagrant_utm/driver/base.rb', line 99 def read_guest_ip; end |
#read_network_interfaces ⇒ Hash
Returns a list of network interfaces of the VM.
104 |
# File 'lib/vagrant_utm/driver/base.rb', line 104 def read_network_interfaces; end |
#read_state ⇒ Symbol
Returns the current state of this VM.
79 |
# File 'lib/vagrant_utm/driver/base.rb', line 79 def read_state; end |
#read_used_ports(active_only: true) ⇒ Array
Returns a list of all forwarded ports in use by active virtual machines.
87 |
# File 'lib/vagrant_utm/driver/base.rb', line 87 def read_used_ports(active_only: true); end |
#read_vms ⇒ Array<String>
Returns a list of all UUIDs of virtual machines currently known by UTM.
93 |
# File 'lib/vagrant_utm/driver/base.rb', line 93 def read_vms; end |
#set_mac_address(mac) ⇒ Object
Sets the MAC address of the first network adapter.
109 |
# File 'lib/vagrant_utm/driver/base.rb', line 109 def set_mac_address(mac); end |
#set_name(name) ⇒ void
This method returns an undefined value.
Sets the name of the virtual machine.
123 |
# File 'lib/vagrant_utm/driver/base.rb', line 123 def set_name(name); end |
#ssh_port(expected) ⇒ Object
Reads the SSH port of this VM.
128 |
# File 'lib/vagrant_utm/driver/base.rb', line 128 def ssh_port(expected); end |
#start ⇒ void
This method returns an undefined value.
Starts the virtual machine referenced by this driver.
132 |
# File 'lib/vagrant_utm/driver/base.rb', line 132 def start; end |
#start_disposable ⇒ void
This method returns an undefined value.
Starts the virtual machine in disposable mode.
136 |
# File 'lib/vagrant_utm/driver/base.rb', line 136 def start_disposable; end |
#suspend ⇒ Object
Suspend the virtual machine.
150 |
# File 'lib/vagrant_utm/driver/base.rb', line 150 def suspend; end |
#verify! ⇒ Object
Verifies that the driver is ready to accept work.
This should raise a VagrantError if things are not ready.
155 |
# File 'lib/vagrant_utm/driver/base.rb', line 155 def verify!; end |
#vm_exists?(uuid) ⇒ Boolean
Check if the VM with the given UUID (Name) exists.
65 |
# File 'lib/vagrant_utm/driver/base.rb', line 65 def vm_exists?(uuid); end |