vagrant-ovirt3 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +211 -0
  6. data/Rakefile +7 -0
  7. data/example_box/README.md +13 -0
  8. data/example_box/Vagrantfile +18 -0
  9. data/example_box/dummy.box +0 -0
  10. data/example_box/metadata.json +4 -0
  11. data/lib/vagrant-ovirt3.rb +42 -0
  12. data/lib/vagrant-ovirt3/action.rb +131 -0
  13. data/lib/vagrant-ovirt3/action/connect_ovirt.rb +84 -0
  14. data/lib/vagrant-ovirt3/action/create_network_interfaces.rb +137 -0
  15. data/lib/vagrant-ovirt3/action/create_vm.rb +113 -0
  16. data/lib/vagrant-ovirt3/action/destroy_vm.rb +25 -0
  17. data/lib/vagrant-ovirt3/action/is_created.rb +18 -0
  18. data/lib/vagrant-ovirt3/action/message_already_created.rb +16 -0
  19. data/lib/vagrant-ovirt3/action/message_not_created.rb +16 -0
  20. data/lib/vagrant-ovirt3/action/read_ssh_info.rb +56 -0
  21. data/lib/vagrant-ovirt3/action/read_state.rb +37 -0
  22. data/lib/vagrant-ovirt3/action/resize_disk.rb +71 -0
  23. data/lib/vagrant-ovirt3/action/set_name_of_domain.rb +31 -0
  24. data/lib/vagrant-ovirt3/action/start_vm.rb +37 -0
  25. data/lib/vagrant-ovirt3/action/sync_folders.rb +65 -0
  26. data/lib/vagrant-ovirt3/action/wait_till_up.rb +94 -0
  27. data/lib/vagrant-ovirt3/config.rb +58 -0
  28. data/lib/vagrant-ovirt3/errors.rb +76 -0
  29. data/lib/vagrant-ovirt3/plugin.rb +74 -0
  30. data/lib/vagrant-ovirt3/provider.rb +76 -0
  31. data/lib/vagrant-ovirt3/util.rb +9 -0
  32. data/lib/vagrant-ovirt3/util/collection.rb +21 -0
  33. data/lib/vagrant-ovirt3/util/timer.rb +17 -0
  34. data/lib/vagrant-ovirt3/version.rb +6 -0
  35. data/locales/en.yml +90 -0
  36. data/tools/prepare_redhat_for_box.sh +132 -0
  37. data/vagrant-ovirt3.gemspec +25 -0
  38. metadata +129 -0
@@ -0,0 +1,84 @@
1
+ require 'fog'
2
+ require 'log4r'
3
+ require 'pp'
4
+ require 'rbovirt'
5
+
6
+ module VagrantPlugins
7
+ module OVirtProvider
8
+ module Action
9
+ class ConnectOVirt
10
+ def initialize(app, env)
11
+ @logger = Log4r::Logger.new("vagrant_ovirt3::action::connect_ovirt")
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+
17
+ # We need both, fog and rbovirt client. Sometimes fog doesn't
18
+ # support some operations like managing quotas, or working with
19
+ # networks. For this rbovirt client is used.
20
+ env[:ovirt_client] = OVirtProvider.ovirt_client if \
21
+ OVirtProvider.ovirt_client != nil
22
+
23
+ if OVirtProvider.ovirt_connection != nil
24
+ env[:ovirt_compute] = OVirtProvider.ovirt_connection
25
+ return @app.call(env)
26
+ end
27
+
28
+ # Get config options for ovirt provider.
29
+ config = env[:machine].provider_config
30
+
31
+ conn_attr = {}
32
+ conn_attr[:provider] = 'ovirt'
33
+ conn_attr[:ovirt_url] = "#{config.url}/api"
34
+ conn_attr[:ovirt_username] = config.username if config.username
35
+ conn_attr[:ovirt_password] = config.password if config.password
36
+
37
+ # We need datacenter id in fog connection initialization. But it's
38
+ # much simpler to use datacenter name in Vagrantfile. So get
39
+ # datacenter id here from rbovirt client before connecting to fog.
40
+ env[:ovirt_client] = ovirt_connect(conn_attr)
41
+ begin
42
+ datacenter = OVirtProvider::Util::Collection.find_matching(
43
+ env[:ovirt_client].datacenters, config.datacenter)
44
+ rescue OVIRT::OvirtException => e
45
+ raise Errors::FogOVirtConnectionError,
46
+ :error_message => e.message
47
+ end
48
+
49
+ raise Errors::NoDatacenterError if datacenter == nil
50
+ conn_attr[:ovirt_datacenter] = datacenter.id
51
+
52
+ # Reconnect and prepar rbovirt client with datacenter set from
53
+ # configuration.
54
+ env[:ovirt_client] = ovirt_connect(conn_attr)
55
+ OVirtProvider.ovirt_client = env[:ovirt_client]
56
+
57
+ # Establish fog connection now.
58
+ @logger.info("Connecting to oVirt (#{config.url}) ...")
59
+ begin
60
+ env[:ovirt_compute] = Fog::Compute.new(conn_attr)
61
+ rescue OVIRT::OvirtException => e
62
+ raise Errors::FogOVirtConnectionError,
63
+ :error_message => e.message
64
+ end
65
+ OVirtProvider.ovirt_connection = env[:ovirt_compute]
66
+
67
+ @app.call(env)
68
+ end
69
+
70
+ private
71
+
72
+ def ovirt_connect(credentials)
73
+ OVIRT::Client.new(
74
+ credentials[:ovirt_username],
75
+ credentials[:ovirt_password],
76
+ credentials[:ovirt_url],
77
+ credentials[:ovirt_datacenter],
78
+ )
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,137 @@
1
+ require 'log4r'
2
+ require 'vagrant/util/scoped_hash_override'
3
+
4
+ module VagrantPlugins
5
+ module OVirtProvider
6
+ module Action
7
+ # Create network interfaces for machine, before VM is running.
8
+ class CreateNetworkInterfaces
9
+ include Vagrant::Util::ScopedHashOverride
10
+
11
+ def initialize(app, env)
12
+ @logger = Log4r::Logger.new("vagrant_ovirt3::action::create_network_interfaces")
13
+ @app = app
14
+ end
15
+
16
+ def call(env)
17
+ # Get machine first.
18
+ begin
19
+ machine = OVirtProvider::Util::Collection.find_matching(
20
+ env[:ovirt_compute].servers.all, env[:machine].id.to_s)
21
+ rescue => e
22
+ raise Errors::NoVMError,
23
+ :vm_name => env[:machine].id.to_s
24
+ end
25
+
26
+ # Setup list of interfaces before creating them
27
+ adapters = []
28
+
29
+ # First interface is for provisioning, so this slot is not usable.
30
+ # This interface should be available already from template.
31
+
32
+ env[:machine].config.vm.networks.each do |type, options|
33
+ # We support private and public networks only. They mean both the
34
+ # same right now.
35
+ next if type != :private_network and type != :public_network
36
+
37
+ # Get options for this interface. Options can be specified in
38
+ # Vagrantfile in short format (:ip => ...), or provider format
39
+ # (:ovirt__network_name => ...).
40
+ options = scoped_hash_override(options, :ovirt)
41
+ options = {
42
+ :netmask => '255.255.255.0',
43
+ :network_name => 'rhevm',
44
+ :interface_type => 'virtio'
45
+ }.merge(options)
46
+
47
+ if options[:adapter]
48
+ if adapters[options[:adapter]]
49
+ raise Errors::InterfaceSlotNotAvailable
50
+ end
51
+
52
+ free_slot = options[:adapter].to_i
53
+ else
54
+ free_slot = find_empty(adapters, start=1)
55
+ raise Errors::InterfaceSlotNotAvailable if free_slot == nil
56
+ end
57
+
58
+ adapters[free_slot] = options
59
+ end
60
+
61
+ # Create each interface as new domain device
62
+ adapters.each_with_index do |opts, slot_number|
63
+ next if slot_number == 0 or opts.nil?
64
+ iface_number = slot_number + 1
65
+
66
+ # Get network id
67
+ network = OVirtProvider::Util::Collection.find_matching(
68
+ env[:ovirt_client].networks(:cluster_id => env[:ovirt_cluster].id),
69
+ opts[:network_name])
70
+ if network == nil
71
+ raise Errors::NoNetworkError,
72
+ :network_name => opts[:network_name]
73
+ end
74
+
75
+ @logger.info("Creating network interface nic#{iface_number}")
76
+ begin
77
+ machine.add_interface(
78
+ :name => "nic#{iface_number}",
79
+ :network => network.id,
80
+ :interface => opts[:interface_type],
81
+ )
82
+ rescue => e
83
+ raise Errors::AddInterfaceError,
84
+ :error_message => e.message
85
+ end
86
+ end
87
+
88
+ # Continue the middleware chain.
89
+ @app.call(env)
90
+
91
+ # Configure interfaces that user requested. Machine should be up and
92
+ # running now.
93
+ networks_to_configure = []
94
+
95
+ adapters.each_with_index do |opts, slot_number|
96
+ # Skip configuring first interface. It's used for provisioning and
97
+ # it has to be available during provisioning - ifdown command is
98
+ # not acceptable here.
99
+ next if slot_number == 0
100
+
101
+ network = {
102
+ :interface => slot_number,
103
+ #:mac => ...,
104
+ }
105
+
106
+ if opts[:ip]
107
+ network = {
108
+ :type => :static,
109
+ :ip => opts[:ip],
110
+ :netmask => opts[:netmask],
111
+ :gateway => opts[:gateway],
112
+ }.merge(network)
113
+ else
114
+ network[:type] = :dhcp
115
+ end
116
+
117
+ networks_to_configure << network
118
+ end
119
+
120
+ env[:ui].info I18n.t("vagrant.actions.vm.network.configuring")
121
+ env[:machine].guest.capability(
122
+ :configure_networks, networks_to_configure)
123
+ end
124
+
125
+ private
126
+
127
+ def find_empty(array, start=0, stop=8)
128
+ for i in start..stop
129
+ return i if !array[i]
130
+ end
131
+ return nil
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,113 @@
1
+ require 'log4r'
2
+ require 'vagrant/util/retryable'
3
+
4
+ module VagrantPlugins
5
+ module OVirtProvider
6
+ module Action
7
+ class CreateVM
8
+ include Vagrant::Util::Retryable
9
+
10
+ def initialize(app, env)
11
+ @logger = Log4r::Logger.new("vagrant_ovirt3::action::create_vm")
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ # Get config.
17
+ config = env[:machine].provider_config
18
+
19
+ # Gather some info about domain
20
+ name = env[:domain_name]
21
+ console = config.console
22
+ cpus = config.cpus
23
+ memory_size = config.memory*1024
24
+
25
+ # Get cluster
26
+ if config.cluster == nil
27
+ cluster = env[:ovirt_compute].clusters.first
28
+ else
29
+ cluster = OVirtProvider::Util::Collection.find_matching(
30
+ env[:ovirt_compute].clusters.all, config.cluster)
31
+ end
32
+ raise Error::NoClusterError if cluster == nil
33
+ # TODO fill env also with other ovirtoptions.
34
+ env[:ovirt_cluster] = cluster
35
+
36
+ # Get template
37
+ template = OVirtProvider::Util::Collection.find_matching(
38
+ env[:ovirt_compute].templates.all, config.template)
39
+ if template == nil
40
+ raise Error::NoTemplateError,
41
+ :template_name => config.template
42
+ end
43
+
44
+ # Output the settings we're going to use to the user
45
+ env[:ui].info(I18n.t("vagrant_ovirt3.creating_vm"))
46
+ env[:ui].info(" -- Name: #{name}")
47
+ env[:ui].info(" -- Cpus: #{cpus}")
48
+ env[:ui].info(" -- Memory: #{memory_size/1024}M")
49
+ env[:ui].info(" -- Template: #{template.name}")
50
+ env[:ui].info(" -- Datacenter: #{config.datacenter}")
51
+ env[:ui].info(" -- Cluster: #{cluster.name}")
52
+ env[:ui].info(" -- Console: #{console}")
53
+ if config.disk_size
54
+ env[:ui].info(" -- Disk size: #{config.disk_size}G")
55
+ end
56
+
57
+ # Create oVirt VM.
58
+ attr = {
59
+ :name => name,
60
+ :cores => cpus,
61
+ :memory => memory_size*1024,
62
+ :cluster => cluster.id,
63
+ :template => template.id,
64
+ :display => {:type => console },
65
+ }
66
+
67
+ begin
68
+ server = env[:ovirt_compute].servers.create(attr)
69
+ rescue OVIRT::OvirtException => e
70
+ raise Errors::FogCreateServerError,
71
+ :error_message => e.message
72
+ end
73
+
74
+ # Immediately save the ID since it is created at this point.
75
+ env[:machine].id = server.id
76
+
77
+ # Wait till all volumes are ready.
78
+ env[:ui].info(I18n.t("vagrant_ovirt3.wait_for_ready_vm"))
79
+ for i in 0..10
80
+ ready = true
81
+ server = env[:ovirt_compute].servers.get(env[:machine].id.to_s)
82
+ server.volumes.each do |volume|
83
+ if volume.status != 'ok'
84
+ ready = false
85
+ break
86
+ end
87
+ end
88
+ break if ready
89
+ sleep 2
90
+ end
91
+
92
+ if not ready
93
+ raise Errors::WaitForReadyVmTimeout
94
+ end
95
+
96
+ @app.call(env)
97
+ end
98
+
99
+ def recover(env)
100
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
101
+
102
+ # Undo the import
103
+ env[:ui].info(I18n.t("vagrant_ovirt3.error_recovering"))
104
+ destroy_env = env.dup
105
+ destroy_env.delete(:interrupted)
106
+ destroy_env[:config_validate] = false
107
+ destroy_env[:force_confirm_destroy] = true
108
+ env[:action_runner].run(Action.action_destroy, destroy_env)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,25 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module OVirtProvider
5
+ module Action
6
+ class DestroyVM
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_ovirt3::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_ovirt3.destroy_vm"))
15
+
16
+ machine = env[:ovirt_compute].servers.get(env[:machine].id.to_s)
17
+ machine.destroy
18
+ env[:machine].id = nil
19
+
20
+ @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module OVirtProvider
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,16 @@
1
+ module VagrantPlugins
2
+ module OVirtProvider
3
+ module Action
4
+ class MessageAlreadyCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_ovirt3.already_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module OVirtProvider
3
+ module Action
4
+ class MessageNotCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_ovirt3.not_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,56 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module OVirtProvider
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_ovirt3::action::read_ssh_info")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_ssh_info] = read_ssh_info(
16
+ env[:ovirt_compute], env[:machine])
17
+
18
+ @app.call(env)
19
+ end
20
+
21
+ def read_ssh_info(ovirt, machine)
22
+ return nil if machine.id.nil?
23
+
24
+ # Get config.
25
+ config = machine.provider_config
26
+
27
+ # Find the machine
28
+ server = ovirt.servers.get(machine.id.to_s)
29
+
30
+ if server.nil?
31
+ # The machine can't be found
32
+ @logger.info("Machine couldn't be found, assuming it got destroyed.")
33
+ machine.id = nil
34
+ return nil
35
+ end
36
+
37
+ ip_address = server.ips.first
38
+ if ip_address == nil or ip_address == ''
39
+ raise Errors::NoIpAddressError
40
+ end
41
+
42
+ # Return the info
43
+ # TODO: Some info should be configurable in Vagrantfile
44
+ return {
45
+ :host => ip_address,
46
+ :port => machine.config.ssh.guest_port,
47
+ :username => machine.config.ssh.username,
48
+ :private_key_path => machine.config.ssh.private_key_path,
49
+ :forward_agent => machine.config.ssh.forward_agent,
50
+ :forward_x11 => machine.config.ssh.forward_x11,
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end