vagrant-ovirt3 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/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +211 -0
- data/Rakefile +7 -0
- data/example_box/README.md +13 -0
- data/example_box/Vagrantfile +18 -0
- data/example_box/dummy.box +0 -0
- data/example_box/metadata.json +4 -0
- data/lib/vagrant-ovirt3.rb +42 -0
- data/lib/vagrant-ovirt3/action.rb +131 -0
- data/lib/vagrant-ovirt3/action/connect_ovirt.rb +84 -0
- data/lib/vagrant-ovirt3/action/create_network_interfaces.rb +137 -0
- data/lib/vagrant-ovirt3/action/create_vm.rb +113 -0
- data/lib/vagrant-ovirt3/action/destroy_vm.rb +25 -0
- data/lib/vagrant-ovirt3/action/is_created.rb +18 -0
- data/lib/vagrant-ovirt3/action/message_already_created.rb +16 -0
- data/lib/vagrant-ovirt3/action/message_not_created.rb +16 -0
- data/lib/vagrant-ovirt3/action/read_ssh_info.rb +56 -0
- data/lib/vagrant-ovirt3/action/read_state.rb +37 -0
- data/lib/vagrant-ovirt3/action/resize_disk.rb +71 -0
- data/lib/vagrant-ovirt3/action/set_name_of_domain.rb +31 -0
- data/lib/vagrant-ovirt3/action/start_vm.rb +37 -0
- data/lib/vagrant-ovirt3/action/sync_folders.rb +65 -0
- data/lib/vagrant-ovirt3/action/wait_till_up.rb +94 -0
- data/lib/vagrant-ovirt3/config.rb +58 -0
- data/lib/vagrant-ovirt3/errors.rb +76 -0
- data/lib/vagrant-ovirt3/plugin.rb +74 -0
- data/lib/vagrant-ovirt3/provider.rb +76 -0
- data/lib/vagrant-ovirt3/util.rb +9 -0
- data/lib/vagrant-ovirt3/util/collection.rb +21 -0
- data/lib/vagrant-ovirt3/util/timer.rb +17 -0
- data/lib/vagrant-ovirt3/version.rb +6 -0
- data/locales/en.yml +90 -0
- data/tools/prepare_redhat_for_box.sh +132 -0
- data/vagrant-ovirt3.gemspec +25 -0
- 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
|