vagrant-kubevirt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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