vagrant_utm 0.0.1
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/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +59 -0
- data/Rakefile +12 -0
- data/docs/.gitignore +15 -0
- data/docs/Gemfile +10 -0
- data/docs/Gemfile.lock +276 -0
- data/docs/README.md +174 -0
- data/docs/_config.yml +76 -0
- data/docs/_includes/footer_custom.html +3 -0
- data/docs/_sass/gallery.scss +64 -0
- data/docs/_virtual_machines/archlinux-arm.md +13 -0
- data/docs/assets/images/favicon.ico +0 -0
- data/docs/assets/images/logo.png +0 -0
- data/docs/assets/images/screens/archlinux-logo.png +0 -0
- data/docs/assets/images/screens/debian-11-xfce-arm64.png +0 -0
- data/docs/boxes/creating_utm_box.md +70 -0
- data/docs/boxes/index.md +6 -0
- data/docs/boxes/utm_box_gallery.md +117 -0
- data/docs/commands.md +156 -0
- data/docs/configuration.md +51 -0
- data/docs/features/index.md +5 -0
- data/docs/features/synced_folders.md +28 -0
- data/docs/index.md +103 -0
- data/docs/internals/actions.md +20 -0
- data/docs/internals/index.md +5 -0
- data/docs/internals/status.md +25 -0
- data/docs/internals/utm_api.md +31 -0
- data/docs/known_issues.md +24 -0
- data/lib/vagrant_utm/action/boot.rb +22 -0
- data/lib/vagrant_utm/action/boot_disposable.rb +22 -0
- data/lib/vagrant_utm/action/check_accessible.rb +33 -0
- data/lib/vagrant_utm/action/check_created.rb +24 -0
- data/lib/vagrant_utm/action/check_guest_additions.rb +37 -0
- data/lib/vagrant_utm/action/check_qemu_img.rb +21 -0
- data/lib/vagrant_utm/action/check_running.rb +25 -0
- data/lib/vagrant_utm/action/check_utm.rb +30 -0
- data/lib/vagrant_utm/action/clear_forwarded_ports.rb +26 -0
- data/lib/vagrant_utm/action/created.rb +26 -0
- data/lib/vagrant_utm/action/customize.rb +50 -0
- data/lib/vagrant_utm/action/destroy.rb +25 -0
- data/lib/vagrant_utm/action/download_confirm.rb +19 -0
- data/lib/vagrant_utm/action/export.rb +22 -0
- data/lib/vagrant_utm/action/forced_halt.rb +28 -0
- data/lib/vagrant_utm/action/forward_ports.rb +90 -0
- data/lib/vagrant_utm/action/import.rb +63 -0
- data/lib/vagrant_utm/action/is_paused.rb +26 -0
- data/lib/vagrant_utm/action/is_running.rb +26 -0
- data/lib/vagrant_utm/action/is_stopped.rb +26 -0
- data/lib/vagrant_utm/action/message_already_running.rb +22 -0
- data/lib/vagrant_utm/action/message_not_created.rb +22 -0
- data/lib/vagrant_utm/action/message_not_running.rb +22 -0
- data/lib/vagrant_utm/action/message_not_stopped.rb +22 -0
- data/lib/vagrant_utm/action/message_will_not_create.rb +23 -0
- data/lib/vagrant_utm/action/message_will_not_destroy.rb +23 -0
- data/lib/vagrant_utm/action/prepare_forwarded_port_collision_params.rb +43 -0
- data/lib/vagrant_utm/action/resume.rb +24 -0
- data/lib/vagrant_utm/action/set_id.rb +20 -0
- data/lib/vagrant_utm/action/set_name.rb +62 -0
- data/lib/vagrant_utm/action/snapshot_delete.rb +34 -0
- data/lib/vagrant_utm/action/snapshot_restore.rb +28 -0
- data/lib/vagrant_utm/action/snapshot_save.rb +34 -0
- data/lib/vagrant_utm/action/suspend.rb +23 -0
- data/lib/vagrant_utm/action/wait_for_running.rb +28 -0
- data/lib/vagrant_utm/action.rb +413 -0
- data/lib/vagrant_utm/cap.rb +40 -0
- data/lib/vagrant_utm/config.rb +141 -0
- data/lib/vagrant_utm/disposable.rb +16 -0
- data/lib/vagrant_utm/driver/base.rb +358 -0
- data/lib/vagrant_utm/driver/meta.rb +132 -0
- data/lib/vagrant_utm/driver/version_4_5.rb +307 -0
- data/lib/vagrant_utm/errors.rb +77 -0
- data/lib/vagrant_utm/model/forwarded_port.rb +75 -0
- data/lib/vagrant_utm/model/list_result.rb +77 -0
- data/lib/vagrant_utm/plugin.rb +65 -0
- data/lib/vagrant_utm/provider.rb +139 -0
- data/lib/vagrant_utm/scripts/add_port_forwards.applescript +72 -0
- data/lib/vagrant_utm/scripts/clear_port_forwards.applescript +56 -0
- data/lib/vagrant_utm/scripts/customize_vm.applescript +59 -0
- data/lib/vagrant_utm/scripts/downloadVM.sh +1 -0
- data/lib/vagrant_utm/scripts/list_vm.js +32 -0
- data/lib/vagrant_utm/scripts/open_with_utm.js +30 -0
- data/lib/vagrant_utm/scripts/read_forwarded_ports.applescript +27 -0
- data/lib/vagrant_utm/scripts/read_guest_ip.applescript +9 -0
- data/lib/vagrant_utm/scripts/read_network_interfaces.applescript +12 -0
- data/lib/vagrant_utm/util/compile_forwarded_ports.rb +43 -0
- data/lib/vagrant_utm/version.rb +9 -0
- data/lib/vagrant_utm.rb +40 -0
- data/locales/en.yml +154 -0
- data/sig/vagrant_utm.rbs +4 -0
- data/vagrantfile_examples/Vagrantfile +27 -0
- metadata +140 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Utm
|
5
|
+
module Action
|
6
|
+
# This action is responsible for suspending the VM.
|
7
|
+
class Suspend
|
8
|
+
def initialize(app, _env)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
if env[:machine].state.id == :started
|
14
|
+
env[:ui].info I18n.t("vagrant.actions.vm.suspend.suspending")
|
15
|
+
env[:machine].provider.driver.suspend
|
16
|
+
end
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Utm
|
5
|
+
module Action
|
6
|
+
# This action waits for a given amount of seconds.
|
7
|
+
# This is a workaround for the UTM provider, which does not
|
8
|
+
# report when the VM is running. As soon as UTM reports the
|
9
|
+
# state as 'running', this action can and will be removed.
|
10
|
+
# Then we use the state 'running', rather than 'started'
|
11
|
+
class WaitForRunning
|
12
|
+
def initialize(app, _env)
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# set the wait time to user configured time or
|
18
|
+
# default time.
|
19
|
+
wait_time = env[:machine].provider_config.wait_time
|
20
|
+
env[:ui].info I18n.t("vagrant_utm.messages.waiting_for_vm", time: wait_time)
|
21
|
+
sleep(wait_time)
|
22
|
+
|
23
|
+
@app.call(env)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,413 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "vagrant"
|
4
|
+
require "vagrant/action/builder"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module Utm
|
8
|
+
# Contains all the supported actions of the UTM provider.
|
9
|
+
module Action # rubocop:disable Metrics/ModuleLength
|
10
|
+
# Autoloading action blocks
|
11
|
+
action_root = Pathname.new(File.expand_path("action", __dir__))
|
12
|
+
autoload :Boot, action_root.join("boot")
|
13
|
+
autoload :BootDisposable, action_root.join("boot_disposable")
|
14
|
+
autoload :CheckAccessible, action_root.join("check_accessible")
|
15
|
+
autoload :CheckCreated, action_root.join("check_created")
|
16
|
+
autoload :CheckGuestAdditions, action_root.join("check_guest_additions")
|
17
|
+
autoload :CheckQemuImg, action_root.join("check_qemu_img")
|
18
|
+
autoload :CheckRunning, action_root.join("check_running")
|
19
|
+
autoload :CheckUtm, action_root.join("check_utm")
|
20
|
+
autoload :ClearForwardedPorts, action_root.join("clear_forwarded_ports")
|
21
|
+
autoload :Created, action_root.join("created")
|
22
|
+
autoload :Customize, action_root.join("customize")
|
23
|
+
autoload :Destroy, action_root.join("destroy")
|
24
|
+
autoload :DownloadConfirm, action_root.join("download_confirm")
|
25
|
+
autoload :Export, action_root.join("export")
|
26
|
+
autoload :ForcedHalt, action_root.join("forced_halt")
|
27
|
+
autoload :ForwardPorts, action_root.join("forward_ports")
|
28
|
+
autoload :Import, action_root.join("import")
|
29
|
+
autoload :IsPaused, action_root.join("is_paused")
|
30
|
+
autoload :IsRunning, action_root.join("is_running")
|
31
|
+
autoload :IsStopped, action_root.join("is_stopped")
|
32
|
+
autoload :MessageAlreadyRunning, action_root.join("message_already_running")
|
33
|
+
autoload :MessageNotCreated, action_root.join("message_not_created")
|
34
|
+
autoload :MessageNotRunning, action_root.join("message_not_running")
|
35
|
+
autoload :MessageNotStopped, action_root.join("message_not_stopped")
|
36
|
+
autoload :MessageWillNotCreate, action_root.join("message_will_not_create")
|
37
|
+
autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
|
38
|
+
autoload :PrepareForwardedPortCollisionParams, action_root.join("prepare_forwarded_port_collision_params")
|
39
|
+
autoload :Resume, action_root.join("resume")
|
40
|
+
autoload :SetId, action_root.join("set_id")
|
41
|
+
autoload :SetName, action_root.join("set_name")
|
42
|
+
autoload :SnapshotDelete, action_root.join("snapshot_delete")
|
43
|
+
autoload :SnapshotRestore, action_root.join("snapshot_restore")
|
44
|
+
autoload :SnapshotSave, action_root.join("snapshot_save")
|
45
|
+
autoload :Suspend, action_root.join("suspend")
|
46
|
+
autoload :WaitForRunning, action_root.join("wait_for_running")
|
47
|
+
|
48
|
+
# Include the built-in Vagrant action modules (e.g., DestroyConfirm)
|
49
|
+
include Vagrant::Action::Builtin
|
50
|
+
|
51
|
+
# State of VM is given by Driver read state
|
52
|
+
|
53
|
+
# This action boots the VM, assuming the VM is in a state that requires
|
54
|
+
# a bootup (i.e. not saved).
|
55
|
+
def self.action_boot # rubocop:disable Metrics/AbcSize
|
56
|
+
Vagrant::Action::Builder.new.tap do |b|
|
57
|
+
b.use CheckAccessible
|
58
|
+
b.use SetName
|
59
|
+
b.use ClearForwardedPorts
|
60
|
+
b.use Provision
|
61
|
+
b.use EnvSet, port_collision_repair: true
|
62
|
+
b.use PrepareForwardedPortCollisionParams
|
63
|
+
b.use HandleForwardedPortCollisions
|
64
|
+
b.use ForwardPorts
|
65
|
+
b.use SetHostname
|
66
|
+
b.use Customize, "pre-boot"
|
67
|
+
b.use Boot
|
68
|
+
b.use Customize, "post-boot"
|
69
|
+
|
70
|
+
# UTM does not have a running state, if you want to
|
71
|
+
# wait manually for the VM to be running, use the following:
|
72
|
+
# b.use WaitForRunning
|
73
|
+
# Since we use forwarded ports , we do not query ip address of VM
|
74
|
+
# for Vagrant communicator.
|
75
|
+
# So we can rely on WaitForCommunicator to wait for VM to be up and running
|
76
|
+
|
77
|
+
# Machine need to be up and running before we can connect to it.
|
78
|
+
# TODO: change valid states to starting, started, running (after UTM provides running state)
|
79
|
+
b.use WaitForCommunicator, %i[starting started]
|
80
|
+
b.use Customize, "post-comm"
|
81
|
+
b.use CheckGuestAdditions
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# This is the action that is primarily responsible for completely
|
86
|
+
# freeing the resources of the underlying virtual machine.
|
87
|
+
# UTM equivalent of `utmctl delete <uuid>`
|
88
|
+
def self.action_destroy
|
89
|
+
Vagrant::Action::Builder.new.tap do |b|
|
90
|
+
b.use CheckUtm
|
91
|
+
b.use Call, Created do |env1, b2|
|
92
|
+
unless env1[:result]
|
93
|
+
b2.use MessageNotCreated
|
94
|
+
next
|
95
|
+
end
|
96
|
+
|
97
|
+
b2.use Call, DestroyConfirm do |env2, b3|
|
98
|
+
if env2[:result]
|
99
|
+
b3.use ConfigValidate
|
100
|
+
b3.use ProvisionerCleanup, :before
|
101
|
+
b3.use CheckAccessible
|
102
|
+
b3.use action_halt
|
103
|
+
b3.use Destroy
|
104
|
+
else
|
105
|
+
b3.use MessageWillNotDestroy
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# This action is primarily responsible for halting the VM.
|
113
|
+
# gracefully or by force.
|
114
|
+
# UTM equivalent of `utmctl stop <uuid>`
|
115
|
+
def self.action_halt
|
116
|
+
Vagrant::Action::Builder.new.tap do |b|
|
117
|
+
b.use CheckUtm
|
118
|
+
b.use Call, Created do |env, b2|
|
119
|
+
if env[:result]
|
120
|
+
b2.use CheckAccessible
|
121
|
+
|
122
|
+
# if VM is paused, resume it before halting
|
123
|
+
# utmctl stop will not work on paused VM
|
124
|
+
b2.use Call, IsPaused do |env2, b3|
|
125
|
+
next unless env2[:result]
|
126
|
+
|
127
|
+
b3.use Resume
|
128
|
+
end
|
129
|
+
|
130
|
+
b2.use Call, GracefulHalt, :stopped, :started do |env2, b3|
|
131
|
+
b3.use ForcedHalt unless env2[:result]
|
132
|
+
end
|
133
|
+
else
|
134
|
+
b2.use MessageNotCreated
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# This action packages the virtual machine into a single box file.
|
141
|
+
def self.action_package
|
142
|
+
Vagrant::Action::Builder.new.tap do |b|
|
143
|
+
b.use CheckUtm
|
144
|
+
b.use Call, Created do |env, b2|
|
145
|
+
unless env[:result]
|
146
|
+
b2.use MessageNotCreated
|
147
|
+
next
|
148
|
+
end
|
149
|
+
b2.use CheckAccessible
|
150
|
+
b2.use action_halt
|
151
|
+
b2.use ClearForwardedPorts
|
152
|
+
b2.use Export
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# This action just runs the provisioners on the machine.
|
158
|
+
def self.action_provision
|
159
|
+
Vagrant::Action::Builder.new.tap do |b|
|
160
|
+
b.use CheckUtm
|
161
|
+
b.use ConfigValidate
|
162
|
+
b.use Call, Created do |env1, b2|
|
163
|
+
unless env1[:result]
|
164
|
+
b2.use MessageNotCreated
|
165
|
+
next
|
166
|
+
end
|
167
|
+
|
168
|
+
b2.use Call, IsRunning do |env2, b3|
|
169
|
+
unless env2[:result]
|
170
|
+
b3.use MessageNotRunning
|
171
|
+
next
|
172
|
+
end
|
173
|
+
|
174
|
+
b3.use CheckAccessible
|
175
|
+
b3.use Provision
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# This action is responsible for reloading the machine, which
|
182
|
+
# brings it down, sucks in new configuration, and brings the
|
183
|
+
# machine back up with the new configuration.
|
184
|
+
def self.action_reload
|
185
|
+
Vagrant::Action::Builder.new.tap do |b|
|
186
|
+
b.use CheckUtm
|
187
|
+
b.use Call, Created do |env1, b2|
|
188
|
+
unless env1[:result]
|
189
|
+
b2.use MessageNotCreated
|
190
|
+
next
|
191
|
+
end
|
192
|
+
|
193
|
+
b2.use ConfigValidate
|
194
|
+
b2.use action_halt
|
195
|
+
b2.use action_start
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# This action is primarily responsible for resuming the suspended VM.
|
201
|
+
# UTM equivalent of `utmctl start <uuid>`
|
202
|
+
def self.action_resume
|
203
|
+
Vagrant::Action::Builder.new.tap do |b|
|
204
|
+
b.use CheckUtm
|
205
|
+
b.use Call, Created do |env, b2|
|
206
|
+
if env[:result]
|
207
|
+
b2.use CheckAccessible
|
208
|
+
|
209
|
+
# if VM is paused , QEMU still holds the port
|
210
|
+
# so we disable port collision check while resuming
|
211
|
+
# lsof -i tcp:8989
|
212
|
+
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
213
|
+
# QEMULaunc 27754 xxxxxxxxx 21u IPv4 0x41d02c3ade4c04f1 0t0 TCP *:sunwebadmins (LISTEN)
|
214
|
+
# b2.use EnvSet, port_collision_repair: false
|
215
|
+
# b2.use PrepareForwardedPortCollisionParams
|
216
|
+
# b2.use HandleForwardedPortCollisions
|
217
|
+
|
218
|
+
b2.use Resume
|
219
|
+
b2.use Provision
|
220
|
+
b2.use WaitForCommunicator, %i[resuming started]
|
221
|
+
else
|
222
|
+
b2.use MessageNotCreated
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# This is the action that is primarily responsible for deleting a snapshot
|
229
|
+
def self.action_snapshot_delete
|
230
|
+
Vagrant::Action::Builder.new.tap do |b|
|
231
|
+
b.use CheckUtm
|
232
|
+
b.use CheckQemuImg
|
233
|
+
b.use Call, Created do |env, b2|
|
234
|
+
if env[:result]
|
235
|
+
# qemu-img needs write-lock to file, so VM should be stopped
|
236
|
+
b2.use Call, IsStopped do |env2, b3|
|
237
|
+
if env2[:result]
|
238
|
+
b3.use SnapshotDelete
|
239
|
+
else
|
240
|
+
b3.use MessageNotStopped
|
241
|
+
end
|
242
|
+
end
|
243
|
+
else
|
244
|
+
b2.use MessageNotCreated
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# This is the action that is primarily responsible for restoring a snapshot
|
251
|
+
def self.action_snapshot_restore # rubocop:disable Metrics/AbcSize
|
252
|
+
Vagrant::Action::Builder.new.tap do |b|
|
253
|
+
b.use CheckUtm
|
254
|
+
b.use CheckQemuImg
|
255
|
+
b.use Call, Created do |env, b2|
|
256
|
+
raise Vagrant::Errors::VMNotCreatedError unless env[:result]
|
257
|
+
|
258
|
+
b2.use CheckAccessible
|
259
|
+
b2.use EnvSet, force_halt: true
|
260
|
+
b2.use action_halt
|
261
|
+
b2.use SnapshotRestore
|
262
|
+
|
263
|
+
b2.use Call, IsEnvSet, :snapshot_delete do |env2, b3|
|
264
|
+
b3.use action_snapshot_delete if env2[:result]
|
265
|
+
end
|
266
|
+
|
267
|
+
b2.use Call, IsEnvSet, :snapshot_start do |env2, b3|
|
268
|
+
b3.use action_start if env2[:result]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# This is the action that is primarily responsible for saving a snapshot
|
275
|
+
def self.action_snapshot_save
|
276
|
+
Vagrant::Action::Builder.new.tap do |b|
|
277
|
+
b.use CheckUtm
|
278
|
+
b.use CheckQemuImg
|
279
|
+
b.use Call, Created do |env, b2|
|
280
|
+
if env[:result]
|
281
|
+
# qemu-img does offline snapshot, so VM should be stopped
|
282
|
+
b2.use Call, IsStopped do |env2, b3|
|
283
|
+
if env2[:result]
|
284
|
+
b3.use SnapshotSave
|
285
|
+
else
|
286
|
+
b3.use MessageNotStopped
|
287
|
+
end
|
288
|
+
end
|
289
|
+
else
|
290
|
+
b2.use MessageNotCreated
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# This is the action that will exec into an SSH shell.
|
297
|
+
def self.action_ssh
|
298
|
+
Vagrant::Action::Builder.new.tap do |b|
|
299
|
+
b.use CheckUtm
|
300
|
+
b.use CheckCreated
|
301
|
+
b.use CheckAccessible
|
302
|
+
b.use CheckRunning
|
303
|
+
b.use SSHExec
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# This is the action that will run a single SSH command.
|
308
|
+
def self.action_ssh_run
|
309
|
+
Vagrant::Action::Builder.new.tap do |b|
|
310
|
+
b.use CheckUtm
|
311
|
+
b.use CheckCreated
|
312
|
+
b.use CheckAccessible
|
313
|
+
b.use CheckRunning
|
314
|
+
b.use SSHRun
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# This action starts a VM, assuming it is already imported and exists.
|
319
|
+
# A precondition of this action is that the VM exists.
|
320
|
+
def self.action_start
|
321
|
+
Vagrant::Action::Builder.new.tap do |b|
|
322
|
+
b.use CheckUtm
|
323
|
+
b.use ConfigValidate
|
324
|
+
b.use Call, IsRunning do |env, b2|
|
325
|
+
# If the VM is running, run the necessary provisioners
|
326
|
+
if env[:result]
|
327
|
+
b2.use action_provision
|
328
|
+
next
|
329
|
+
end
|
330
|
+
|
331
|
+
b2.use Call, IsPaused do |env2, b3|
|
332
|
+
if env2[:result]
|
333
|
+
b3.use Resume
|
334
|
+
next
|
335
|
+
end
|
336
|
+
|
337
|
+
# The VM is not paused, so we must have to boot it up
|
338
|
+
# like normal. Boot!
|
339
|
+
b3.use action_boot
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# This action start VM in disposable mode.
|
346
|
+
# UTM equivalent of `utmctl start <uuid> --disposable`
|
347
|
+
def self.action_start_disposable
|
348
|
+
Vagrant::Action::Builder.new.tap do |b|
|
349
|
+
b.use CheckUtm
|
350
|
+
b.use ConfigValidate
|
351
|
+
b.use Call, IsRunning do |env1, b2|
|
352
|
+
if env1[:result]
|
353
|
+
b2.use MessageAlreadyRunning
|
354
|
+
next
|
355
|
+
end
|
356
|
+
# If the VM is NOT running, then start in disposable mode
|
357
|
+
b2.use BootDisposable
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
# This action is primarily responsible for suspending the VM.
|
363
|
+
# UTM equivalent of `utmctl suspend <uuid>`
|
364
|
+
def self.action_suspend
|
365
|
+
Vagrant::Action::Builder.new.tap do |b|
|
366
|
+
b.use CheckUtm
|
367
|
+
b.use Call, Created do |env, b2|
|
368
|
+
if env[:result]
|
369
|
+
b2.use CheckAccessible
|
370
|
+
b2.use Suspend
|
371
|
+
else
|
372
|
+
b2.use MessageNotCreated
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
# This action brings the machine up from nothing, including importing
|
379
|
+
# the UTM file, configuring metadata, and booting.
|
380
|
+
def self.action_up # rubocop:disable Metrics/AbcSize
|
381
|
+
Vagrant::Action::Builder.new.tap do |b|
|
382
|
+
b.use CheckUtm
|
383
|
+
b.use ConfigValidate
|
384
|
+
b.use Call, Created do |env, b2|
|
385
|
+
# If the VM is NOT created yet, then do the setup steps
|
386
|
+
unless env[:result]
|
387
|
+
b2.use CheckAccessible
|
388
|
+
b2.use Customize, "pre-import"
|
389
|
+
# load UTM file to UTM app, through 'utm://downloadVM?url='
|
390
|
+
b2.use Import
|
391
|
+
|
392
|
+
b2.use Call, DownloadConfirm do |env1, b3|
|
393
|
+
if env1[:result]
|
394
|
+
# SetID
|
395
|
+
b3.use SetId
|
396
|
+
b3.use SetName
|
397
|
+
# Customize
|
398
|
+
b3.use Customize, "pre-boot"
|
399
|
+
else
|
400
|
+
b3.use MessageWillNotCreate
|
401
|
+
raise Errors::UtmImportFailed
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Start the VM
|
408
|
+
b.use action_start
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Utm
|
5
|
+
# Contains all the supported capabilities of the UTM provider.
|
6
|
+
module Cap
|
7
|
+
# Reads the forwarded ports that currently exist on the machine
|
8
|
+
# itself. This raises an exception if the machine isn't running (UTM 'started').
|
9
|
+
#
|
10
|
+
# This also may not match up with configured forwarded ports, because
|
11
|
+
# Vagrant auto port collision fixing may have taken place.
|
12
|
+
#
|
13
|
+
# @return [Hash<Integer, Integer>] Host => Guest port mappings.
|
14
|
+
def self.forwarded_ports(machine)
|
15
|
+
return nil if machine.state.id != :started
|
16
|
+
|
17
|
+
{}.tap do |result|
|
18
|
+
machine.provider.driver.read_forwarded_ports.each do |_, _, h, g|
|
19
|
+
result[h] = g
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a list of the snapshots that are taken on this machine.
|
25
|
+
#
|
26
|
+
# @return [Array<String>] Snapshot Name
|
27
|
+
def self.snapshot_list(machine)
|
28
|
+
return [] if machine.id.nil?
|
29
|
+
|
30
|
+
begin
|
31
|
+
machine.provider.driver.list_snapshots(machine.id)
|
32
|
+
rescue VagrantPlugins::Utm::Errors::CommandError => e
|
33
|
+
raise Errors::SnapShotCommandFailed, {
|
34
|
+
stderr: e.inspect
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "i18n"
|
4
|
+
require "vagrant"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module Utm
|
8
|
+
# This is the configuration class for the UTM provider.
|
9
|
+
class Config < Vagrant.plugin("2", :config)
|
10
|
+
# This should be set to the name of the machine in the UTM GUI.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
attr_accessor :name
|
14
|
+
|
15
|
+
# The path to the UTM VM file.
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
attr_accessor :utm_file_url
|
19
|
+
|
20
|
+
# If true, will check if guest additions are installed and up to
|
21
|
+
# date. By default, this is true.
|
22
|
+
#
|
23
|
+
# @return [Boolean]
|
24
|
+
attr_accessor :check_guest_additions
|
25
|
+
|
26
|
+
# An array of customizations to make on the VM prior to booting it.
|
27
|
+
#
|
28
|
+
# @return [Array]
|
29
|
+
attr_reader :customizations
|
30
|
+
|
31
|
+
# The time to wait for the VM to be 'running' after 'started'.
|
32
|
+
#
|
33
|
+
# @return [Integer]
|
34
|
+
attr_accessor :wait_time
|
35
|
+
|
36
|
+
# Initialize the configuration with unset values.
|
37
|
+
def initialize
|
38
|
+
super
|
39
|
+
@check_guest_additions = UNSET_VALUE
|
40
|
+
@customizations = []
|
41
|
+
@name = UNSET_VALUE
|
42
|
+
@utm_file_url = UNSET_VALUE
|
43
|
+
@wait_time = UNSET_VALUE
|
44
|
+
end
|
45
|
+
|
46
|
+
# Customize the VM by calling 'osascript' with the given
|
47
|
+
# arguments.
|
48
|
+
#
|
49
|
+
# When called multiple times, the customizations will be applied
|
50
|
+
# in the order given.
|
51
|
+
#
|
52
|
+
# @param [Array] command An array of arguments to pass to
|
53
|
+
# osascript config function.
|
54
|
+
def customize(*command)
|
55
|
+
# Append the event and command to the customizations array
|
56
|
+
event = command.first.is_a?(String) ? command.shift : "pre-boot"
|
57
|
+
command = command[0]
|
58
|
+
@customizations << [event, command]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Shortcut for setting memory size for the virtual machine.
|
62
|
+
# Calls #customize internally.
|
63
|
+
#
|
64
|
+
# @param size [Integer] the memory size in MB
|
65
|
+
def memory=(size)
|
66
|
+
customize("pre-boot", ["customize_vm.applescript", :id, "--memory", size.to_s])
|
67
|
+
end
|
68
|
+
|
69
|
+
# Shortcut for setting CPU count for the virtual machine.
|
70
|
+
# Calls #customize internally.
|
71
|
+
#
|
72
|
+
# @param count [Integer] the count of CPUs
|
73
|
+
def cpus=(count)
|
74
|
+
customize("pre-boot", ["customize_vm.applescript", :id, "--cpus", count.to_i])
|
75
|
+
end
|
76
|
+
|
77
|
+
# Shortcut for setting the notes of the virtual machine.
|
78
|
+
# Calls #customize internally.
|
79
|
+
#
|
80
|
+
# @param notes [String] the notes for the VM
|
81
|
+
def notes=(notes)
|
82
|
+
customize("pre-boot", ["customize_vm.applescript", :id, "--notes", notes])
|
83
|
+
end
|
84
|
+
|
85
|
+
# Shortcut for setting the directory share mode of the virtual machine.
|
86
|
+
# Calls #customize internally.
|
87
|
+
#
|
88
|
+
# @param mode [String] the directory share mode for the VM
|
89
|
+
def directory_share_mode=(mode)
|
90
|
+
# The mode can be 'none', 'webDAV', 'virtFS'
|
91
|
+
# Convert the mode to the corresponding 4-byte code
|
92
|
+
# and pass it to the customize_vm.applescript
|
93
|
+
mode_code = case mode.to_s
|
94
|
+
when "none"
|
95
|
+
"SmOf"
|
96
|
+
when "webDAV"
|
97
|
+
"SmWv"
|
98
|
+
when "virtFS"
|
99
|
+
"SmVs"
|
100
|
+
else
|
101
|
+
raise Vagrant::Errors::ConfigInvalid,
|
102
|
+
errors: "Invalid directory share mode, must be 'none', 'webDAV', or 'virtFS'"
|
103
|
+
end
|
104
|
+
customize("pre-boot", ["customize_vm.applescript", :id, "--directory-share-mode", mode_code])
|
105
|
+
end
|
106
|
+
|
107
|
+
# This is the hook that is called to finalize the object before it
|
108
|
+
# is put into use.
|
109
|
+
def finalize!
|
110
|
+
@check_guest_additions = true if @check_guest_additions == UNSET_VALUE
|
111
|
+
|
112
|
+
# The default name is just nothing, and we default it
|
113
|
+
@name = nil if @name == UNSET_VALUE
|
114
|
+
|
115
|
+
@utm_file_url = nil if @utm_file_url == UNSET_VALUE
|
116
|
+
|
117
|
+
@wait_time = 20 if @wait_time == UNSET_VALUE
|
118
|
+
end
|
119
|
+
|
120
|
+
def validate(_machine)
|
121
|
+
errors = _detected_errors
|
122
|
+
|
123
|
+
# Checks for the UTM file URL
|
124
|
+
errors << I18n.t("vagrant_utm.config.utm_file_url_required") if @utm_file_url.nil? || @utm_file_url.empty?
|
125
|
+
|
126
|
+
valid_events = %w[pre-import pre-boot post-boot post-comm]
|
127
|
+
@customizations.each do |event, _| # rubocop:disable Style/HashEachMethods
|
128
|
+
next if valid_events.include?(event)
|
129
|
+
|
130
|
+
errors << I18n.t(
|
131
|
+
"vagrant.virtualbox.config.invalid_event",
|
132
|
+
event: event.to_s,
|
133
|
+
valid_events: valid_events.join(", ")
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
{ "UTM Provider" => errors }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Utm
|
5
|
+
# Run VM as a snapshot and do not save changes to disk.
|
6
|
+
class Disposable < Vagrant.plugin(2, :command)
|
7
|
+
def execute
|
8
|
+
with_target_vms do |machine|
|
9
|
+
machine.action(:start_disposable)
|
10
|
+
end
|
11
|
+
|
12
|
+
0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|