vagrant-kvm 0.1.7 → 0.1.8
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.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/CHANGELOG.md +0 -7
- data/DEVELOPMENT.md +69 -0
- data/INSTALL.md +1 -1
- data/README.md +61 -47
- data/bin/package.sh +83 -0
- data/install.rb +7 -0
- data/lib/vagrant-kvm/action.rb +23 -31
- data/lib/vagrant-kvm/action/customize.rb +44 -0
- data/lib/vagrant-kvm/action/import.rb +52 -23
- data/lib/vagrant-kvm/action/init_storage_pool.rb +5 -4
- data/lib/vagrant-kvm/action/network.rb +127 -30
- data/lib/vagrant-kvm/action/{prepare_gui.rb → prepare_kvmconfig.rb} +4 -1
- data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +16 -23
- data/lib/vagrant-kvm/action/set_name.rb +27 -3
- data/lib/vagrant-kvm/action/share_folders.rb +4 -5
- data/lib/vagrant-kvm/cap/mount_p9.rb +40 -0
- data/lib/vagrant-kvm/config.rb +73 -1
- data/lib/vagrant-kvm/driver/driver.rb +303 -117
- data/lib/vagrant-kvm/errors.rb +4 -4
- data/lib/vagrant-kvm/plugin.rb +12 -2
- data/lib/vagrant-kvm/provider.rb +2 -19
- data/lib/vagrant-kvm/synced_folder.rb +57 -0
- data/lib/vagrant-kvm/util/network_definition.rb +30 -3
- data/lib/vagrant-kvm/util/vm_definition.rb +110 -11
- data/lib/vagrant-kvm/version.rb +1 -1
- data/locales/en.yml +5 -3
- data/locales/ja.yml +11 -4
- data/spec/vagrant-kvm/config_spec.rb +6 -0
- data/spec/vagrant-kvm/driver/driver_spec.rb +4 -3
- data/spec/vagrant-kvm/util/vm_definition_spec.rb +4 -8
- data/templates/libvirt_domain.erb +29 -3
- data/vagrant-kvm.gemspec +3 -3
- metadata +21 -9
- data/lib/vagrant-kvm/action/prune_nfs_exports.rb +0 -20
@@ -25,12 +25,11 @@ module VagrantPlugins
|
|
25
25
|
def shared_folders
|
26
26
|
{}.tap do |result|
|
27
27
|
@env[:machine].config.vm.synced_folders.each do |id, data|
|
28
|
-
|
29
|
-
#next if data[:nfs]
|
28
|
+
next if data[:disabled]
|
30
29
|
|
31
|
-
unless
|
32
|
-
|
33
|
-
|
30
|
+
data[:nfs] = true unless @env[:machine].provider_config.enable_virtfs
|
31
|
+
|
32
|
+
if data[:nfs]
|
34
33
|
# This to prevent overwriting the actual shared folders data
|
35
34
|
result[id] = data.dup
|
36
35
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
require "vagrant/util/retryable"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ProviderKvm
|
6
|
+
module Cap
|
7
|
+
class MountP9
|
8
|
+
extend Vagrant::Util::Retryable
|
9
|
+
|
10
|
+
def self.mount_p9_shared_folder(machine, folders, options)
|
11
|
+
folders.each do |name, opts|
|
12
|
+
# Expand the guest path so we can handle things like "~/vagrant"
|
13
|
+
expanded_guest_path = machine.guest.capability(
|
14
|
+
:shell_expand_guest_path, opts[:guestpath])
|
15
|
+
|
16
|
+
# Do the actual creating and mounting
|
17
|
+
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
18
|
+
|
19
|
+
# Mount
|
20
|
+
# tag maximum len is 31
|
21
|
+
mount_tag = Digest::MD5.new.update(name).to_s[0,31]
|
22
|
+
|
23
|
+
mount_opts="-o trans=virtio"
|
24
|
+
mount_opts += ",access=#{options[:owner]}" if options[:owner]
|
25
|
+
mount_opts += ",version=#{options[:version]}" if options[:version]
|
26
|
+
mount_opts += ",#{opts[:mount_options]}" if opts[:mount_options]
|
27
|
+
|
28
|
+
mount_command = "mount -t 9p #{mount_opts} '#{mount_tag}' #{expanded_guest_path}"
|
29
|
+
retryable(:on => Vagrant::Errors::LinuxMountFailed,
|
30
|
+
:tries => 5,
|
31
|
+
:sleep => 3) do
|
32
|
+
machine.communicate.sudo(mount_command,
|
33
|
+
:error_class => Vagrant::Errors::LinuxMountFailed)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/vagrant-kvm/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'etc'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module ProviderKvm
|
3
5
|
class Config < Vagrant.plugin("2", :config)
|
@@ -21,6 +23,11 @@ module VagrantPlugins
|
|
21
23
|
# @return [Hash]
|
22
24
|
attr_reader :network_adapters
|
23
25
|
|
26
|
+
# The storage pool to use
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
attr_accessor :storage_pool
|
30
|
+
|
24
31
|
# The VM image format
|
25
32
|
#
|
26
33
|
# @return [String]
|
@@ -63,11 +70,27 @@ module VagrantPlugins
|
|
63
70
|
attr_accessor :machine_type
|
64
71
|
attr_accessor :network_model
|
65
72
|
attr_accessor :video_model
|
73
|
+
attr_accessor :sound
|
74
|
+
attr_accessor :virtio_rng
|
75
|
+
|
76
|
+
# disk bus type
|
77
|
+
# sata/virtio
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
attr_accessor :disk_bus
|
81
|
+
|
82
|
+
# Security labelling
|
83
|
+
# default: off
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
attr_accessor :seclabel
|
66
87
|
attr_accessor :force_pause
|
67
88
|
|
68
89
|
def initialize
|
90
|
+
@customizations = []
|
69
91
|
@name = UNSET_VALUE
|
70
92
|
@gui = UNSET_VALUE
|
93
|
+
@storage_pool = UNSET_VALUE
|
71
94
|
@image_type = UNSET_VALUE
|
72
95
|
@image_mode = UNSET_VALUE
|
73
96
|
@qemu_bin = UNSET_VALUE
|
@@ -80,7 +103,27 @@ module VagrantPlugins
|
|
80
103
|
@machine_type = UNSET_VALUE
|
81
104
|
@network_model = UNSET_VALUE
|
82
105
|
@video_model = UNSET_VALUE
|
83
|
-
@
|
106
|
+
@disk_bus = UNSET_VALUE
|
107
|
+
@sound = UNSET_VALUE
|
108
|
+
@force_pause = UNSET_VALUE
|
109
|
+
@enable_virtfs = UNSET_VALUE
|
110
|
+
@virtio_rng = UNSET_VALUE
|
111
|
+
end
|
112
|
+
|
113
|
+
# Customize the VM by predefined actions.
|
114
|
+
#
|
115
|
+
# When called multiple times, the customizations will be applied
|
116
|
+
# in the order given.
|
117
|
+
#
|
118
|
+
# The special `:name` parameter in the command will be replaced with
|
119
|
+
# the unique ID or name of the virtual machine. This is useful for
|
120
|
+
# parameters to `modifyvm` and the like.
|
121
|
+
#
|
122
|
+
# @param [Array] command An array of arguments to pass to
|
123
|
+
def customize(*command)
|
124
|
+
event = command.first.is_a?(String) ? command.shift : "pre-boot"
|
125
|
+
command = command[0]
|
126
|
+
@customizations << [event, command]
|
84
127
|
end
|
85
128
|
|
86
129
|
# This is the hook that is called to finalize the object before it
|
@@ -90,6 +133,9 @@ module VagrantPlugins
|
|
90
133
|
@name = nil if @name == UNSET_VALUE
|
91
134
|
# Default is to not show a GUI
|
92
135
|
@gui = false if @gui == UNSET_VALUE
|
136
|
+
# Default is a storage pool we create for vagrant
|
137
|
+
login = Etc.getlogin
|
138
|
+
@storage_pool = 'vagrant-'+login.to_s if @storage_pool == UNSET_VALUE
|
93
139
|
# Default image type is a sparsed raw
|
94
140
|
@image_type = 'qcow2' if @image_type == UNSET_VALUE
|
95
141
|
case @image_mode
|
@@ -141,7 +187,33 @@ module VagrantPlugins
|
|
141
187
|
@machine_type = "pc-1.2" if @machine_type == UNSET_VALUE
|
142
188
|
@network_model = "virtio" if @network_model == UNSET_VALUE
|
143
189
|
@video_model = "cirrus" if @video_model == UNSET_VALUE
|
190
|
+
@disk_bus = nil if @disk_bus == UNSET_VALUE
|
191
|
+
@sound = false if @sound == UNSET_VALUE
|
144
192
|
@force_pause = false if @force_pause == UNSET_VALUE
|
193
|
+
@enable_virtfs = false if @enable_virtfs == UNSET_VALUE
|
194
|
+
@virtio_rng = nil if @virtio_rng == UNSET_VALUE
|
195
|
+
end
|
196
|
+
|
197
|
+
def validate(machine)
|
198
|
+
errors = []
|
199
|
+
|
200
|
+
valid_events = ["pre-import", "pre-boot", "post-boot"]
|
201
|
+
@customizations.each do |event, _|
|
202
|
+
if !valid_events.include?(event)
|
203
|
+
errors << I18n.t(
|
204
|
+
"vagrant.kvm.config.invalid_event",
|
205
|
+
event: event.to_s,
|
206
|
+
valid_events: valid_events.join(", "))
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
@customizations.each do |event, command|
|
211
|
+
if event == "pre-import" && command.index(:id)
|
212
|
+
errors << I18n.t("vagrant.kvm.config.id_in_pre_import")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
{ "KVM Provider" => errors }
|
145
217
|
end
|
146
218
|
end
|
147
219
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'libvirt'
|
2
2
|
require 'log4r'
|
3
|
+
require 'pathname'
|
4
|
+
require "rexml/document"
|
3
5
|
|
4
6
|
module VagrantPlugins
|
5
7
|
module ProviderKvm
|
@@ -29,27 +31,17 @@ module VagrantPlugins
|
|
29
31
|
# The UUID of the virtual machine we represent
|
30
32
|
attr_reader :uuid
|
31
33
|
|
32
|
-
# The QEMU version
|
33
|
-
# XXX sufficient or have to check kvm and libvirt versions?
|
34
|
-
attr_reader :version
|
35
|
-
|
36
|
-
# KVM support status
|
37
|
-
attr_reader :kvm
|
38
|
-
|
39
34
|
# Vagrant 1.5.x pool migration
|
40
35
|
attr_reader :pool_migrate
|
41
36
|
|
42
37
|
def initialize(uuid=nil)
|
43
38
|
@logger = Log4r::Logger.new("vagrant::provider::kvm::driver")
|
44
39
|
@uuid = uuid
|
45
|
-
|
46
|
-
@pool_name = "vagrant"
|
47
|
-
@network_name = "vagrant"
|
40
|
+
@virsh_path = "virsh"
|
48
41
|
@pool_migrate = false
|
49
42
|
|
50
43
|
load_kvm_module!
|
51
44
|
connect_libvirt_qemu!
|
52
|
-
init_storage_pool!
|
53
45
|
|
54
46
|
if @uuid
|
55
47
|
# Verify the VM exists, and if it doesn't, then don't worry
|
@@ -150,17 +142,20 @@ module VagrantPlugins
|
|
150
142
|
# @param [String] definition Path to the VM XML file.
|
151
143
|
# @param [String] volume_name Name of the imported volume
|
152
144
|
# @param [Hash] attributes
|
153
|
-
def import(
|
145
|
+
def import(box_xml_filename, volume_name, args={})
|
154
146
|
@logger.info("Importing VM #{@name}")
|
155
147
|
# create vm definition from xml
|
156
|
-
definition = File.open(
|
148
|
+
definition = File.open(box_xml_filename) { |f| Util::VmDefinition.new(f.read) }
|
157
149
|
volume_path = lookup_volume_path_by_name(volume_name)
|
158
150
|
args = {
|
159
151
|
:image_type => "qcow2",
|
160
152
|
:qemu_bin => "/usr/bin/qemu",
|
161
153
|
:disk => volume_path,
|
162
|
-
:
|
154
|
+
:network => 'vagrant',
|
155
|
+
:name => @name,
|
156
|
+
:uuid => nil
|
163
157
|
}.merge(args)
|
158
|
+
args.merge!(:virtio_rng => nil) if @conn.version.to_i < 1003000 # virtio_rng supported in 1.3.0+
|
164
159
|
definition.update(args)
|
165
160
|
# create vm
|
166
161
|
@logger.info("Creating new VM")
|
@@ -172,33 +167,58 @@ module VagrantPlugins
|
|
172
167
|
|
173
168
|
# Create network
|
174
169
|
def create_network(config)
|
170
|
+
# Get the network if it exists
|
171
|
+
network_name = config[:name]
|
172
|
+
hosts = config[:hosts]
|
173
|
+
@logger.info("empty host!") unless hosts
|
175
174
|
begin
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
@logger.info("Creating network #{@network_name}")
|
187
|
-
@network = define_network(definition)
|
188
|
-
else
|
175
|
+
network = @conn.lookup_network_by_name(network_name)
|
176
|
+
definition = Util::NetworkDefinition.new(network_name,
|
177
|
+
network.xml_desc)
|
178
|
+
old_def = Util::NetworkDefinition.new(network_name,
|
179
|
+
network.xml_desc)
|
180
|
+
definition.update(config)
|
181
|
+
@logger.info("Update network #{network_name}")
|
182
|
+
@logger.debug("From:\n#{old_def.as_xml}")
|
183
|
+
@logger.debug("TO:\n#{definition.as_xml}")
|
184
|
+
|
189
185
|
# Only destroy existing network if config has changed. This is
|
190
186
|
# necessary because other VM could be currently using this network
|
191
187
|
# and will loose connectivity if the network is destroyed.
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
188
|
+
if network.active?
|
189
|
+
@logger.info "Reusing existing configuration for #{network_name}"
|
190
|
+
update_command = Libvirt::Network::NETWORK_UPDATE_COMMAND_ADD_LAST
|
191
|
+
hosts.each do |host|
|
192
|
+
if old_def.already_exist_host?(host)
|
193
|
+
update_command = Libvirt::Network::NETWORK_UPDATE_COMMAND_MODIFY
|
194
|
+
end
|
195
|
+
end
|
196
|
+
if update_command == Libvirt::Network::NETWORK_UPDATE_COMMAND_MODIFY
|
197
|
+
@logger.info ("Updating network #{network_name} using UPDATE_COMMAND_MODIFY")
|
198
|
+
else
|
199
|
+
@logger.info ("Updating network #{network_name} using UPDATE_COMMAND_ADD_LAST")
|
200
|
+
end
|
201
|
+
|
202
|
+
network.update(update_command,
|
203
|
+
Libvirt::Network::NETWORK_SECTION_IP_DHCP_HOST,
|
204
|
+
-1,
|
205
|
+
definition.as_host_xml,
|
206
|
+
Libvirt::Network::NETWORK_UPDATE_AFFECT_CURRENT
|
207
|
+
)
|
208
|
+
network.create unless network.active?
|
209
|
+
else # network is not active
|
210
|
+
@logger.info "Recreating network config for #{network_name}"
|
211
|
+
network.undefine
|
212
|
+
network = define_network(definition)
|
201
213
|
end
|
214
|
+
|
215
|
+
rescue Libvirt::RetrieveError
|
216
|
+
# Network doesn't exist, create with defaults
|
217
|
+
definition = Util::NetworkDefinition.new(network_name)
|
218
|
+
definition.update(config)
|
219
|
+
@logger.info("Creating network #{network_name}")
|
220
|
+
@logger.debug("with\n#{definition.as_xml}")
|
221
|
+
network = define_network(definition)
|
202
222
|
end
|
203
223
|
end
|
204
224
|
|
@@ -210,68 +230,100 @@ module VagrantPlugins
|
|
210
230
|
network
|
211
231
|
end
|
212
232
|
|
213
|
-
|
214
|
-
|
215
|
-
# Storage pool doesn't exist so we create it
|
216
|
-
# create dir if it doesn't exist
|
217
|
-
# if we let libvirt create the dir it is owned by root
|
218
|
-
pool_path = File.join(base_path, "/storage-pool")
|
219
|
-
FileUtils.mkpath(pool_path) unless Dir.exists?(pool_path)
|
220
|
-
init_storage_directory(
|
221
|
-
:pool_path => pool_path,
|
222
|
-
:pool_name => @pool_name,
|
223
|
-
:owner => uid, :group=>gid, :mode=>'755')
|
224
|
-
init_storage_pool!
|
233
|
+
def get_default_ip
|
234
|
+
"192.168.123.10"
|
225
235
|
end
|
226
236
|
|
227
|
-
def
|
237
|
+
def read_machine_ip
|
238
|
+
if @uuid && vm_exists?(@uuid)
|
239
|
+
begin
|
240
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
241
|
+
definition = Util::VmDefinition.new(domain.xml_desc)
|
242
|
+
mac_address = definition.get(:mac)
|
243
|
+
network_name = definition.get(:network)
|
244
|
+
network = @conn.lookup_network_by_name(network_name)
|
245
|
+
network_definition = Util::NetworkDefinition.new(network_name,
|
246
|
+
network.xml_desc)
|
247
|
+
network_definition.get(:hosts).each do |host|
|
248
|
+
return host[:ip] if mac_address == host[:mac]
|
249
|
+
end
|
250
|
+
rescue Libvirt::RetrieveError
|
251
|
+
@logger.info("cannot get definition og #{@uuid}")
|
252
|
+
end
|
253
|
+
else
|
254
|
+
@logger.debug("missing uuid? #{@uuid}")
|
255
|
+
end
|
256
|
+
get_default_ip
|
257
|
+
end
|
258
|
+
|
259
|
+
# Activate the driver's storage pool
|
260
|
+
def activate_storage_pool(pool_name)
|
261
|
+
# Get storage pool if it exists
|
262
|
+
@pool = init_storage_pool(pool_name)
|
263
|
+
# check neccesity of migrating to new storage pool format
|
264
|
+
# this is happen when user has already used vagrant-kvm 0.1.5 and after
|
265
|
+
# XXX needs clarification
|
266
|
+
check_migrate_box_storage_pool
|
267
|
+
@logger.info("Retrieving storage pool #{pool_name}")
|
268
|
+
end
|
269
|
+
|
270
|
+
# Initialize or Create a new storage pool
|
271
|
+
def init_storage_pool(pool_name, pool_path='/tmp', dir_mode='0755')
|
228
272
|
begin
|
229
|
-
#
|
230
|
-
pool = @conn.lookup_storage_pool_by_name(
|
231
|
-
@logger.info("
|
273
|
+
# Try to retrieve the storage pool
|
274
|
+
pool = @conn.lookup_storage_pool_by_name(pool_name)
|
275
|
+
@logger.info("Activating storage pool #{pool_name}")
|
276
|
+
pool.create unless pool.active?
|
277
|
+
pool.refresh
|
278
|
+
pool
|
232
279
|
rescue Libvirt::RetrieveError
|
233
|
-
|
234
|
-
|
280
|
+
create_storage_pool(pool_name, pool_path, dir_mode)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def create_storage_pool(pool_name, pool_path, dir_mode)
|
285
|
+
@logger.info("Creating new storage pool #{pool_name} in #{pool_path}")
|
286
|
+
# create dir if it doesn't exist
|
287
|
+
FileUtils.mkpath(pool_path) unless Dir.exists?(pool_path)
|
288
|
+
storage_pool_xml = <<-EOF
|
235
289
|
<pool type="dir">
|
236
|
-
<name>#{
|
290
|
+
<name>#{pool_name}</name>
|
237
291
|
<target>
|
238
|
-
<path>#{
|
292
|
+
<path>#{pool_path}</path>
|
239
293
|
<permissions>
|
240
|
-
<owner>#{
|
241
|
-
<group>#{
|
242
|
-
<mode>#{
|
294
|
+
<owner>#{Process.uid}</owner>
|
295
|
+
<group>#{Process.gid}</group>
|
296
|
+
<mode>#{dir_mode}</mode>
|
243
297
|
</permissions>
|
244
298
|
</target>
|
245
299
|
</pool>
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
# pool = @conn.define_storage_pool_xml(storage_pool_xml)
|
252
|
-
# that made 'pesistent' storage pool
|
253
|
-
# this caused problem when following sinario:
|
254
|
-
#
|
255
|
-
# 1. user use vagrant-kvm 0.1.5 with vagrant-1.4.x
|
256
|
-
# 2. user upgrade vagrant 1.5.x
|
257
|
-
# 3. user upgrade vagrant 0.1.5.1 and after
|
258
|
-
#
|
259
|
-
# vagrant-kvm 0.1.5 don't work with vagrant 1.5.x
|
260
|
-
# previous synario can be happned on many user.
|
261
|
-
#
|
262
|
-
# We use transient pool instead of persistent one
|
263
|
-
# in vagrant-kvm 0.1.5.x, 0.1.6 and after
|
264
|
-
#
|
265
|
-
# Pools defined here will be removed after system reboot.
|
266
|
-
#
|
300
|
+
EOF
|
301
|
+
# Create transient pool
|
302
|
+
# Pools defined here will be removed after system reboot.
|
303
|
+
@logger.debug("Creating storage pool with XML:\n #{storage_pool_xml}")
|
304
|
+
begin
|
267
305
|
pool = @conn.create_storage_pool_xml(storage_pool_xml)
|
268
306
|
pool.build unless pool.active?
|
269
|
-
|
270
|
-
|
307
|
+
pool.refresh
|
308
|
+
pool
|
309
|
+
rescue
|
310
|
+
# check conflict and shutdown old pool
|
311
|
+
defined_pool_list = @conn.list_storage_pools
|
312
|
+
defined_pool_list.each do |defined_pool_name|
|
313
|
+
defined_pool = @conn.lookup_storage_pool_by_name(defined_pool_name)
|
314
|
+
defined_pool_doc = REXML::Document.new defined_pool.xml_desc
|
315
|
+
defined_pool_path = File.expand_path(defined_pool_doc.elements["/pool/target/path"].text)
|
316
|
+
@logger.debug("check whether conflict with #{defined_pool_name} on #{defined_pool_path}")
|
317
|
+
if defined_pool_path == File.expand_path(pool_path)
|
318
|
+
defined_pool.destroy
|
319
|
+
pool = @conn.create_storage_pool_xml(storage_pool_xml)
|
320
|
+
pool.build unless pool.active?
|
321
|
+
pool.refresh
|
322
|
+
return pool
|
323
|
+
end
|
324
|
+
end
|
325
|
+
raise Errors::KvmFailStoragePool
|
271
326
|
end
|
272
|
-
pool.create unless pool.active?
|
273
|
-
pool.refresh
|
274
|
-
pool
|
275
327
|
end
|
276
328
|
|
277
329
|
def check_migrate_box_storage_pool
|
@@ -286,7 +338,7 @@ module VagrantPlugins
|
|
286
338
|
@pool_migrate = true
|
287
339
|
end
|
288
340
|
rescue Libvirt::RetrieveError
|
289
|
-
|
341
|
+
raise Errors::KvmFailStoragePool
|
290
342
|
end
|
291
343
|
end
|
292
344
|
end
|
@@ -302,11 +354,45 @@ module VagrantPlugins
|
|
302
354
|
end
|
303
355
|
end
|
304
356
|
|
357
|
+
def storage_pool_path
|
358
|
+
doc = REXML::Document.new @pool.xml_desc
|
359
|
+
doc.elements["/pool/target/path"].text
|
360
|
+
end
|
361
|
+
|
305
362
|
def lookup_volume_path_by_name(volume_name)
|
306
363
|
volume = @pool.lookup_volume_by_name(volume_name)
|
307
364
|
volume.path
|
308
365
|
end
|
309
366
|
|
367
|
+
def list_all_network_ips
|
368
|
+
interfaces = read_network_interfaces
|
369
|
+
ips = []
|
370
|
+
interfaces.each do |interface|
|
371
|
+
next if interface.type == :user
|
372
|
+
ips << list_network_ips(interface.name)
|
373
|
+
end
|
374
|
+
ips
|
375
|
+
end
|
376
|
+
|
377
|
+
def list_default_network_ips
|
378
|
+
list_network_ips('vagrant')
|
379
|
+
end
|
380
|
+
|
381
|
+
def list_network_ips(network_name)
|
382
|
+
begin
|
383
|
+
network = @conn.lookup_network_by_name(network_name)
|
384
|
+
network_definition = Util::NetworkDefinition.new(network_name, network.xml_desc)
|
385
|
+
ips = []
|
386
|
+
if network_definition
|
387
|
+
ips = network_definition.hosts.map {|host| host[:ip]}
|
388
|
+
end
|
389
|
+
ips
|
390
|
+
rescue Libvirt::RetrieveError
|
391
|
+
@logger.info("error when getting network xml")
|
392
|
+
[]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
310
396
|
# Returns a list of network interfaces of the VM.
|
311
397
|
#
|
312
398
|
# @return [Hash]
|
@@ -333,6 +419,22 @@ module VagrantPlugins
|
|
333
419
|
end
|
334
420
|
end
|
335
421
|
|
422
|
+
# Returns a hostname of the guest
|
423
|
+
# introduced from ruby-libvirt 0.5.0
|
424
|
+
#
|
425
|
+
# @return [String]
|
426
|
+
def hostname?
|
427
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
428
|
+
domain.hostname
|
429
|
+
end
|
430
|
+
|
431
|
+
# reset the guest
|
432
|
+
# introduced from ruby-libvirt 0.5.0
|
433
|
+
def reset
|
434
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
435
|
+
domain.reset
|
436
|
+
end
|
437
|
+
|
336
438
|
def read_state
|
337
439
|
domain = @conn.lookup_domain_by_uuid(@uuid)
|
338
440
|
state, reason = domain.state
|
@@ -369,6 +471,7 @@ module VagrantPlugins
|
|
369
471
|
|
370
472
|
def set_mac_address(mac)
|
371
473
|
update_domain_xml(:mac => mac)
|
474
|
+
@logger.debug("set mac: #{mac}")
|
372
475
|
end
|
373
476
|
|
374
477
|
def set_gui(vnc_port, vnc_autoport, vnc_password)
|
@@ -384,6 +487,14 @@ module VagrantPlugins
|
|
384
487
|
update_domain_xml(:disk_bus => disk_bus)
|
385
488
|
end
|
386
489
|
|
490
|
+
def share_folders(folders)
|
491
|
+
update_domain_xml(:p9 => folders)
|
492
|
+
end
|
493
|
+
|
494
|
+
def clear_shared_folders
|
495
|
+
#stub
|
496
|
+
end
|
497
|
+
|
387
498
|
def update_domain_xml(options)
|
388
499
|
domain = @conn.lookup_domain_by_uuid(@uuid)
|
389
500
|
# Use DOMAIN_XML_SECURE to dump ALL options (including VNC password)
|
@@ -396,6 +507,18 @@ module VagrantPlugins
|
|
396
507
|
@conn.define_domain_xml(xml)
|
397
508
|
end
|
398
509
|
|
510
|
+
def add_nic(nic)
|
511
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
512
|
+
# Use DOMAIN_XML_SECURE to dump ALL options (including VNC password)
|
513
|
+
original_xml = domain.xml_desc(Libvirt::Domain::DOMAIN_XML_SECURE)
|
514
|
+
definition = Util::VmDefinition.new(original_xml)
|
515
|
+
definition.add_nic(nic)
|
516
|
+
domain.undefine
|
517
|
+
xml = definition.as_xml
|
518
|
+
@logger.debug("add nic\nFrom #{original_xml} \nTo: #{xml}")
|
519
|
+
@conn.define_domain_xml(xml)
|
520
|
+
end
|
521
|
+
|
399
522
|
# Starts the virtual machine.
|
400
523
|
def start
|
401
524
|
domain = @conn.lookup_domain_by_uuid(@uuid)
|
@@ -409,6 +532,20 @@ module VagrantPlugins
|
|
409
532
|
domain.managed_save
|
410
533
|
end
|
411
534
|
|
535
|
+
# Suspend for duration
|
536
|
+
# introduced from ruby-libvirt 0.5.0
|
537
|
+
def suspend_for_duration(target, duration)
|
538
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
539
|
+
domain.pmsuspend_for_duration(target, duration)
|
540
|
+
end
|
541
|
+
|
542
|
+
# Wakeup the virtual machine
|
543
|
+
# introduced from ruby-libvirt 0.5.0
|
544
|
+
def wakeup
|
545
|
+
domain = @conn.lookup_domain_by_uuid(@uuid)
|
546
|
+
domain.pmwakeup
|
547
|
+
end
|
548
|
+
|
412
549
|
def can_save?
|
413
550
|
domain = @conn.lookup_domain_by_uuid(@uuid)
|
414
551
|
definition = Util::VmDefinition.new(domain.xml_desc)
|
@@ -446,7 +583,36 @@ module VagrantPlugins
|
|
446
583
|
end
|
447
584
|
end
|
448
585
|
|
449
|
-
#
|
586
|
+
# Executes a command and returns the raw result object.
|
587
|
+
def raw(*command, &block)
|
588
|
+
int_callback = lambda do
|
589
|
+
@interrupted = true
|
590
|
+
@logger.info("Interrupted.")
|
591
|
+
end
|
592
|
+
|
593
|
+
# Append in the options for subprocess
|
594
|
+
command << { :notify => [:stdout, :stderr] }
|
595
|
+
|
596
|
+
Vagrant::Util::Busy.busy(int_callback) do
|
597
|
+
Vagrant::Util::Subprocess.execute(@virsh_path, *command, &block)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
def execute_command(command)
|
602
|
+
raw(*command)
|
603
|
+
end
|
604
|
+
|
605
|
+
# Verifies that the connection is alive
|
606
|
+
# introduced from ruby-libvirt 0.5.0
|
607
|
+
#
|
608
|
+
# This will raise a VagrantError if things are not ready.
|
609
|
+
def alive!
|
610
|
+
unless @conn.alive?
|
611
|
+
raise Vagrant::Errors::KvmNoConnection
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
# Verifies that the driver is ready and the connection is open
|
450
616
|
#
|
451
617
|
# This will raise a VagrantError if things are not ready.
|
452
618
|
def verify!
|
@@ -470,41 +636,41 @@ module VagrantPlugins
|
|
470
636
|
# Checks which Linux OS variants
|
471
637
|
#
|
472
638
|
# host_redhat?
|
639
|
+
# host_ubuntu?
|
473
640
|
# host_debian?
|
474
641
|
# host_gentoo?
|
475
642
|
# host_arch?
|
476
643
|
# @return [Boolean]
|
477
644
|
def host_redhat?
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
return true if contents =~ /^Korora/ # Korora
|
645
|
+
# Check also Korora, CentOS, Fedora,
|
646
|
+
# Oracle Linux < 5.3 and
|
647
|
+
# Red Hat Enterprise Linux and Oracle Linux >= 5.3
|
648
|
+
return true if check_os_release?("/etc/redhat-release",
|
649
|
+
["CentOS","Fedora","Korora","Enterprise Linux Enterprise Linux","Red Hat Enterprise Linux"])
|
650
|
+
false
|
651
|
+
end
|
486
652
|
|
487
|
-
|
488
|
-
|
653
|
+
def host_suse?
|
654
|
+
check_os_release?("/etc/SuSE-release")
|
655
|
+
end
|
489
656
|
|
490
|
-
|
491
|
-
|
492
|
-
|
657
|
+
def host_ubuntu?
|
658
|
+
if rel = check_lsb_release?
|
659
|
+
return true if rel == "Ubuntu"
|
493
660
|
end
|
494
|
-
|
495
661
|
false
|
496
662
|
end
|
497
663
|
|
498
664
|
def host_debian?
|
499
|
-
|
665
|
+
check_os_release?("/etc/debian_version")
|
500
666
|
end
|
501
667
|
|
502
668
|
def host_gentoo?
|
503
|
-
|
669
|
+
check_os_release?("/etc/gentoo-release")
|
504
670
|
end
|
505
671
|
|
506
672
|
def host_arch?
|
507
|
-
|
673
|
+
check_os_release?("/etc/arch-release")
|
508
674
|
end
|
509
675
|
|
510
676
|
private
|
@@ -520,6 +686,30 @@ module VagrantPlugins
|
|
520
686
|
"#{maj}.#{min}.#{rel}"
|
521
687
|
end
|
522
688
|
|
689
|
+
# Check contents of release file
|
690
|
+
#
|
691
|
+
# filename: release file path
|
692
|
+
# criteria: ["CentOS","Fedora",...]
|
693
|
+
def check_os_release?(filename, criteria=nil)
|
694
|
+
return File.exists?(filename) unless criteria
|
695
|
+
|
696
|
+
release_file = Pathname.new(filename)
|
697
|
+
if release_file.exist?
|
698
|
+
release_file.open("r:ISO-8859-1:UTF-8") do |f|
|
699
|
+
contents = f.gets
|
700
|
+
criteria.each do |c|
|
701
|
+
return true if contents =~ /^#{c}/
|
702
|
+
end
|
703
|
+
end
|
704
|
+
end
|
705
|
+
false
|
706
|
+
end
|
707
|
+
|
708
|
+
def check_lsb_release?
|
709
|
+
return false unless File.exists?("/usr/bin/lsb_release")
|
710
|
+
IO.popen('/usr/bin/lsb_release -i') { |o| o.read.chomp.split("\t") }[1]
|
711
|
+
end
|
712
|
+
|
523
713
|
def load_kvm_module!
|
524
714
|
@logger.info("Check KVM kernel modules")
|
525
715
|
kvm = File.readlines('/proc/modules').any? { |line| line =~ /kvm_(intel|amd)/ }
|
@@ -542,6 +732,7 @@ module VagrantPlugins
|
|
542
732
|
# Open a connection to the qemu driver
|
543
733
|
begin
|
544
734
|
@conn = Libvirt::open('qemu:///system')
|
735
|
+
@conn.capabilities
|
545
736
|
rescue Libvirt::Error => e
|
546
737
|
if e.libvirt_code == 5
|
547
738
|
# can't connect to hypervisor
|
@@ -551,24 +742,19 @@ module VagrantPlugins
|
|
551
742
|
end
|
552
743
|
end
|
553
744
|
|
554
|
-
|
745
|
+
hv_type = @conn.type.to_s
|
746
|
+
unless hv_type == "QEMU"
|
747
|
+
raise Errors::KvmUnsupportedHypervisor,
|
748
|
+
:actual => hv_type, :required => "QEMU"
|
749
|
+
end
|
750
|
+
|
751
|
+
version = read_version
|
555
752
|
if @conn.version.to_i < 1001000
|
556
753
|
raise Errors::KvmInvalidVersion,
|
557
|
-
:actual =>
|
754
|
+
:actual => version, :required => ">= 1.1.0"
|
558
755
|
end
|
559
756
|
end
|
560
757
|
|
561
|
-
def init_storage_pool!
|
562
|
-
# Get storage pool if it exists
|
563
|
-
begin
|
564
|
-
@pool = @conn.lookup_storage_pool_by_name(@pool_name)
|
565
|
-
# this is happen when user has already used vagrant-kvm 0.1.5 and after
|
566
|
-
# check neccesity of migration
|
567
|
-
check_migrate_box_storage_pool
|
568
|
-
rescue Libvirt::RetrieveError
|
569
|
-
# storage pool doesn't exist yet
|
570
|
-
end
|
571
|
-
end
|
572
758
|
end
|
573
759
|
end
|
574
760
|
end
|