vagrant-kubevirt 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 +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +12 -0
- data/LICENSE +13 -0
- data/README.md +109 -0
- data/Rakefile +22 -0
- data/example_box/README.md +9 -0
- data/example_box/Vagrantfile +20 -0
- data/example_box/kubevirt.box +0 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-kubevirt.rb +18 -0
- data/lib/vagrant-kubevirt/action.rb +176 -0
- data/lib/vagrant-kubevirt/action/connect_kubevirt.rb +37 -0
- data/lib/vagrant-kubevirt/action/create_vm.rb +133 -0
- data/lib/vagrant-kubevirt/action/destroy_vm.rb +30 -0
- data/lib/vagrant-kubevirt/action/is_created.rb +18 -0
- data/lib/vagrant-kubevirt/action/is_stopped.rb +18 -0
- data/lib/vagrant-kubevirt/action/read_ssh_info.rb +54 -0
- data/lib/vagrant-kubevirt/action/read_state.rb +44 -0
- data/lib/vagrant-kubevirt/action/set_domain_name.rb +33 -0
- data/lib/vagrant-kubevirt/action/start_vm.rb +35 -0
- data/lib/vagrant-kubevirt/action/stop_vm.rb +37 -0
- data/lib/vagrant-kubevirt/action/wait_for_state.rb +64 -0
- data/lib/vagrant-kubevirt/config.rb +60 -0
- data/lib/vagrant-kubevirt/errors.rb +39 -0
- data/lib/vagrant-kubevirt/plugin.rb +73 -0
- data/lib/vagrant-kubevirt/provider.rb +50 -0
- data/lib/vagrant-kubevirt/version.rb +5 -0
- data/locales/en.yml +69 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/environment_helper.rb +18 -0
- data/spec/support/kubevirt_context.rb +15 -0
- data/spec/support/sharedcontext.rb +33 -0
- data/spec/unit/action/create_vm_spec.rb +122 -0
- data/spec/unit/action/destroy_vm_spec.rb +33 -0
- data/spec/unit/action/read_ssh_info_spec.rb +45 -0
- data/spec/unit/action/read_state_spec.rb +44 -0
- data/spec/unit/action/start_vm_spec.rb +44 -0
- data/spec/unit/action/stop_vm_spec.rb +57 -0
- data/spec/unit/action/wait_for_state_spec.rb +57 -0
- data/spec/unit/config_spec.rb +41 -0
- data/vagrant-kubevirt.gemspec +26 -0
- metadata +161 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'vagrant/util/retryable'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module Kubevirt
|
8
|
+
module Action
|
9
|
+
# This creates the virtual machine.
|
10
|
+
class CreateVM
|
11
|
+
include Vagrant::Util::Retryable
|
12
|
+
|
13
|
+
def initialize(app, env)
|
14
|
+
@app = app
|
15
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::create_vm")
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
# Get config.
|
20
|
+
config = env[:machine].provider_config
|
21
|
+
ssh_info = env[:machine].config.ssh
|
22
|
+
|
23
|
+
vm_name = env[:domain_name]
|
24
|
+
namespace = config.namespace
|
25
|
+
cpus = config.cpus
|
26
|
+
memory_size = config.memory
|
27
|
+
image = config.image
|
28
|
+
pvc = config.pvc
|
29
|
+
port_node = config.port_node
|
30
|
+
|
31
|
+
template = config.template
|
32
|
+
|
33
|
+
# Output the settings we're going to use to the user
|
34
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.creating_vm"))
|
35
|
+
env[:ui].info(" -- Name: #{vm_name}")
|
36
|
+
env[:ui].info(" -- Namespace: #{namespace}")
|
37
|
+
env[:ui].info(" -- Cpus: #{cpus}")
|
38
|
+
env[:ui].info(" -- Memory: #{memory_size}M")
|
39
|
+
|
40
|
+
kubevirt = env[:kubevirt_compute]
|
41
|
+
|
42
|
+
if template == nil
|
43
|
+
volumes = []
|
44
|
+
if !image.nil?
|
45
|
+
volume = Fog::Kubevirt::Compute::Volume.new
|
46
|
+
volume.type = 'containerDisk'
|
47
|
+
volume.info = image
|
48
|
+
volumes << volume
|
49
|
+
end
|
50
|
+
if !pvc.nil?
|
51
|
+
volume = Fog::Kubevirt::Compute::Volume.new
|
52
|
+
volume.type = 'persistentVolumeClaim'
|
53
|
+
volume.info = pvc
|
54
|
+
volumes << volume
|
55
|
+
end
|
56
|
+
provision_vm(kubevirt, vm_name, cpus, memory_size, volumes, ssh_info)
|
57
|
+
else
|
58
|
+
env[:ui].info(" -- Template: #{template}")
|
59
|
+
provision_from_template(kubevirt, template, vm_name, cpus, memory_size)
|
60
|
+
end
|
61
|
+
|
62
|
+
create_service(kubevirt, vm_name, port_node)
|
63
|
+
|
64
|
+
vm = kubevirt.vms.get(vm_name)
|
65
|
+
env[:machine].id = vm.name
|
66
|
+
|
67
|
+
# Terminate the instance if we were interrupted
|
68
|
+
terminate(env) if env[:interrupted]
|
69
|
+
|
70
|
+
@app.call(env)
|
71
|
+
end
|
72
|
+
|
73
|
+
def recover(env)
|
74
|
+
return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
|
75
|
+
|
76
|
+
if env[:machine].provider.state.id != :not_created
|
77
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.error_recovering"))
|
78
|
+
terminate(env)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def provision_from_template(kubevirt, template, vm_name, cpus, memory_size)
|
85
|
+
begin
|
86
|
+
temp = kubevirt.templates.get(template)
|
87
|
+
temp.clone(name: vm_name, memory: memory_size, cpu_cores: cpus)
|
88
|
+
rescue Fog::Errors::Error => e
|
89
|
+
raise Errors::FogError, :message => e.message
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def provision_vm(kubevirt, vm_name, cpus, memory_size, volumes, ssh_info)
|
94
|
+
begin
|
95
|
+
init = {}
|
96
|
+
userData = ""
|
97
|
+
|
98
|
+
unless ssh_info.username.nil?
|
99
|
+
userData.concat("user: #{ssh_info.username}\n")
|
100
|
+
end
|
101
|
+
unless ssh_info.password.nil?
|
102
|
+
userData.concat("password: #{ssh_info.password}\n")
|
103
|
+
end
|
104
|
+
|
105
|
+
unless userData.empty?
|
106
|
+
init = {:userData => "#cloud-config\n#{userData}chpasswd: { expire: False }"}
|
107
|
+
end
|
108
|
+
|
109
|
+
kubevirt.vms.create(vm_name: vm_name, cpus: cpus, memory_size: memory_size, volumes: volumes, cloudinit: init)
|
110
|
+
rescue Fog::Errors::Error => e
|
111
|
+
raise Errors::FogError, :message => e.message
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_service(kubevirt, vm_name, port_node)
|
116
|
+
begin
|
117
|
+
kubevirt.services.create(port: port_node, name: "#{vm_name}-ssh", target_port: 22, vmi_name: vm_name, service_type: "NodePort")
|
118
|
+
rescue Fog::Errors::Error => e
|
119
|
+
raise Errors::FogError, :message => e.message
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def terminate(env)
|
124
|
+
destroy_env = env.dup
|
125
|
+
destroy_env.delete(:interrupted)
|
126
|
+
destroy_env[:config_validate] = false
|
127
|
+
destroy_env[:force_confirm_destroy] = true
|
128
|
+
env[:action_runner].run(Action.action_destroy, destroy_env)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Kubevirt
|
5
|
+
module Action
|
6
|
+
class DestroyVM
|
7
|
+
def initialize(app, env)
|
8
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::destroy_vm")
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
# Destroy the server, remove the tracking ID
|
14
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.destroy_vm"))
|
15
|
+
kubevirt = env[:kubevirt_compute]
|
16
|
+
|
17
|
+
name = env[:machine].id.to_s
|
18
|
+
config = env[:machine].provider_config
|
19
|
+
|
20
|
+
kubevirt.vminstances.destroy(name, config.namespace)
|
21
|
+
kubevirt.services.delete("#{name}-ssh")
|
22
|
+
|
23
|
+
env[:machine].id = nil
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Kubevirt
|
3
|
+
module Action
|
4
|
+
# This can be used with "Call" built-in to check if the machine
|
5
|
+
# is created and branch in the middleware.
|
6
|
+
class IsCreated
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:result] = env[:machine].state.id != :not_created
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Kubevirt
|
3
|
+
module Action
|
4
|
+
# This can be used with "Call" built-in to check if the machine
|
5
|
+
# is stopped and branch in the middleware.
|
6
|
+
class IsStopped
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:result] = env[:machine].state.id == 'stopped'
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Kubevirt
|
5
|
+
module Action
|
6
|
+
# This action reads the SSH info for the machine and puts it into the
|
7
|
+
# `:machine_ssh_info` key in the environment.
|
8
|
+
class ReadSSHInfo
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::read_ssh_info")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_ssh_info] = read_ssh_info(env[:kubevirt_compute], env[:machine])
|
16
|
+
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_ssh_info(kubevirt, machine)
|
21
|
+
return nil if machine.id.nil?
|
22
|
+
|
23
|
+
vmi_name = machine.id
|
24
|
+
|
25
|
+
# Find the machine
|
26
|
+
vmi = kubevirt.vminstances.get(vmi_name)
|
27
|
+
if vmi.nil?
|
28
|
+
# The machine can't be found
|
29
|
+
@logger.info(I18n.t("vagrant_kubevirt.vm_not_found"))
|
30
|
+
machine.id = nil
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
|
34
|
+
node_name = vmi.node_name
|
35
|
+
if node_name.nil?
|
36
|
+
@logger.info(I18n.t("vagrant_kubevirt.not_running"))
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
service = kubevirt.services.get("#{vmi_name}-ssh")
|
41
|
+
if service.nil?
|
42
|
+
raise Errors::NoServiceError, :name => vmi_name
|
43
|
+
end
|
44
|
+
|
45
|
+
info = { :host => vmi.node_name, :port => service.node_port }
|
46
|
+
key_path = machine.config.ssh.private_key_path
|
47
|
+
info[:private_key_path] = key_path unless key_path.nil? || key_path.empty?
|
48
|
+
|
49
|
+
return info
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Kubevirt
|
5
|
+
module Action
|
6
|
+
# This action reads the state of the machine and puts it in the
|
7
|
+
# `:machine_state_id` key in the environment.
|
8
|
+
class ReadState
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::read_state")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_state_id] = read_state(env[:kubevirt_compute], env[:machine])
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_state(kubevirt, machine)
|
20
|
+
return :not_created if machine.id.nil?
|
21
|
+
|
22
|
+
begin
|
23
|
+
# Find the machine
|
24
|
+
vm = kubevirt.vms.get(machine.id)
|
25
|
+
rescue Fog::Kubevirt::Errors::ClientError => e
|
26
|
+
msg = e.message
|
27
|
+
|
28
|
+
unless msg.include? '404'
|
29
|
+
raise Errors::FogError, :message => msg
|
30
|
+
else
|
31
|
+
# The machine can't be found
|
32
|
+
@logger.info(I18n.t("vagrant_kubevirt.vm_not_found"))
|
33
|
+
machine.id = nil
|
34
|
+
return :not_created
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the state
|
39
|
+
return vm.status
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Kubevirt
|
3
|
+
module Action
|
4
|
+
|
5
|
+
# Setup name for domain.
|
6
|
+
class SetDomainName
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:domain_name] = env[:root_path].basename.to_s.dup
|
13
|
+
env[:domain_name].gsub!(/([_.])/, '-')
|
14
|
+
|
15
|
+
# Check if the domain name is not already taken
|
16
|
+
kubevirt = env[:kubevirt_compute]
|
17
|
+
begin
|
18
|
+
kubevirt.vms.get(env[:domain_name])
|
19
|
+
rescue Fog::Kubevirt::Errors::ClientError => e
|
20
|
+
msg = e.message
|
21
|
+
|
22
|
+
unless msg.include? '404'
|
23
|
+
raise Errors::FogError, :message => msg
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
require 'log4r'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Kubevirt
|
6
|
+
module Action
|
7
|
+
|
8
|
+
# Just start the VM.
|
9
|
+
class StartVM
|
10
|
+
def initialize(app, env)
|
11
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::start_vm")
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.starting_vm"))
|
17
|
+
|
18
|
+
kubevirt = env[:kubevirt_compute]
|
19
|
+
# Start VM.
|
20
|
+
begin
|
21
|
+
vm = kubevirt.vms.get(env[:machine].id.to_s)
|
22
|
+
if vm == nil
|
23
|
+
raise Errors::NoVMError, :vm_name => env[:domain_name]
|
24
|
+
end
|
25
|
+
vm.start
|
26
|
+
rescue Fog::Errors::Error => e
|
27
|
+
raise Errors::StartVMError, :message => e.message
|
28
|
+
end
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Kubevirt
|
6
|
+
module Action
|
7
|
+
# This stops the running instance.
|
8
|
+
class StopVM
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::stop_vm")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
begin
|
16
|
+
kubevirt = env[:kubevirt_compute]
|
17
|
+
vm = kubevirt.vms.get(env[:machine].id.to_s)
|
18
|
+
if vm == nil
|
19
|
+
raise Errors::NoVMError, :vm_name => env[:domain_name]
|
20
|
+
end
|
21
|
+
|
22
|
+
if vm.status == :stopped
|
23
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.already_status", :status => env[:machine].state.id))
|
24
|
+
else
|
25
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.stopping"))
|
26
|
+
vm.stop
|
27
|
+
end
|
28
|
+
rescue Fog::Errors::Error => e
|
29
|
+
raise Errors::StopVMError, :message => e.message
|
30
|
+
end
|
31
|
+
|
32
|
+
@app.call(env)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "timeout"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Kubevirt
|
6
|
+
module Action
|
7
|
+
# This action will wait for a machine to reach a specific state or quit by timeout
|
8
|
+
class WaitForState
|
9
|
+
# env[:result] will be false in case of timeout.
|
10
|
+
# @param [Symbol] state Target machine state.
|
11
|
+
# @param [Number] timeout Timeout in seconds.
|
12
|
+
def initialize(app, env, state, timeout)
|
13
|
+
@app = app
|
14
|
+
@logger = Log4r::Logger.new("vagrant_kubevirt::action::wait_for_state")
|
15
|
+
@state = state
|
16
|
+
@timeout = timeout
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
env[:result] = true
|
22
|
+
vm_name = env[:domain_name]
|
23
|
+
kubevirt = env[:kubevirt_compute]
|
24
|
+
|
25
|
+
|
26
|
+
if @state.to_s == 'running'
|
27
|
+
watch = kubevirt.watch_vminstances
|
28
|
+
kind = 'VirtualMachineInstance'
|
29
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.wait_for_boot"))
|
30
|
+
else
|
31
|
+
watch = kubevirt.watch_vms
|
32
|
+
kind = 'VirtualMachine'
|
33
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.wait_for_state", :state => @state))
|
34
|
+
end
|
35
|
+
|
36
|
+
vm = kubevirt.vms.get(vm_name)
|
37
|
+
|
38
|
+
if vm.status == @state
|
39
|
+
env[:ui].info(I18n.t("vagrant_kubevirt.already_status", :status => @state))
|
40
|
+
else
|
41
|
+
begin
|
42
|
+
Timeout.timeout(@timeout) do
|
43
|
+
watch.each do |notice|
|
44
|
+
break if notice.kind == kind && notice.name == vm_name && !notice.status.nil? && notice.status.downcase == @state.to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
rescue Timeout::Error
|
48
|
+
raise Errors::VMReadyTimeout, timeout: @timeout
|
49
|
+
end
|
50
|
+
end
|
51
|
+
watch.finish
|
52
|
+
|
53
|
+
# wait for sshd to be up
|
54
|
+
if @state.to_s == 'running'
|
55
|
+
wait = env[:machine].config.vm.boot_timeout
|
56
|
+
env[:machine].communicate.wait_for_ready(wait)
|
57
|
+
end
|
58
|
+
|
59
|
+
@app.call(env)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|