vagrant-xapi 0.0.1 → 1.0.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +83 -0
  3. data/LICENSE +21 -0
  4. data/README.md +460 -4
  5. data/docs/architecture.md +1420 -0
  6. data/docs/operations.md +531 -0
  7. data/lib/vagrant-xapi/action/base.rb +103 -0
  8. data/lib/vagrant-xapi/action/cloud_init.rb +130 -0
  9. data/lib/vagrant-xapi/action/create.rb +127 -0
  10. data/lib/vagrant-xapi/action/destroy.rb +68 -0
  11. data/lib/vagrant-xapi/action/network.rb +229 -0
  12. data/lib/vagrant-xapi/action/package.rb +103 -0
  13. data/lib/vagrant-xapi/action/power.rb +185 -0
  14. data/lib/vagrant-xapi/action/snapshots.rb +43 -0
  15. data/lib/vagrant-xapi/action.rb +317 -0
  16. data/lib/vagrant-xapi/api/client.rb +393 -0
  17. data/lib/vagrant-xapi/api/errors.rb +98 -0
  18. data/lib/vagrant-xapi/api/http_transfer.rb +332 -0
  19. data/lib/vagrant-xapi/api/redactor.rb +77 -0
  20. data/lib/vagrant-xapi/api/session_registry.rb +59 -0
  21. data/lib/vagrant-xapi/api/task.rb +156 -0
  22. data/lib/vagrant-xapi/api/transport.rb +249 -0
  23. data/lib/vagrant-xapi/cap.rb +90 -0
  24. data/lib/vagrant-xapi/command/adopt.rb +92 -0
  25. data/lib/vagrant-xapi/command/base.rb +79 -0
  26. data/lib/vagrant-xapi/command/console.rb +87 -0
  27. data/lib/vagrant-xapi/command/diff.rb +267 -0
  28. data/lib/vagrant-xapi/command/hosts.rb +63 -0
  29. data/lib/vagrant-xapi/command/info.rb +94 -0
  30. data/lib/vagrant-xapi/command/marked.rb +85 -0
  31. data/lib/vagrant-xapi/command/orphans.rb +96 -0
  32. data/lib/vagrant-xapi/command/root.rb +55 -0
  33. data/lib/vagrant-xapi/command/templates.rb +91 -0
  34. data/lib/vagrant-xapi/config.rb +333 -0
  35. data/lib/vagrant-xapi/errors.rb +113 -0
  36. data/lib/vagrant-xapi/extensions.rb +80 -0
  37. data/lib/vagrant-xapi/glue.rb +330 -0
  38. data/lib/vagrant-xapi/legacy/plugin.rb +61 -0
  39. data/lib/vagrant-xapi/legacy/xenapi.rb +129 -0
  40. data/lib/vagrant-xapi/plugin.rb +58 -0
  41. data/lib/vagrant-xapi/provider.rb +135 -0
  42. data/lib/vagrant-xapi/services/adoption.rb +73 -0
  43. data/lib/vagrant-xapi/services/base.rb +242 -0
  44. data/lib/vagrant-xapi/services/box_source.rb +218 -0
  45. data/lib/vagrant-xapi/services/console.rb +115 -0
  46. data/lib/vagrant-xapi/services/content_diff.rb +96 -0
  47. data/lib/vagrant-xapi/services/destroyer.rb +104 -0
  48. data/lib/vagrant-xapi/services/diff_disks.rb +346 -0
  49. data/lib/vagrant-xapi/services/differ.rb +382 -0
  50. data/lib/vagrant-xapi/services/disk_image.rb +122 -0
  51. data/lib/vagrant-xapi/services/disks.rb +281 -0
  52. data/lib/vagrant-xapi/services/exporter.rb +128 -0
  53. data/lib/vagrant-xapi/services/file_diff.rb +249 -0
  54. data/lib/vagrant-xapi/services/guest_files.rb +730 -0
  55. data/lib/vagrant-xapi/services/hosts.rb +55 -0
  56. data/lib/vagrant-xapi/services/image_upload.rb +172 -0
  57. data/lib/vagrant-xapi/services/inventory.rb +225 -0
  58. data/lib/vagrant-xapi/services/ip_detector.rb +107 -0
  59. data/lib/vagrant-xapi/services/lock.rb +293 -0
  60. data/lib/vagrant-xapi/services/lookup.rb +181 -0
  61. data/lib/vagrant-xapi/services/networks.rb +248 -0
  62. data/lib/vagrant-xapi/services/power.rb +108 -0
  63. data/lib/vagrant-xapi/services/rfb.rb +129 -0
  64. data/lib/vagrant-xapi/services/snapshots.rb +81 -0
  65. data/lib/vagrant-xapi/services/template_cache.rb +263 -0
  66. data/lib/vagrant-xapi/services/tunnels.rb +217 -0
  67. data/lib/vagrant-xapi/services/vm_builder.rb +215 -0
  68. data/lib/vagrant-xapi/version.rb +7 -0
  69. data/lib/vagrant-xapi/xenserver/config.rb +69 -0
  70. data/lib/vagrant-xapi/xenserver/migrate.rb +103 -0
  71. data/lib/vagrant-xapi/xenserver/plugin.rb +96 -0
  72. data/lib/vagrant-xapi/xenserver/provider.rb +22 -0
  73. data/lib/vagrant-xapi/xenserver/takeover.rb +79 -0
  74. data/lib/vagrant-xapi.rb +21 -2
  75. data/lib/xenapi.rb +22 -0
  76. data/locales/en.yml +517 -0
  77. data/locales/legacy.en.yml +6 -0
  78. metadata +86 -5
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ipaddr"
4
+
5
+ require_relative "base"
6
+ require_relative "../services/diff_disks"
7
+ require_relative "../services/power"
8
+ require_relative "../services/networks"
9
+ require_relative "../services/ip_detector"
10
+
11
+ module VagrantPlugins
12
+ module Xapi
13
+ module Action
14
+ # Starts a halted VM. VMs on an internal network all run on the host of
15
+ # the first VM that used it (internal networks exist per host).
16
+ class StartVm < Base
17
+ def call(env)
18
+ wrap { Action.placed(env, ctx(env), vm(env)) { |power, ref, host| power.start(ref, host: host) } }
19
+ @app.call(env)
20
+ end
21
+ end
22
+
23
+ # Yields Power, the VM and the host it must run on: on an internal
24
+ # network the host of a running peer, under the project's placement
25
+ # lock; otherwise nil (XAPI chooses).
26
+ def self.placed(env, ctx, ref)
27
+ networks = Services::Networks.new(ctx, project: Glue.project_path(env[:machine]))
28
+ internal = networks.internal_networks_of(ref)
29
+ power = Services::Power.new(ctx)
30
+ return yield(power, ref, nil) if internal.empty?
31
+
32
+ networks.placement_lock { yield(power, ref, networks.running_peer_host(internal, except: ref)) }
33
+ end
34
+
35
+ # Vagrant's SSH communicator lists Errno::EPIPE among the errors to
36
+ # retry, but wait_for_ready connects with a single try and does not
37
+ # rescue it, so `vagrant up` died with a stack trace. net-ssh raises it
38
+ # when sshd closes a connection right after accepting it. OpenSSH 9.8
39
+ # and newer do that for a while after failed logins from the same
40
+ # address (PerSourcePenalties), e.g. while cloud-init is still creating
41
+ # the vagrant user. Here it counts as "not ready yet", within the same
42
+ # timeout.
43
+ module BrokenPipeRetry
44
+ RETRY_DELAY = 5
45
+ # Repeated, so a wait that never ends does not look stuck.
46
+ WARN_EVERY = 60
47
+
48
+ def wait_for_ready(timeout)
49
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
50
+ warned_at = nil
51
+ begin
52
+ super([deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC), 1].max)
53
+ rescue Errno::EPIPE
54
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
55
+ return false if now + RETRY_DELAY >= deadline
56
+
57
+ if warned_at.nil? || now - warned_at >= WARN_EVERY
58
+ instance_variable_get(:@machine)&.ui&.detail(I18n.t("vagrant_xapi.messages.ssh_broken_pipe"))
59
+ warned_at = now
60
+ end
61
+ sleep RETRY_DELAY
62
+ retry
63
+ end
64
+ end
65
+ end
66
+
67
+ # Vagrant's WaitForCommunicator with BrokenPipeRetry on the machine's
68
+ # communicator.
69
+ class WaitForCommunicator < Vagrant::Action::Builtin::WaitForCommunicator
70
+ def call(env)
71
+ communicator = env[:machine].communicate
72
+ unless communicator.singleton_class.include?(BrokenPipeRetry)
73
+ communicator.singleton_class.prepend(BrokenPipeRetry)
74
+ end
75
+ super
76
+ end
77
+ end
78
+
79
+ # Removes snapshot disks an interrupted `vagrant xapi diff` left attached,
80
+ # before the guest boots: they carry the same file system UUIDs as the
81
+ # VM's own disks, so the guest could mount (or boot from) the copy. One
82
+ # that cannot be removed stops the boot with an error.
83
+ class RemoveDiffDisks < Base
84
+ def call(env)
85
+ wrap do
86
+ disks = Services::DiffDisks.new(ctx(env))
87
+ # Under the diff lock of the VM: a diff still running on it (the
88
+ # VM was halted under it) keeps its disks until it is done.
89
+ disks.synchronize(vm(env), wait: Services::DiffDisks::LEFTOVER_LOCK_WAIT) do
90
+ disks.cleanup_leftovers(vm(env), unattached: false, required: true)
91
+ end
92
+ end
93
+ @app.call(env)
94
+ end
95
+ end
96
+
97
+ # Waits until the guest reports an IP (config.vm.boot_timeout).
98
+ class WaitForIp < Base
99
+ def call(env)
100
+ machine = env[:machine]
101
+ wrap do
102
+ c = ctx(env)
103
+ env[:ui].info(I18n.t("vagrant_xapi.messages.waiting_for_ip"))
104
+ ip, source = Glue.ip_detector(machine, c).wait(vm(env), timeout: machine.config.vm.boot_timeout)
105
+ env[:ui].detail(I18n.t("vagrant_xapi.messages.ip_found", ip: ip, source: source))
106
+ env[:xapi_ip] = ip
107
+ end
108
+ @app.call(env)
109
+ end
110
+ end
111
+
112
+ # clean_shutdown, then hard_shutdown after shutdown_timeout; with
113
+ # --force (env[:force_halt]) straight to hard_shutdown.
114
+ class HaltVm < Base
115
+ def call(env)
116
+ wrap do
117
+ ref = vm(env)
118
+ Services::Power.new(ctx(env)).shutdown(ref, timeout: config(env).shutdown_timeout,
119
+ force: env[:force_halt] ? true : false)
120
+ end
121
+ @app.call(env)
122
+ end
123
+ end
124
+
125
+ class SuspendVm < Base
126
+ def call(env)
127
+ wrap { Services::Power.new(ctx(env)).suspend(vm(env)) }
128
+ @app.call(env)
129
+ end
130
+ end
131
+
132
+ # Resumes a suspended VM, on an internal network on the host of its
133
+ # peers, like StartVm.
134
+ class ResumeVm < Base
135
+ def call(env)
136
+ wrap { Action.placed(env, ctx(env), vm(env)) { |power, ref, host| power.resume(ref, host: host) } }
137
+ @app.call(env)
138
+ end
139
+ end
140
+
141
+ class UnpauseVm < Base
142
+ def call(env)
143
+ wrap { Services::Power.new(ctx(env)).unpause(vm(env)) }
144
+ @app.call(env)
145
+ end
146
+ end
147
+
148
+ # Static addresses on VIFs other than device 0 are set in the guest
149
+ # through the guest capability configure_networks, like VirtualBox.
150
+ class ConfigureGuestNetworks < Base
151
+ def call(env)
152
+ machine = env[:machine]
153
+ networks = Glue.vif_plan(machine).select do |spec|
154
+ spec.device.positive? && spec.kind != :himn && spec.static_ip? && spec.auto_config
155
+ end
156
+ if !networks.empty? && machine.guest.capability?(:configure_networks)
157
+ env[:ui].info(I18n.t("vagrant.actions.vm.network.configuring"))
158
+ machine.guest.capability(:configure_networks, networks.map { |spec| guest_network(spec) })
159
+ end
160
+ @app.call(env)
161
+ end
162
+
163
+ private
164
+
165
+ # Vagrant's guest capabilities take :static with a dotted netmask, and
166
+ # :static6 with a prefix length.
167
+ def guest_network(spec)
168
+ prefix = spec.prefix_length
169
+ if spec.ipv6?
170
+ return { type: :static6, ip: spec.ip.to_s, netmask: prefix, interface: spec.device,
171
+ gateway: spec.gateway }.compact
172
+ end
173
+
174
+ {
175
+ type: :static,
176
+ ip: spec.ip.to_s,
177
+ netmask: IPAddr.new("255.255.255.255").mask(prefix).to_s,
178
+ interface: spec.device,
179
+ gateway: spec.gateway
180
+ }.compact
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "../services/snapshots"
5
+
6
+ module VagrantPlugins
7
+ module Xapi
8
+ module Action
9
+ class SnapshotSave < Base
10
+ def call(env)
11
+ name = env[:snapshot_name]
12
+ env[:ui].info(I18n.t("vagrant.actions.vm.snapshot.saving", name: name))
13
+ wrap do
14
+ Services::Snapshots.new(ctx(env)).save(vm(env), name, memory: config(env).snapshot_memory)
15
+ end
16
+ env[:ui].success(I18n.t("vagrant.actions.vm.snapshot.saved", name: name))
17
+ @app.call(env)
18
+ end
19
+ end
20
+
21
+ # Like VirtualBox: halt (forced) first, then revert. A checkpoint comes
22
+ # back as suspended; action_start then resumes it.
23
+ class SnapshotRestore < Base
24
+ def call(env)
25
+ name = env[:snapshot_name]
26
+ env[:ui].info(I18n.t("vagrant.actions.vm.snapshot.restoring", name: name))
27
+ wrap { Services::Snapshots.new(ctx(env)).restore(vm(env), name) }
28
+ @app.call(env)
29
+ end
30
+ end
31
+
32
+ class SnapshotDelete < Base
33
+ def call(env)
34
+ name = env[:snapshot_name]
35
+ env[:ui].info(I18n.t("vagrant.actions.vm.snapshot.deleting", name: name))
36
+ wrap { Services::Snapshots.new(ctx(env)).delete(vm(env), name) }
37
+ env[:ui].success(I18n.t("vagrant.actions.vm.snapshot.deleted", name: name))
38
+ @app.call(env)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,317 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module Xapi
7
+ # Action stacks. Each one starts with TranslateErrors, ConfigValidate and
8
+ # ConnectXapi. The order of steps follows the VirtualBox provider.
9
+ module Action
10
+ action_root = File.expand_path("action", __dir__)
11
+
12
+ autoload :TranslateErrors, "#{action_root}/base"
13
+ autoload :ConnectXapi, "#{action_root}/base"
14
+ autoload :IsCreated, "#{action_root}/base"
15
+ autoload :CheckRunning, "#{action_root}/base"
16
+ autoload :Message, "#{action_root}/base"
17
+ autoload :ImportTemplate, "#{action_root}/create"
18
+ autoload :CreateVm, "#{action_root}/create"
19
+ autoload :ConfigureVm, "#{action_root}/create"
20
+ autoload :StartVm, "#{action_root}/power"
21
+ autoload :RemoveDiffDisks, "#{action_root}/power"
22
+ autoload :WaitForIp, "#{action_root}/power"
23
+ autoload :WaitForCommunicator, "#{action_root}/power"
24
+ autoload :HaltVm, "#{action_root}/power"
25
+ autoload :SuspendVm, "#{action_root}/power"
26
+ autoload :ResumeVm, "#{action_root}/power"
27
+ autoload :UnpauseVm, "#{action_root}/power"
28
+ autoload :ConfigureGuestNetworks, "#{action_root}/power"
29
+ autoload :StartTunnels, "#{action_root}/network"
30
+ autoload :StopTunnels, "#{action_root}/network"
31
+ autoload :EnsureTunnels, "#{action_root}/network"
32
+ autoload :PrepareForwardedPortCollisionParams, "#{action_root}/network"
33
+ autoload :PrepareNFSValidIds, "#{action_root}/network"
34
+ autoload :PrepareNFSSettings, "#{action_root}/network"
35
+ autoload :DestroyVm, "#{action_root}/destroy"
36
+ autoload :CheckOwner, "#{action_root}/destroy"
37
+ autoload :SnapshotSave, "#{action_root}/snapshots"
38
+ autoload :SnapshotRestore, "#{action_root}/snapshots"
39
+ autoload :SnapshotDelete, "#{action_root}/snapshots"
40
+ autoload :PackageSetupFolders, "#{action_root}/package"
41
+ autoload :PackageSetupFiles, "#{action_root}/package"
42
+ autoload :Package, "#{action_root}/package"
43
+ autoload :PackageExport, "#{action_root}/package"
44
+ autoload :PackageVagrantfile, "#{action_root}/package"
45
+ autoload :CloudInitSetup, "#{action_root}/cloud_init"
46
+
47
+ include Vagrant::Action::Builtin
48
+
49
+ # Common head of every stack.
50
+ def self.base(validate: true)
51
+ Vagrant::Action::Builder.new.tap do |b|
52
+ b.use TranslateErrors
53
+ b.use ConfigValidate if validate
54
+ b.use ConnectXapi
55
+ end
56
+ end
57
+
58
+ # A stack for an existing VM: the steps from the block run connected,
59
+ # after validation. A machine without an id is not created without
60
+ # asking the pool, so for a machine that was never created or is
61
+ # destroyed these stacks say so and never connect; its Vagrantfile may
62
+ # not reach the pool (`vagrant destroy` under the user's default
63
+ # provider, a host that is gone).
64
+ def self.created(validate: true, not_created: :message, &steps)
65
+ Vagrant::Action::Builder.new.tap do |b|
66
+ b.use TranslateErrors
67
+ b.use Call, IsCreated do |env, b2|
68
+ unless env[:result]
69
+ raise Vagrant::Errors::VMNotCreatedError if not_created == :raise
70
+
71
+ b2.use Message, :not_created
72
+ next
73
+ end
74
+
75
+ b2.use ConfigValidate if validate
76
+ b2.use ConnectXapi
77
+ steps.call(b2)
78
+ end
79
+ end
80
+ end
81
+
82
+ # up: import the box as template if needed, create the VM, then start.
83
+ def self.action_up
84
+ Vagrant::Action::Builder.new.tap do |b|
85
+ b.use TranslateErrors
86
+ # The box Vagrantfile may carry provider defaults, so handle the
87
+ # box before validating, like VirtualBox does.
88
+ b.use Call, IsCreated do |env, b2|
89
+ b2.use HandleBox unless env[:result]
90
+ end
91
+ b.use ConfigValidate
92
+ b.use ConnectXapi
93
+ b.use Call, IsCreated do |env, b2|
94
+ unless env[:result]
95
+ b2.use ImportTemplate
96
+ b2.use CreateVm
97
+ end
98
+ end
99
+ b.use action_start
100
+ end
101
+ end
102
+
103
+ # halted: boot; suspended: resume; paused: unpause; running: message.
104
+ def self.action_start
105
+ Vagrant::Action::Builder.new.tap do |b|
106
+ b.use BoxCheckOutdated
107
+ b.use Call, IsState, :running do |env, b2|
108
+ if env[:result]
109
+ b2.use Message, :already_running
110
+ b2.use Provision
111
+ b2.use EnsureTunnels
112
+ next
113
+ end
114
+
115
+ b2.use Call, IsState, :suspended do |env2, b3|
116
+ if env2[:result]
117
+ b3.use action_resume
118
+ next
119
+ end
120
+
121
+ b3.use Call, IsState, :paused do |env3, b4|
122
+ if env3[:result]
123
+ b4.use UnpauseVm
124
+ b4.use EnsureTunnels
125
+ next
126
+ end
127
+
128
+ b4.use action_boot
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ # The start steps for a halted VM.
136
+ def self.action_boot
137
+ Vagrant::Action::Builder.new.tap do |b|
138
+ b.use Provision
139
+ b.use EnvSet, port_collision_repair: true
140
+ # Tunnels left over when the VM was stopped outside Vagrant.
141
+ b.use StopTunnels
142
+ b.use PrepareForwardedPortCollisionParams
143
+ b.use HandleForwardedPortCollisions
144
+ b.use PrepareNFSValidIds
145
+ b.use SyncedFolderCleanup
146
+ b.use SyncedFolders
147
+ b.use PrepareNFSSettings
148
+ b.use SetHostname
149
+ b.use CloudInitSetup
150
+ # Before the disk steps, so they never see (or number around) a
151
+ # leftover diff disk.
152
+ b.use RemoveDiffDisks
153
+ b.use CleanupDisks
154
+ b.use Disk
155
+ b.use StartVm
156
+ b.use WaitForIp
157
+ b.use WaitForCommunicator, [:running]
158
+ b.use ConfigureGuestNetworks
159
+ b.use CloudInitWait
160
+ b.use StartTunnels
161
+ end
162
+ end
163
+
164
+ def self.action_halt
165
+ created do |b|
166
+ b.use StopTunnels
167
+ b.use Call, GracefulHalt, :halted, :running do |env, b2|
168
+ b2.use HaltVm unless env[:result]
169
+ end
170
+ end
171
+ end
172
+
173
+ def self.action_reload
174
+ created do |b|
175
+ b.use action_halt
176
+ b.use ConfigureVm
177
+ b.use action_start
178
+ end
179
+ end
180
+
181
+ def self.action_destroy
182
+ created(validate: false) do |b|
183
+ b.use Call, DestroyConfirm do |env, b2|
184
+ unless env[:result]
185
+ b2.use Message, :will_not_destroy
186
+ next
187
+ end
188
+
189
+ b2.use ConfigValidate
190
+ b2.use CheckOwner
191
+ b2.use ProvisionerCleanup, :before
192
+ b2.use EnvSet, force_halt: true
193
+ b2.use StopTunnels
194
+ b2.use HaltVm
195
+ b2.use DestroyVm
196
+ b2.use PrepareNFSValidIds
197
+ b2.use SyncedFolderCleanup
198
+ end
199
+ end
200
+ end
201
+
202
+ def self.action_suspend
203
+ created do |b|
204
+ b.use Call, IsState, :running do |env, b2|
205
+ unless env[:result]
206
+ b2.use Message, :not_running
207
+ next
208
+ end
209
+
210
+ b2.use StopTunnels
211
+ b2.use SuspendVm
212
+ end
213
+ end
214
+ end
215
+
216
+ def self.action_resume
217
+ created(validate: false) do |b|
218
+ b.use Call, IsState, :suspended do |env, b2|
219
+ unless env[:result]
220
+ b2.use Message, :not_suspended
221
+ next
222
+ end
223
+
224
+ # Tunnels are set up anew on resume, so a taken port can still be
225
+ # repaired (VirtualBox cannot, its forwards live in the VM).
226
+ b2.use EnvSet, port_collision_repair: true
227
+ b2.use StopTunnels
228
+ b2.use PrepareForwardedPortCollisionParams
229
+ b2.use HandleForwardedPortCollisions
230
+ b2.use Provision
231
+ b2.use ResumeVm
232
+ b2.use WaitForIp
233
+ b2.use WaitForCommunicator, [:running]
234
+ b2.use StartTunnels
235
+ end
236
+ end
237
+ end
238
+
239
+ def self.action_provision
240
+ created do |b|
241
+ b.use Call, IsState, :running do |env, b2|
242
+ unless env[:result]
243
+ b2.use Message, :not_running
244
+ next
245
+ end
246
+
247
+ b2.use Provision
248
+ end
249
+ end
250
+ end
251
+
252
+ def self.action_ssh
253
+ base(validate: false).tap do |b|
254
+ b.use CheckRunning
255
+ b.use SSHExec
256
+ end
257
+ end
258
+
259
+ def self.action_ssh_run
260
+ base(validate: false).tap do |b|
261
+ b.use CheckRunning
262
+ b.use SSHRun
263
+ end
264
+ end
265
+
266
+ def self.action_package
267
+ created do |b|
268
+ b.use PackageSetupFolders
269
+ b.use PackageSetupFiles
270
+ b.use action_halt
271
+ b.use StopTunnels
272
+ b.use PrepareNFSValidIds
273
+ b.use SyncedFolderCleanup
274
+ b.use Package
275
+ b.use PackageExport
276
+ b.use PackageVagrantfile
277
+ end
278
+ end
279
+
280
+ def self.action_snapshot_save
281
+ created do |b|
282
+ b.use SnapshotSave
283
+ end
284
+ end
285
+
286
+ def self.action_snapshot_restore
287
+ created(not_created: :raise) do |b|
288
+ b.use EnvSet, force_halt: true
289
+ b.use action_halt
290
+ b.use SnapshotRestore
291
+
292
+ b.use Call, IsEnvSet, :snapshot_delete do |env, b2|
293
+ b2.use action_snapshot_delete if env[:result]
294
+ end
295
+
296
+ b.use Call, IsEnvSet, :snapshot_start do |env, b2|
297
+ b2.use action_start if env[:result]
298
+ end
299
+ end
300
+ end
301
+
302
+ def self.action_snapshot_delete
303
+ created do |b|
304
+ b.use SnapshotDelete
305
+ end
306
+ end
307
+
308
+ def self.action_sync_folders
309
+ base(validate: false).tap do |b|
310
+ b.use PrepareNFSValidIds
311
+ b.use SyncedFolders
312
+ b.use PrepareNFSSettings
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end