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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +83 -0
- data/LICENSE +21 -0
- data/README.md +460 -4
- data/docs/architecture.md +1420 -0
- data/docs/operations.md +531 -0
- data/lib/vagrant-xapi/action/base.rb +103 -0
- data/lib/vagrant-xapi/action/cloud_init.rb +130 -0
- data/lib/vagrant-xapi/action/create.rb +127 -0
- data/lib/vagrant-xapi/action/destroy.rb +68 -0
- data/lib/vagrant-xapi/action/network.rb +229 -0
- data/lib/vagrant-xapi/action/package.rb +103 -0
- data/lib/vagrant-xapi/action/power.rb +185 -0
- data/lib/vagrant-xapi/action/snapshots.rb +43 -0
- data/lib/vagrant-xapi/action.rb +317 -0
- data/lib/vagrant-xapi/api/client.rb +393 -0
- data/lib/vagrant-xapi/api/errors.rb +98 -0
- data/lib/vagrant-xapi/api/http_transfer.rb +332 -0
- data/lib/vagrant-xapi/api/redactor.rb +77 -0
- data/lib/vagrant-xapi/api/session_registry.rb +59 -0
- data/lib/vagrant-xapi/api/task.rb +156 -0
- data/lib/vagrant-xapi/api/transport.rb +249 -0
- data/lib/vagrant-xapi/cap.rb +90 -0
- data/lib/vagrant-xapi/command/adopt.rb +92 -0
- data/lib/vagrant-xapi/command/base.rb +79 -0
- data/lib/vagrant-xapi/command/console.rb +87 -0
- data/lib/vagrant-xapi/command/diff.rb +267 -0
- data/lib/vagrant-xapi/command/hosts.rb +63 -0
- data/lib/vagrant-xapi/command/info.rb +94 -0
- data/lib/vagrant-xapi/command/marked.rb +85 -0
- data/lib/vagrant-xapi/command/orphans.rb +96 -0
- data/lib/vagrant-xapi/command/root.rb +55 -0
- data/lib/vagrant-xapi/command/templates.rb +91 -0
- data/lib/vagrant-xapi/config.rb +333 -0
- data/lib/vagrant-xapi/errors.rb +113 -0
- data/lib/vagrant-xapi/extensions.rb +80 -0
- data/lib/vagrant-xapi/glue.rb +330 -0
- data/lib/vagrant-xapi/legacy/plugin.rb +61 -0
- data/lib/vagrant-xapi/legacy/xenapi.rb +129 -0
- data/lib/vagrant-xapi/plugin.rb +58 -0
- data/lib/vagrant-xapi/provider.rb +135 -0
- data/lib/vagrant-xapi/services/adoption.rb +73 -0
- data/lib/vagrant-xapi/services/base.rb +242 -0
- data/lib/vagrant-xapi/services/box_source.rb +218 -0
- data/lib/vagrant-xapi/services/console.rb +115 -0
- data/lib/vagrant-xapi/services/content_diff.rb +96 -0
- data/lib/vagrant-xapi/services/destroyer.rb +104 -0
- data/lib/vagrant-xapi/services/diff_disks.rb +346 -0
- data/lib/vagrant-xapi/services/differ.rb +382 -0
- data/lib/vagrant-xapi/services/disk_image.rb +122 -0
- data/lib/vagrant-xapi/services/disks.rb +281 -0
- data/lib/vagrant-xapi/services/exporter.rb +128 -0
- data/lib/vagrant-xapi/services/file_diff.rb +249 -0
- data/lib/vagrant-xapi/services/guest_files.rb +730 -0
- data/lib/vagrant-xapi/services/hosts.rb +55 -0
- data/lib/vagrant-xapi/services/image_upload.rb +172 -0
- data/lib/vagrant-xapi/services/inventory.rb +225 -0
- data/lib/vagrant-xapi/services/ip_detector.rb +107 -0
- data/lib/vagrant-xapi/services/lock.rb +293 -0
- data/lib/vagrant-xapi/services/lookup.rb +181 -0
- data/lib/vagrant-xapi/services/networks.rb +248 -0
- data/lib/vagrant-xapi/services/power.rb +108 -0
- data/lib/vagrant-xapi/services/rfb.rb +129 -0
- data/lib/vagrant-xapi/services/snapshots.rb +81 -0
- data/lib/vagrant-xapi/services/template_cache.rb +263 -0
- data/lib/vagrant-xapi/services/tunnels.rb +217 -0
- data/lib/vagrant-xapi/services/vm_builder.rb +215 -0
- data/lib/vagrant-xapi/version.rb +7 -0
- data/lib/vagrant-xapi/xenserver/config.rb +69 -0
- data/lib/vagrant-xapi/xenserver/migrate.rb +103 -0
- data/lib/vagrant-xapi/xenserver/plugin.rb +96 -0
- data/lib/vagrant-xapi/xenserver/provider.rb +22 -0
- data/lib/vagrant-xapi/xenserver/takeover.rb +79 -0
- data/lib/vagrant-xapi.rb +21 -2
- data/lib/xenapi.rb +22 -0
- data/locales/en.yml +517 -0
- data/locales/legacy.en.yml +6 -0
- 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
|