vagrant-kubevirt 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,60 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
require "iniparse"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Kubevirt
|
6
|
+
class Config < Vagrant.plugin("2", :config)
|
7
|
+
|
8
|
+
attr_accessor :token
|
9
|
+
attr_accessor :hostname
|
10
|
+
attr_accessor :port
|
11
|
+
attr_accessor :namespace
|
12
|
+
|
13
|
+
# Domain specific settings used while creating new machine.
|
14
|
+
attr_accessor :memory
|
15
|
+
attr_accessor :cpus
|
16
|
+
attr_accessor :template
|
17
|
+
attr_accessor :image
|
18
|
+
attr_accessor :pvc
|
19
|
+
attr_accessor :port_node
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@token = UNSET_VALUE
|
23
|
+
@hostname = UNSET_VALUE
|
24
|
+
@port = UNSET_VALUE
|
25
|
+
@namespace = UNSET_VALUE
|
26
|
+
|
27
|
+
@memory = UNSET_VALUE
|
28
|
+
@cpus = UNSET_VALUE
|
29
|
+
@template = UNSET_VALUE
|
30
|
+
@image = UNSET_VALUE
|
31
|
+
@pvc = UNSET_VALUE
|
32
|
+
@port_node = UNSET_VALUE
|
33
|
+
end
|
34
|
+
|
35
|
+
def finalize!
|
36
|
+
@token = nil if @token == UNSET_VALUE
|
37
|
+
@hostname = 'localhost' if @hostname == UNSET_VALUE
|
38
|
+
@port = '8443' if @port == UNSET_VALUE
|
39
|
+
@namespace = 'default' if @namespace == UNSET_VALUE
|
40
|
+
|
41
|
+
@memory = 512 if @memory == UNSET_VALUE
|
42
|
+
@cpus = 1 if @cpus == UNSET_VALUE
|
43
|
+
@template = nil if @template == UNSET_VALUE
|
44
|
+
@image = nil if @image == UNSET_VALUE
|
45
|
+
@pvc = nil if @pvc == UNSET_VALUE
|
46
|
+
@port_node = 30000 if @port_node == UNSET_VALUE
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate(machine)
|
50
|
+
errors = _detected_errors
|
51
|
+
|
52
|
+
config = machine.provider_config
|
53
|
+
|
54
|
+
errors << I18n.t("vagrant_kubevirt.config.image_info_required") if config.template.nil? and config.image.nil? and config.pvc.nil?
|
55
|
+
|
56
|
+
{ 'Kubevirt Provider' => errors }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Kubevirt
|
5
|
+
module Errors
|
6
|
+
class VagrantKubevirtError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_kubevirt.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class FogError < VagrantKubevirtError
|
11
|
+
error_key(:fog_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoVMError < VagrantKubevirtError
|
15
|
+
error_key(:no_vm_error)
|
16
|
+
end
|
17
|
+
|
18
|
+
class StartVMError < VagrantKubevirtError
|
19
|
+
error_key(:start_vm_error)
|
20
|
+
end
|
21
|
+
|
22
|
+
class StopVMError < VagrantKubevirtError
|
23
|
+
error_key(:stop_vm_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class VMReadyTimeout < VagrantKubevirtError
|
27
|
+
error_key(:vm_ready_timeout)
|
28
|
+
end
|
29
|
+
|
30
|
+
class NoNodeError < VagrantKubevirtError
|
31
|
+
error_key(:no_node_error)
|
32
|
+
end
|
33
|
+
|
34
|
+
class NoServiceError < VagrantKubevirtError
|
35
|
+
error_key(:no_service_error)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The Vagrant Kubevirt plugin must be run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
8
|
+
# this into an early Vagrant version.
|
9
|
+
if Vagrant::VERSION < "1.2.0"
|
10
|
+
raise "The Vagrant Kubevirt plugin is only compatible with Vagrant 1.2+"
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module Kubevirt
|
15
|
+
class Plugin < Vagrant.plugin('2')
|
16
|
+
name "Kubevirt"
|
17
|
+
description <<-DESC
|
18
|
+
This plugin installs a provider that allows Vagrant to manage
|
19
|
+
Kubevirt machines.
|
20
|
+
DESC
|
21
|
+
|
22
|
+
config(:kubevirt, :provider) do
|
23
|
+
require_relative "config"
|
24
|
+
Config
|
25
|
+
end
|
26
|
+
|
27
|
+
provider(:kubevirt, parallel: true) do
|
28
|
+
# Setup logging and i18n
|
29
|
+
setup_logging
|
30
|
+
setup_i18n
|
31
|
+
|
32
|
+
# Return the provider
|
33
|
+
require_relative "provider"
|
34
|
+
Provider
|
35
|
+
end
|
36
|
+
|
37
|
+
# This initializes the internationalization strings.
|
38
|
+
def self.setup_i18n
|
39
|
+
I18n.load_path << File.expand_path("locales/en.yml", Kubevirt.source_root)
|
40
|
+
I18n.reload!
|
41
|
+
end
|
42
|
+
|
43
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
44
|
+
def self.setup_logging
|
45
|
+
require "log4r"
|
46
|
+
|
47
|
+
level = nil
|
48
|
+
begin
|
49
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
50
|
+
rescue NameError
|
51
|
+
# This means that the logging constant wasn't found,
|
52
|
+
# which is fine. We just keep `level` as `nil`. But
|
53
|
+
# we tell the user.
|
54
|
+
level = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Some constants, such as "true" resolve to booleans, so the
|
58
|
+
# above error checking doesn't catch it. This will check to make
|
59
|
+
# sure that the log level is an integer, as Log4r requires.
|
60
|
+
level = nil if !level.is_a?(Integer)
|
61
|
+
|
62
|
+
# Set the logging level on all "vagrant" namespaced
|
63
|
+
# logs as long as we have a valid level.
|
64
|
+
if level
|
65
|
+
logger = Log4r::Logger.new("vagrant_kubevirt")
|
66
|
+
logger.outputters = Log4r::Outputter.stderr
|
67
|
+
logger.level = level
|
68
|
+
logger = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "vagrant"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Kubevirt
|
6
|
+
class Provider < Vagrant.plugin("2", :provider)
|
7
|
+
def initialize(machine)
|
8
|
+
@machine = machine
|
9
|
+
end
|
10
|
+
|
11
|
+
def action(name)
|
12
|
+
# Attempt to get the action method from the Action class if it
|
13
|
+
# exists, otherwise return nil to show that we don't support the
|
14
|
+
# given action.
|
15
|
+
action_method = "action_#{name}"
|
16
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def ssh_info
|
21
|
+
# Run a custom action called "read_ssh_info" which does what it
|
22
|
+
# says and puts the resulting SSH info into the `:machine_ssh_info`
|
23
|
+
# key in the environment.
|
24
|
+
env = @machine.action("read_ssh_info", lock: false)
|
25
|
+
env[:machine_ssh_info]
|
26
|
+
end
|
27
|
+
|
28
|
+
def state
|
29
|
+
# Run a custom action we define called "read_state" which does
|
30
|
+
# what it says. It puts the state in the `:machine_state_id`
|
31
|
+
# key in the environment.
|
32
|
+
env = @machine.action("read_state", lock: false)
|
33
|
+
|
34
|
+
state_id = env[:machine_state_id]
|
35
|
+
|
36
|
+
# Get the short and long description
|
37
|
+
short = I18n.t("vagrant_kubevirt.states.short_#{state_id}")
|
38
|
+
long = I18n.t("vagrant_kubevirt.states.long_#{state_id}")
|
39
|
+
|
40
|
+
# Return the MachineState object
|
41
|
+
Vagrant::MachineState.new(state_id, short, long)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
id = @machine.id.nil? ? "new" : @machine.id
|
46
|
+
"Kubevirt (#{id})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_kubevirt:
|
3
|
+
creating_vm: |-
|
4
|
+
Creating VM with the following settings...
|
5
|
+
already_status: |-
|
6
|
+
The VM is already %{status}.
|
7
|
+
error_recovering: |-
|
8
|
+
An error occured. Recovering..
|
9
|
+
starting_vm: |-
|
10
|
+
Starting the VM...
|
11
|
+
wait_for_state: |-
|
12
|
+
Waiting for VM to reach state %{state}
|
13
|
+
not_created: |-
|
14
|
+
Virtual machine is not created. Please run `vagrant up` first.
|
15
|
+
action_failed: |-
|
16
|
+
%{action} failed.
|
17
|
+
stopping: |-
|
18
|
+
Stopping the VM...
|
19
|
+
destroy_vm: |-
|
20
|
+
Removing the VM...
|
21
|
+
vm_not_found: |-
|
22
|
+
The VM not found or terminated, assuming it got destroyed.
|
23
|
+
vm_exists: |-
|
24
|
+
The VM is already created
|
25
|
+
not_running: |-
|
26
|
+
The VM is not running
|
27
|
+
wait_for_boot: |-
|
28
|
+
Waiting for VM to boot
|
29
|
+
|
30
|
+
config:
|
31
|
+
kubevirt_info_required: |-
|
32
|
+
One or more of the needed Kubevirt connection details are missing.
|
33
|
+
image_info_required: |-
|
34
|
+
Either template, pvc or image details are required.
|
35
|
+
|
36
|
+
states:
|
37
|
+
short_not_created: |-
|
38
|
+
not created
|
39
|
+
long_not_created: |-
|
40
|
+
The virtual machine is not created. Run `vagrant up` to create it.
|
41
|
+
short_running: |-
|
42
|
+
running
|
43
|
+
long_running: |-
|
44
|
+
The virtual machine is running. To stop this machine, you can run
|
45
|
+
`vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
|
46
|
+
short_stopped: |-
|
47
|
+
stopped
|
48
|
+
long_stopped: |-
|
49
|
+
The virtual machine is stopped. Run `vagrant up` to start it.
|
50
|
+
|
51
|
+
errors:
|
52
|
+
fog_error: |-
|
53
|
+
There was an error talking to Kubevirt. The error message is shown
|
54
|
+
below:
|
55
|
+
|
56
|
+
%{message}
|
57
|
+
no_vm_error: |-
|
58
|
+
No VM %{vm_name} found.
|
59
|
+
start_vm_error: |-
|
60
|
+
Unable to start VM: %{message}
|
61
|
+
stop_vm_error: |-
|
62
|
+
Unable to stop VM: %{message}
|
63
|
+
vm_ready_timeout: |-
|
64
|
+
The VM never became "ready" in AWS. The timeout currently
|
65
|
+
set waiting for the vm to become ready is %{timeout} seconds.
|
66
|
+
no_node_error: |-
|
67
|
+
The VM is not running on a node.
|
68
|
+
no_service_error: |-
|
69
|
+
No service configured for VM: %{name}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fog/kubevirt'
|
2
|
+
|
3
|
+
shared_context 'kubevirt' do
|
4
|
+
include_context 'unit'
|
5
|
+
|
6
|
+
let(:kubevirt_context) { true }
|
7
|
+
let(:id) { 'dummy-vagrant_dummy' }
|
8
|
+
|
9
|
+
before (:each) do
|
10
|
+
stub_const('Fog::Kubevirt::Compute', compute)
|
11
|
+
allow(compute).to receive(:new).with(hash_including(:kubevirt_hostname, :kubevirt_port, :kubevirt_token, :kubevirt_namespace, :kubevirt_log)).and_return(compute)
|
12
|
+
|
13
|
+
allow(machine).to receive(:id).and_return(id)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_context 'unit' do
|
4
|
+
include_context 'vagrant-unit'
|
5
|
+
|
6
|
+
let(:vagrantfile) do
|
7
|
+
<<-EOF
|
8
|
+
Vagrant.configure('2') do |config|
|
9
|
+
config.vm.box = 'kubevirt'
|
10
|
+
config.vm.define :test
|
11
|
+
|
12
|
+
config.vm.provider :kubevirt do |kubevirt|
|
13
|
+
kubevirt.token = 'abc'
|
14
|
+
kubevirt.template = 'working'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
EOF
|
18
|
+
end
|
19
|
+
let(:test_env) do
|
20
|
+
test_env = isolated_environment
|
21
|
+
test_env.vagrantfile vagrantfile
|
22
|
+
test_env
|
23
|
+
end
|
24
|
+
let(:env) { { env: iso_env, machine: machine, ui: ui, root_path: File.expand_path(File.dirname(__FILE__)), kubevirt_compute: compute, domain_name: 'Test', action_runner: runner} }
|
25
|
+
let(:conf) { Vagrant::Config::V2::DummyConfig.new }
|
26
|
+
let(:ui) { Vagrant::UI::Basic.new }
|
27
|
+
let(:iso_env) { test_env.create_vagrant_env ui_class: Vagrant::UI::Basic }
|
28
|
+
let(:machine) { iso_env.machine(:test, :kubevirt) }
|
29
|
+
let(:app) { ->(env) {} }
|
30
|
+
let(:plugin) { register_plugin }
|
31
|
+
let(:compute) { double('compute') }
|
32
|
+
let(:runner) { double('runner') }
|
33
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'support/sharedcontext'
|
2
|
+
require 'support/kubevirt_context'
|
3
|
+
|
4
|
+
require 'vagrant-kubevirt/action/create_vm'
|
5
|
+
|
6
|
+
describe VagrantPlugins::Kubevirt::Action::CreateVM do
|
7
|
+
subject { described_class.new(app, env) }
|
8
|
+
|
9
|
+
include_context 'unit'
|
10
|
+
include_context 'kubevirt'
|
11
|
+
|
12
|
+
let(:services) { double('service') }
|
13
|
+
let(:vms) { double('vms') }
|
14
|
+
let(:vm) { double('vm') }
|
15
|
+
|
16
|
+
describe '#call' do
|
17
|
+
before do
|
18
|
+
allow(compute).to receive(:vms).and_return(vms)
|
19
|
+
allow(compute).to receive(:services).and_return(services)
|
20
|
+
allow(services).to receive(:create)
|
21
|
+
|
22
|
+
allow(vms).to receive(:get).and_return(vm)
|
23
|
+
allow(vm).to receive(:name).and_return('Test')
|
24
|
+
|
25
|
+
expect(ui).to receive(:info).with('Creating VM with the following settings...')
|
26
|
+
expect(ui).to receive(:info).with(' -- Name: Test')
|
27
|
+
expect(ui).to receive(:info).with(' -- Namespace: default')
|
28
|
+
expect(ui).to receive(:info).with(' -- Cpus: 1')
|
29
|
+
expect(ui).to receive(:info).with(' -- Memory: 512M')
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when template defined' do
|
33
|
+
let(:templates) { double('templates') }
|
34
|
+
let(:template) { double('template') }
|
35
|
+
|
36
|
+
before do
|
37
|
+
allow(compute).to receive(:templates).and_return(templates)
|
38
|
+
allow(templates).to receive(:get).and_return(template)
|
39
|
+
|
40
|
+
expect(template).to receive(:clone)
|
41
|
+
expect(ui).to receive(:info).with(' -- Template: working')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'clones a template' do
|
45
|
+
expect(subject.call(env)).to be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'recovers after interruption' do
|
49
|
+
env[:interrupted] = true
|
50
|
+
expect(runner).to receive(:run)
|
51
|
+
|
52
|
+
expect(subject.call(env)).to be_nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when image defined' do
|
57
|
+
let(:vagrantfile) do
|
58
|
+
<<-EOF
|
59
|
+
Vagrant.configure('2') do |config|
|
60
|
+
config.vm.box = 'kubevirt'
|
61
|
+
config.vm.define :test
|
62
|
+
|
63
|
+
config.vm.provider :kubevirt do |kubevirt|
|
64
|
+
kubevirt.token = 'abc'
|
65
|
+
kubevirt.image = 'kubevirt/fedora'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
EOF
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'creates a vm using image' do
|
72
|
+
expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => 'kubevirt/fedora', :pvc => nil))
|
73
|
+
|
74
|
+
expect(subject.call(env)).to be_nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when pvc defined' do
|
79
|
+
let(:vagrantfile) do
|
80
|
+
<<-EOF
|
81
|
+
Vagrant.configure('2') do |config|
|
82
|
+
config.vm.box = 'kubevirt'
|
83
|
+
config.vm.define :test
|
84
|
+
|
85
|
+
config.vm.provider :kubevirt do |kubevirt|
|
86
|
+
kubevirt.token = 'abc'
|
87
|
+
kubevirt.pvc = 'my_disk'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
EOF
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'creates a vm using pvc' do
|
94
|
+
expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => nil, :pvc => "my_disk"))
|
95
|
+
|
96
|
+
expect(subject.call(env)).to be_nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'with folders synchronized' do
|
101
|
+
let(:vagrantfile) do
|
102
|
+
<<-EOF
|
103
|
+
Vagrant.configure('2') do |config|
|
104
|
+
config.vm.box = 'kubevirt'
|
105
|
+
config.vm.define :test
|
106
|
+
config.vm.synced_folder "", "/srv/website"
|
107
|
+
config.vm.provider :kubevirt do |kubevirt|
|
108
|
+
kubevirt.token = 'abc'
|
109
|
+
kubevirt.image = 'kubevirt/fedora'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
EOF
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'creates a vm with folder defined' do
|
116
|
+
expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => 'kubevirt/fedora', :pvc => nil))
|
117
|
+
|
118
|
+
expect(subject.call(env)).to be_nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|