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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile +12 -0
  6. data/LICENSE +13 -0
  7. data/README.md +109 -0
  8. data/Rakefile +22 -0
  9. data/example_box/README.md +9 -0
  10. data/example_box/Vagrantfile +20 -0
  11. data/example_box/kubevirt.box +0 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-kubevirt.rb +18 -0
  14. data/lib/vagrant-kubevirt/action.rb +176 -0
  15. data/lib/vagrant-kubevirt/action/connect_kubevirt.rb +37 -0
  16. data/lib/vagrant-kubevirt/action/create_vm.rb +133 -0
  17. data/lib/vagrant-kubevirt/action/destroy_vm.rb +30 -0
  18. data/lib/vagrant-kubevirt/action/is_created.rb +18 -0
  19. data/lib/vagrant-kubevirt/action/is_stopped.rb +18 -0
  20. data/lib/vagrant-kubevirt/action/read_ssh_info.rb +54 -0
  21. data/lib/vagrant-kubevirt/action/read_state.rb +44 -0
  22. data/lib/vagrant-kubevirt/action/set_domain_name.rb +33 -0
  23. data/lib/vagrant-kubevirt/action/start_vm.rb +35 -0
  24. data/lib/vagrant-kubevirt/action/stop_vm.rb +37 -0
  25. data/lib/vagrant-kubevirt/action/wait_for_state.rb +64 -0
  26. data/lib/vagrant-kubevirt/config.rb +60 -0
  27. data/lib/vagrant-kubevirt/errors.rb +39 -0
  28. data/lib/vagrant-kubevirt/plugin.rb +73 -0
  29. data/lib/vagrant-kubevirt/provider.rb +50 -0
  30. data/lib/vagrant-kubevirt/version.rb +5 -0
  31. data/locales/en.yml +69 -0
  32. data/spec/spec_helper.rb +6 -0
  33. data/spec/support/environment_helper.rb +18 -0
  34. data/spec/support/kubevirt_context.rb +15 -0
  35. data/spec/support/sharedcontext.rb +33 -0
  36. data/spec/unit/action/create_vm_spec.rb +122 -0
  37. data/spec/unit/action/destroy_vm_spec.rb +33 -0
  38. data/spec/unit/action/read_ssh_info_spec.rb +45 -0
  39. data/spec/unit/action/read_state_spec.rb +44 -0
  40. data/spec/unit/action/start_vm_spec.rb +44 -0
  41. data/spec/unit/action/stop_vm_spec.rb +57 -0
  42. data/spec/unit/action/wait_for_state_spec.rb +57 -0
  43. data/spec/unit/config_spec.rb +41 -0
  44. data/vagrant-kubevirt.gemspec +26 -0
  45. 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