vagrant-libvirt 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a7de8bcfdcab60b3237c7d64fd047fa9b43bbf8
4
+ data.tar.gz: f98b1b521b2d6665be337341791ae260244d29eb
5
+ SHA512:
6
+ metadata.gz: 6d33e5ae966f1758ec327b73a9d3527cfa0b6c3ab461630beb4e13bc391c5f291ab04b48884bc0d568e2376ee3fda1361bce6efab0d3d5513b987f08f7b75513
7
+ data.tar.gz: 83408a1dcb5c55fd745e204b7d23f78cf1ec9d6e6eb5beb8a27f31cbff4154a916bd9068b7e80dade9318f97b504a77671171486ce954e65b9af73474487e151
data/Gemfile CHANGED
@@ -4,11 +4,9 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :development do
7
- gem 'rake'
8
- gem 'rspec', '~> 2.13.0'
9
- gem 'rspec-fire', require: 'rspec/fire'
10
- gem 'rspec-spies', require: false
11
- gem 'coveralls', require: false
12
- gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git'
7
+ # We depend on Vagrant for development, but we don't add it as a
8
+ # gem dependency because we expect to be installed within the
9
+ # Vagrant environment itself using `vagrant plugin`.
10
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
13
11
  end
14
12
 
data/README.md CHANGED
@@ -99,14 +99,19 @@ This provider exposes quite a few provider-specific configuration options:
99
99
  * `password` - Password to access Libvirt.
100
100
  * `id_ssh_key_file` - The id ssh key file name to access Libvirt (eg: id_dsa or id_rsa or ... in the user .ssh directory)
101
101
  * `storage_pool_name` - Libvirt storage pool name, where box image and instance snapshots will be stored.
102
- * `default_network` - Libvirt default network name. If not specified default network name is 'default'.
103
102
 
104
103
  ### Domain Specific Options
105
104
 
105
+ * `disk_bus` - The type of disk device to emulate. Defaults to virtio if not set. Possible values are documented in libvirt's [description for _target_](http://libvirt.org/formatdomain.html#elementsDisks).
106
106
  * `memory` - Amount of memory in MBytes. Defaults to 512 if not set.
107
107
  * `cpus` - Number of virtual cpus. Defaults to 1 if not set.
108
108
  * `nested` - [Enable nested virtualization](https://github.com/torvalds/linux/blob/master/Documentation/virtual/kvm/nested-vmx.txt). Default is false.
109
+ * `cpu_mode` - What cpu mode to use for nested virtualization. Defaults to 'host-model' if not set.
109
110
  * `volume_cache` - Controls the cache mechanism. Possible values are "default", "none", "writethrough", "writeback", "directsync" and "unsafe". [See driver->cache in libvirt documentation](http://libvirt.org/formatdomain.html#elementsDisks).
111
+ * `kernel` - To launch the guest with a kernel residing on host filesystems (Equivalent to qemu `-kernel`)
112
+ * `initrd` - To specify the initramfs/initrd to use for the guest (Equivalent to qemu `-initrd`)
113
+ * `cmd_line` - Arguments passed on to the guest kernel initramfs or initrd to use (Equivalent to qemu `-append`)
114
+
110
115
 
111
116
  Specific domain settings can be set for each domain separately in multi-VM
112
117
  environment. Example below shows a part of Vagrantfile, where specific options
@@ -120,7 +125,7 @@ Vagrant.configure("2") do |config|
120
125
  domain.memory = 2048
121
126
  domain.cpus = 2
122
127
  domain.nested = true
123
- domain.volume_cache = 'none'
128
+ domain.volume_cache = 'none'
124
129
  end
125
130
  end
126
131
 
@@ -229,15 +234,24 @@ starts with 'libvirt__' string. Here is a list of those options:
229
234
  Default mode is 'bridge'.
230
235
  * `:mac` - MAC address for the interface.
231
236
 
232
- ## Obtaining Domain IP Address
237
+ ### Management Network
238
+
239
+ Vagrant-libvirt uses a private network to perform some management operations
240
+ on VMs. All VMs will have an interface connected to this network and
241
+ an IP address dynamically assigned by libvirt. This is in addition to any
242
+ networks you configure. The name and address used by this network are
243
+ configurable at the provider level.
244
+
245
+ * `management_network_name` - Name of libvirt network to which all VMs will be connected. If not specified the default is 'vagrant-libvirt'.
246
+ * `management_network_address` - Address of network to which all VMs will be connected. Must include the address and subnet mask. If not specified the default is '192.168.121.0/24'.
233
247
 
234
- Libvirt doesn't provide standard way how to find out an IP address of running
235
- domain. But we know, what is MAC address of virtual machine. Libvirt is closely
236
- connected with dnsmasq server, which acts also as a DHCP server. Dnsmasq server
237
- makes lease information public in `/var/lib/libvirt/dnsmasq` directory, or in
238
- `/var/lib/misc/dnsmasq.leases` file on some systems. This is the place, where
239
- information like which MAC address has which IP address resides and it's parsed
240
- by vagrant-libvirt plugin.
248
+ You may wonder how vagrant-libvirt knows the IP address a VM received.
249
+ Libvirt doesn't provide a standard way to find out the IP address of a running
250
+ domain. But we do know the MAC address of the virtual machine's interface on
251
+ the management network. Libvirt is closely connected with dnsmasq, which acts as
252
+ a DHCP server. dnsmasq writes lease information in the `/var/lib/libvirt/dnsmasq`
253
+ directory. Vagrant-libvirt looks for the MAC address in this file and extracts
254
+ the corresponding IP address.
241
255
 
242
256
  ## SSH Access To VM
243
257
 
data/Rakefile CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  #require 'rubygems'
4
4
  #require 'bundler/setup'
5
- Dir['./tasks/**/*.rake'].each { |f| load f }
6
5
  require 'bundler/gem_tasks'
7
6
  Bundler::GemHelper.install_tasks
8
7
  task default: [:deftask]
@@ -52,6 +52,9 @@ Vagrant.configure("2") do |config|
52
52
  # Libvirt storage pool name, where box image and instance snapshots will
53
53
  # be stored.
54
54
  libvirt.storage_pool_name = "default"
55
+
56
+ # Set a prefix for the machines that's different than the project dir name.
57
+ #libvirt.default_prefix = ''
55
58
  end
56
59
  end
57
60
 
@@ -25,7 +25,13 @@ module VagrantPlugins
25
25
  b2.use CreateNetworks
26
26
  b2.use CreateNetworkInterfaces
27
27
 
28
- b2.use NFS
28
+ if Vagrant::VERSION < "1.4.0"
29
+ b2.use NFS
30
+ else
31
+ b2.use SyncedFolderCleanup
32
+ b2.use SyncedFolders
33
+ end
34
+
29
35
  b2.use PrepareNFSSettings
30
36
  b2.use ShareFolders
31
37
  b2.use SetHostname
@@ -51,19 +57,32 @@ module VagrantPlugins
51
57
  next if env[:result]
52
58
 
53
59
  b2.use Call, IsSuspended do |env2, b3|
60
+ # if vm is suspended resume it then exit
54
61
  if env2[:result]
55
62
  b3.use ResumeDomain
56
63
  next
57
64
  end
58
65
 
59
- # VM is not running or suspended. Start it.. Machine should gain
60
- # IP address when comming up, so wait for dhcp lease and store IP
61
- # into machines data_dir.
62
- b3.use NFS
66
+ # VM is not running or suspended.
67
+
68
+ # Ensure networks are created and active
69
+ b3.use CreateNetworks
70
+
71
+ # Handle shared folders
72
+ if Vagrant::VERSION < "1.4.0"
73
+ b3.use NFS
74
+ else
75
+ b3.use SyncedFolderCleanup
76
+ b3.use SyncedFolders
77
+ end
63
78
  b3.use PrepareNFSSettings
64
79
  b3.use ShareFolders
65
80
 
81
+ # Start it..
66
82
  b3.use StartDomain
83
+
84
+ # Machine should gain IP address when comming up,
85
+ # so wait for dhcp lease and store IP into machines data_dir.
67
86
  b3.use WaitTillUp
68
87
  end
69
88
  end
@@ -302,6 +321,10 @@ module VagrantPlugins
302
321
  autoload :WaitTillUp, action_root.join('wait_till_up')
303
322
  autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
304
323
  autoload :HandleBoxUrl, 'vagrant/action/builtin/handle_box_url'
324
+ unless Vagrant::VERSION < "1.4.0"
325
+ autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
326
+ autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
327
+ end
305
328
  end
306
329
  end
307
330
  end
@@ -67,13 +67,9 @@ module VagrantPlugins
67
67
  conn_attr[:libvirt_password] = config.password if config.password
68
68
 
69
69
  # Setup command for retrieving IP address for newly created machine
70
- # with some MAC address. Get it from dnsmasq leases table - either
71
- # /var/lib/libvirt/dnsmasq/*.leases files, or
72
- # /var/lib/misc/dnsmasq.leases if available.
73
- ip_command = "LEASES='/var/lib/libvirt/dnsmasq/*.leases'; "
74
- ip_command << "[ -f /var/lib/misc/dnsmasq.leases ] && "
75
- ip_command << "LEASES='/var/lib/misc/dnsmasq.leases'; "
76
- ip_command << "grep $mac $LEASES | awk '{ print $3 }'"
70
+ # with some MAC address. Get it from dnsmasq leases table
71
+ ip_command = %q[ LEASES=$(find /var/lib/libvirt/dnsmasq/ /var/lib/misc/ -name '*leases'); ]
72
+ ip_command << %q[ [ -n "$LEASES" ] && grep $mac $LEASES | awk '{ print $3 }' ]
77
73
  conn_attr[:libvirt_ip_command] = ip_command
78
74
 
79
75
  @logger.info("Connecting to Libvirt (#{uri}) ...")
@@ -19,9 +19,14 @@ module VagrantPlugins
19
19
  # Gather some info about domain
20
20
  @name = env[:domain_name]
21
21
  @cpus = config.cpus
22
+ @cpu_mode = config.cpu_mode
23
+ @disk_bus = config.disk_bus
22
24
  @nested = config.nested
23
25
  @memory_size = config.memory*1024
24
26
  @domain_volume_cache = config.volume_cache
27
+ @kernel = config.kernel
28
+ @cmd_line = config.cmd_line
29
+ @initrd = config.initrd
25
30
 
26
31
  # TODO get type from driver config option
27
32
  @domain_type = 'kvm'
@@ -44,6 +49,9 @@ module VagrantPlugins
44
49
  env[:ui].info(" -- Storage pool: #{env[:machine].provider_config.storage_pool_name}")
45
50
  env[:ui].info(" -- Image: #{@domain_volume_path}")
46
51
  env[:ui].info(" -- Volume Cache: #{@domain_volume_cache}")
52
+ env[:ui].info(" -- Kernel: #{@kernel}")
53
+ env[:ui].info(" -- Initrd: #{@initrd}")
54
+ env[:ui].info(" -- Command line : #{@cmd_line}")
47
55
 
48
56
  # Create libvirt domain.
49
57
  # Is there a way to tell fog to create new domain with already
@@ -16,7 +16,7 @@ module VagrantPlugins
16
16
 
17
17
  def initialize(app, env)
18
18
  @logger = Log4r::Logger.new('vagrant_libvirt::action::create_network_interfaces')
19
- @default_network = env[:machine].provider_config.default_network;
19
+ @management_network_name = env[:machine].provider_config.management_network_name
20
20
  @app = app
21
21
  end
22
22
 
@@ -37,6 +37,7 @@ module VagrantPlugins
37
37
 
38
38
  # Assign interfaces to slots.
39
39
  env[:machine].config.vm.networks.each do |type, options|
40
+ @logger.debug "In config found network type #{type} options #{options}"
40
41
 
41
42
  # Get options for this interface. Options can be specified in
42
43
  # Vagrantfile in short format (:ip => ...), or provider format
@@ -51,8 +52,10 @@ module VagrantPlugins
51
52
  end
52
53
 
53
54
  free_slot = options[:adapter].to_i
55
+ @logger.debug "Using specified adapter slot #{free_slot}"
54
56
  else
55
57
  free_slot = find_empty(adapters)
58
+ @logger.debug "Adapter not specified so found slot #{free_slot}"
56
59
  raise Errors::InterfaceSlotNotAvailable if free_slot == nil
57
60
  end
58
61
 
@@ -104,6 +107,7 @@ module VagrantPlugins
104
107
  # it has to be available during provisioning - ifdown command is
105
108
  # not acceptable here.
106
109
  next if slot_number == 0
110
+ @logger.debug "Configuring interface slot_number #{slot_number} options #{options}"
107
111
 
108
112
  network = {
109
113
  :interface => slot_number,
@@ -139,7 +143,10 @@ module VagrantPlugins
139
143
 
140
144
  # Return network name according to interface options.
141
145
  def interface_network(libvirt_client, options)
142
- return options[:network_name] if options[:network_name]
146
+ if options[:network_name]
147
+ @logger.debug "Found network by name"
148
+ return options[:network_name]
149
+ end
143
150
 
144
151
  # Get list of all (active and inactive) libvirt networks.
145
152
  available_networks = libvirt_networks(libvirt_client)
@@ -147,12 +154,20 @@ module VagrantPlugins
147
154
  if options[:ip]
148
155
  address = network_address(options[:ip], options[:netmask])
149
156
  available_networks.each do |network|
150
- return network[:name] if address == network[:network_address]
157
+ if address == network[:network_address]
158
+ @logger.debug "Found network by ip"
159
+ return network[:name]
160
+ end
151
161
  end
152
162
  end
153
163
 
154
- # TODO Network default can be missing or named different.
155
- return @default_network;
164
+ # the management network always gets attached to slot 0
165
+ # because the first network is of type forwarded_port.
166
+ # this is confusing.
167
+ # TODO only iterate over networks of type private_network
168
+ # and prepend the management network to that list
169
+ @logger.debug "Did not find network so using default of #{@management_network_name}"
170
+ @management_network_name
156
171
  end
157
172
  end
158
173
  end
@@ -2,6 +2,7 @@ require 'log4r'
2
2
  require 'vagrant/util/network_ip'
3
3
  require 'vagrant/util/scoped_hash_override'
4
4
  require 'ipaddr'
5
+ require 'thread'
5
6
 
6
7
  module VagrantPlugins
7
8
  module ProviderLibvirt
@@ -13,6 +14,8 @@ module VagrantPlugins
13
14
  include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
14
15
  include VagrantPlugins::ProviderLibvirt::Util::LibvirtUtil
15
16
 
17
+ @@lock = Mutex.new
18
+
16
19
  def initialize(app, env)
17
20
  mess = 'vagrant_libvirt::action::create_networks'
18
21
  @logger = Log4r::Logger.new(mess)
@@ -25,60 +28,98 @@ module VagrantPlugins
25
28
 
26
29
  def call(env)
27
30
 
28
- # Iterate over networks requested from config. If some network is not
29
- # available, create it if possible. Otherwise raise an error.
30
- env[:machine].config.vm.networks.each do |type, options|
31
+ management_network_name = env[:machine].provider_config.management_network_name
32
+ management_network_address = env[:machine].provider_config.management_network_address
33
+ @logger.info "Using #{management_network_name} at #{management_network_address} as the management network"
31
34
 
32
- # Get a list of all (active and inactive) libvirt networks. This
33
- # list is used throughout this class and should be easier to
34
- # process than libvirt API calls.
35
- @available_networks = libvirt_networks(env[:libvirt_compute].client)
35
+ begin
36
+ management_network_ip = IPAddr.new(management_network_address)
37
+ rescue ArgumentError
38
+ raise Errors::ManagementNetworkError,
39
+ error_message: "#{management_network_address} is not a valid IP address"
40
+ end
36
41
 
37
- # Now, we support private networks only. There are two other types
38
- # public network and port forwarding, but there are problems with
39
- # creating them via libvirt API, so this provider doesn't implement
40
- # them.
41
- next if type != :private_network
42
+ # capture address into $1 and mask into $2
43
+ management_network_ip.inspect =~ /IPv4:(.*)\/(.*)>/
42
44
 
43
- # Get options for this interface network. Options can be specified
44
- # in Vagrantfile in short format (:ip => ...), or provider format
45
- # (:libvirt__network_name => ...).
46
- @options = scoped_hash_override(options, :libvirt)
47
- @options = {
45
+ if $2 == '255.255.255.255'
46
+ raise Errors::ManagementNetworkError,
47
+ error_message: "#{management_network_address} does not include both an address and subnet mask"
48
+ end
49
+
50
+ management_network_options = {
51
+ network_name: management_network_name,
52
+ ip: $1,
53
+ netmask: $2,
54
+ dhcp_enabled: true,
55
+ forward_mode: 'nat',
56
+ }
57
+
58
+ # add management network to list of networks to check
59
+ networks = [ management_network_options ]
60
+
61
+ env[:machine].config.vm.networks.each do |type, original_options|
62
+ # There are two other types public network and port forwarding,
63
+ # but there are problems with creating them via libvirt API,
64
+ # so this provider doesn't implement them.
65
+ next if type != :private_network
66
+ # Options can be specified in Vagrantfile in short format (:ip => ...),
67
+ # or provider format # (:libvirt__network_name => ...).
68
+ # https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/scoped_hash_override.rb
69
+ options = scoped_hash_override(original_options, :libvirt)
70
+ # use default values if not already set
71
+ options = {
48
72
  netmask: '255.255.255.0',
49
73
  dhcp_enabled: true,
50
74
  forward_mode: 'nat',
51
- }.merge(@options)
52
-
53
- # Prepare a hash describing network for this specific interface.
54
- @interface_network = {
55
- name: nil,
56
- ip_address: nil,
57
- netmask: @options[:netmask],
58
- network_address: nil,
59
- bridge_name: nil,
60
- created: false,
61
- active: false,
62
- autostart: false,
63
- libvirt_network: nil,
64
- }
65
-
66
- if @options[:ip]
67
- handle_ip_option(env)
68
- elsif @options[:network_name]
69
- handle_network_name_option
70
- else
71
- # TODO: Should be smarter than just using fixed 'default' string.
72
- @interface_network = lookup_network_by_name('default')
73
- if !@interface_network
74
- raise Errors::NetworkNotAvailableError,
75
- network_name: 'default'
75
+ }.merge(options)
76
+ # add to list of networks to check
77
+ networks.push(options)
78
+ end
79
+
80
+ # only one vm at a time should try to set up networks
81
+ # otherwise they'll have inconsitent views of current state
82
+ # and conduct redundant operations that cause errors
83
+ @@lock.synchronize do
84
+ # Iterate over networks If some network is not
85
+ # available, create it if possible. Otherwise raise an error.
86
+ networks.each do |options|
87
+ @logger.debug "Searching for network with options #{options}"
88
+
89
+ # should fix other methods so this doesn't have to be instance var
90
+ @options = options
91
+
92
+ # Get a list of all (active and inactive) libvirt networks. This
93
+ # list is used throughout this class and should be easier to
94
+ # process than libvirt API calls.
95
+ @available_networks = libvirt_networks(env[:libvirt_compute].client)
96
+
97
+ # Prepare a hash describing network for this specific interface.
98
+ @interface_network = {
99
+ name: nil,
100
+ ip_address: nil,
101
+ netmask: @options[:netmask],
102
+ network_address: nil,
103
+ bridge_name: nil,
104
+ created: false,
105
+ active: false,
106
+ autostart: false,
107
+ libvirt_network: nil,
108
+ }
109
+
110
+ if @options[:ip]
111
+ handle_ip_option(env)
112
+ # in vagrant 1.2.3 and later it is not possible to take this branch
113
+ # because cannot have name without ip
114
+ # https://github.com/mitchellh/vagrant/commit/cf2f6da4dbcb4f57c9cdb3b94dcd0bba62c5f5fd
115
+ elsif @options[:network_name]
116
+ handle_network_name_option
76
117
  end
77
- end
78
118
 
79
- autostart_network if !@interface_network[:autostart]
80
- activate_network if !@interface_network[:active]
119
+ autostart_network if !@interface_network[:autostart]
120
+ activate_network if !@interface_network[:active]
81
121
  end
122
+ end
82
123
 
83
124
  @app.call(env)
84
125
  end
@@ -87,6 +128,7 @@ module VagrantPlugins
87
128
 
88
129
  # Return hash of network for specified name, or nil if not found.
89
130
  def lookup_network_by_name(network_name)
131
+ @logger.debug "looking up network named #{network_name}"
90
132
  @available_networks.each do |network|
91
133
  return network if network[:name] == network_name
92
134
  end
@@ -95,12 +137,25 @@ module VagrantPlugins
95
137
 
96
138
  # Return hash of network for specified bridge, or nil if not found.
97
139
  def lookup_bridge_by_name(bridge_name)
140
+ @logger.debug "looking up bridge named #{bridge_name}"
98
141
  @available_networks.each do |network|
99
142
  return network if network[:bridge_name] == bridge_name
100
143
  end
101
144
  nil
102
145
  end
103
146
 
147
+ # Throw an error if dhcp setting for an existing network does not
148
+ # match what was configured in the vagrantfile
149
+ # since we always enable dhcp for the management network
150
+ # this ensures we wont start a vm vagrant cant reach
151
+ def verify_dhcp
152
+ unless @options[:dhcp_enabled] == @interface_network[:dhcp_enabled]
153
+ raise Errors::DHCPMismatch,
154
+ network_name: @interface_network[:name],
155
+ requested: @options[:dhcp_enabled] ? 'enabled' : 'disabled'
156
+ end
157
+ end
158
+
104
159
  # Handle only situations, when ip is specified. Variables @options and
105
160
  # @available_networks should be filled before calling this function.
106
161
  def handle_ip_option(env)
@@ -120,11 +175,18 @@ module VagrantPlugins
120
175
  if available_network[:network_address] == \
121
176
  @interface_network[:network_address]
122
177
  @interface_network = available_network
178
+ @logger.debug "found existing network by ip, values are"
179
+ @logger.debug @interface_network
123
180
  break
124
181
  end
125
182
  end
126
183
 
184
+ if @interface_network[:created]
185
+ verify_dhcp
186
+ end
187
+
127
188
  if @options[:network_name]
189
+ @logger.debug "Checking that network name does not clash with ip"
128
190
  if @interface_network[:created]
129
191
  # Just check for mismatch error here - if name and ip from
130
192
  # config match together.
@@ -156,6 +218,7 @@ module VagrantPlugins
156
218
  # Is name for new network set? If not, generate a unique one.
157
219
  count = 0
158
220
  while @interface_network[:name].nil?
221
+ @logger.debug "generating name for network"
159
222
 
160
223
  # Generate a network name.
161
224
  network_name = env[:root_path].basename.to_s.dup
@@ -171,6 +234,7 @@ module VagrantPlugins
171
234
  # Generate a unique name for network bridge.
172
235
  count = 0
173
236
  while @interface_network[:bridge_name].nil?
237
+ @logger.debug "generating name for bridge"
174
238
  bridge_name = 'virbr'
175
239
  bridge_name << count.to_s
176
240
  count += 1
@@ -195,6 +259,8 @@ module VagrantPlugins
195
259
  if !@interface_network
196
260
  raise Errors::NetworkNotAvailableError,
197
261
  network_name: @options[:network_name]
262
+ else
263
+ verify_dhcp
198
264
  end
199
265
  end
200
266
 
@@ -234,6 +300,7 @@ module VagrantPlugins
234
300
  begin
235
301
  @interface_network[:libvirt_network] = \
236
302
  @libvirt_client.define_network_xml(to_xml('private_network'))
303
+ @logger.debug "created network"
237
304
  rescue => e
238
305
  raise Errors::CreateNetworkError, error_message: e.message
239
306
  end
@@ -18,7 +18,7 @@ module VagrantPlugins
18
18
  # data directory, created_networks file holds UUIDs of each network.
19
19
  created_networks_file = env[:machine].data_dir + 'created_networks'
20
20
 
21
- @logger.info 'Attepmt destroy network'
21
+ @logger.info 'Checking if any networks were created'
22
22
  # If created_networks file doesn't exist, there are no networks we
23
23
  # need to remove.
24
24
  unless File.exist?(created_networks_file)
@@ -26,39 +26,45 @@ module VagrantPlugins
26
26
  return @app.call(env)
27
27
  end
28
28
 
29
- @logger.info 'file with network exists'
29
+ @logger.info 'File with created networks exists'
30
30
 
31
31
  # Iterate over each created network UUID and try to remove it.
32
32
  created_networks = []
33
33
  file = File.open(created_networks_file, 'r')
34
34
  file.readlines.each do |network_uuid|
35
- @logger.info network_uuid
35
+ @logger.info "Checking for #{network_uuid}"
36
+ # lookup_network_by_uuid throws same exception
37
+ # if there is an error or if the network just doesn't exist
36
38
  begin
37
39
  libvirt_network = env[:libvirt_compute].client.lookup_network_by_uuid(
38
40
  network_uuid)
39
- rescue
40
- raise network_uuid
41
- next
41
+ rescue Libvirt::RetrieveError => e
42
+ # this network is already destroyed, so move on
43
+ if e.message =~ /Network not found/
44
+ @logger.info "It is already undefined"
45
+ next
46
+ # some other error occured, so raise it again
47
+ else
48
+ raise e
49
+ end
42
50
  end
43
51
 
44
- # Maybe network doesn't exist anymore.
45
- next unless libvirt_network
46
-
47
52
  # Skip removing if network has still active connections.
48
53
  xml = Nokogiri::XML(libvirt_network.xml_desc)
49
54
  connections = xml.xpath('/network/@connections').first
50
- @logger.info connections
51
55
  if connections != nil
56
+ @logger.info "Still has connections so will not undefine"
52
57
  created_networks << network_uuid
53
58
  next
54
59
  end
55
60
 
56
- # Shutdown network first.
57
- libvirt_network.destroy
58
61
 
62
+ # Shutdown network first.
59
63
  # Undefine network.
60
64
  begin
65
+ libvirt_network.destroy
61
66
  libvirt_network.undefine
67
+ @logger.info "Undefined it"
62
68
  rescue => e
63
69
  raise Error::DestroyNetworkError,
64
70
  network_name: libvirt_network.name,
@@ -68,13 +74,16 @@ module VagrantPlugins
68
74
  file.close
69
75
 
70
76
  # Update status of created networks after removing some/all of them.
77
+ # Not sure why we are doing this, something else seems to always delete the file
71
78
  if created_networks.length > 0
72
79
  File.open(created_networks_file, 'w') do |file|
80
+ @logger.info "Writing new created_networks file"
73
81
  created_networks.each do |network_uuid|
74
82
  file.puts network_uuid
75
83
  end
76
84
  end
77
85
  else
86
+ @logger.info "Deleting created_networks file"
78
87
  File.delete(created_networks_file)
79
88
  end
80
89
 
@@ -5,21 +5,31 @@ module VagrantPlugins
5
5
  # Setup name for domain and domain volumes.
6
6
  class SetNameOfDomain
7
7
  def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant_libvirt::action::set_name_of_domain")
8
9
  @app = app
9
10
  end
10
11
 
11
12
  def call(env)
12
13
  require 'securerandom'
13
- env[:domain_name] = env[:root_path].basename.to_s.dup
14
+ config = env[:machine].provider_config
15
+ if config.default_prefix.nil?
16
+ env[:domain_name] = env[:root_path].basename.to_s.dup
17
+ else
18
+ env[:domain_name] = config.default_prefix.to_s
19
+ end
14
20
  env[:domain_name].gsub!(/[^-a-z0-9_]/i, '')
15
21
  env[:domain_name] << '_'
16
22
  env[:domain_name] << env[:machine].name.to_s
17
-
23
+
24
+ @logger.info("Looking for domain #{env[:domain_name]} through list #{env[:libvirt_compute].servers.all}")
18
25
  # Check if the domain name is not already taken
19
26
  domain = ProviderLibvirt::Util::Collection.find_matching(
20
27
  env[:libvirt_compute].servers.all, env[:domain_name])
28
+
29
+ @logger.info("Looking for domain #{env[:domain_name]}")
30
+
21
31
  if domain != nil
22
- raise Vagrant::Errors::DomainNameExists,
32
+ raise ProviderLibvirt::Errors::DomainNameExists,
23
33
  :domain_name => env[:domain_name]
24
34
  end
25
35
 
@@ -1,4 +1,4 @@
1
- require "pathname"
1
+ require 'pathname'
2
2
 
3
3
  require "log4r"
4
4
 
@@ -27,7 +27,7 @@ module VagrantPlugins
27
27
  # avoid creating an additional directory with rsync
28
28
  hostpath = "#{hostpath}/" if hostpath !~ /\/$/
29
29
 
30
- env[:ui].info(I18n.t("vagrant_libvirt.rsync_folder",
30
+ env[:ui].info(I18n.t('vagrant_libvirt.rsync_folder',
31
31
  :hostpath => hostpath,
32
32
  :guestpath => guestpath))
33
33
 
@@ -38,9 +38,9 @@ module VagrantPlugins
38
38
 
39
39
  # Rsync over to the guest path using the SSH info
40
40
  command = [
41
- "rsync", "--del", "--verbose", "--archive", "-z",
42
- "--exclude", ".vagrant/",
43
- "-e", "ssh -p #{ssh_info[:port]} #{proxycommand} -o StrictHostKeyChecking=no -i '#{ssh_info[:private_key_path]}'",
41
+ 'rsync', '--del', '--verbose', '--archive', '-z',
42
+ '--exclude', '.vagrant/',
43
+ '-e', "ssh -p #{ssh_info[:port]} #{proxycommand} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
44
44
  hostpath,
45
45
  "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
46
46
 
@@ -53,6 +53,12 @@ module VagrantPlugins
53
53
  end
54
54
  end
55
55
  end
56
+ private
57
+
58
+ def ssh_key_options(ssh_info)
59
+ # Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
60
+ Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
61
+ end
56
62
  end
57
63
  end
58
64
  end
@@ -26,13 +26,22 @@ module VagrantPlugins
26
26
  attr_accessor :storage_pool_name
27
27
 
28
28
  # Libvirt default network
29
- attr_accessor :default_network
29
+ attr_accessor :management_network_name
30
+ attr_accessor :management_network_address
31
+
32
+ # Default host prefix (alternative to use project folder name)
33
+ attr_accessor :default_prefix
30
34
 
31
35
  # Domain specific settings used while creating new domain.
32
36
  attr_accessor :memory
33
37
  attr_accessor :cpus
38
+ attr_accessor :cpu_mode
39
+ attr_accessor :disk_bus
34
40
  attr_accessor :nested
35
41
  attr_accessor :volume_cache
42
+ attr_accessor :kernel
43
+ attr_accessor :cmd_line
44
+ attr_accessor :initrd
36
45
 
37
46
  def initialize
38
47
  @driver = UNSET_VALUE
@@ -42,13 +51,19 @@ module VagrantPlugins
42
51
  @password = UNSET_VALUE
43
52
  @id_ssh_key_file = UNSET_VALUE
44
53
  @storage_pool_name = UNSET_VALUE
45
- @default_network = UNSET_VALUE
54
+ @management_network_name = UNSET_VALUE
55
+ @management_network_address = UNSET_VALUE
46
56
 
47
57
  # Domain specific settings.
48
58
  @memory = UNSET_VALUE
49
59
  @cpus = UNSET_VALUE
60
+ @cpu_mode = UNSET_VALUE
61
+ @disk_bus = UNSET_VALUE
50
62
  @nested = UNSET_VALUE
51
63
  @volume_cache = UNSET_VALUE
64
+ @kernel = UNSET_VALUE
65
+ @initrd = UNSET_VALUE
66
+ @cmd_line = UNSET_VALUE
52
67
  end
53
68
 
54
69
  def finalize!
@@ -59,13 +74,19 @@ module VagrantPlugins
59
74
  @password = nil if @password == UNSET_VALUE
60
75
  @id_ssh_key_file = 'id_rsa' if @id_ssh_key_file == UNSET_VALUE
61
76
  @storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
62
- @default_network = 'default' if @default_network == UNSET_VALUE
77
+ @management_network_name = 'vagrant-libvirt' if @management_network_name == UNSET_VALUE
78
+ @management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
63
79
 
64
80
  # Domain specific settings.
65
81
  @memory = 512 if @memory == UNSET_VALUE
66
82
  @cpus = 1 if @cpus == UNSET_VALUE
83
+ @cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
84
+ @disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
67
85
  @nested = false if @nested == UNSET_VALUE
68
86
  @volume_cache = 'default' if @volume_cache == UNSET_VALUE
87
+ @kernel = nil if @kernel == UNSET_VALUE
88
+ @cmd_line = '' if @cmd_line == UNSET_VALUE
89
+ @initrd = '' if @initrd == UNSET_VALUE
69
90
  end
70
91
 
71
92
  def validate(machine)
@@ -68,16 +68,19 @@ module VagrantPlugins
68
68
  error_key(:fog_create_server_error)
69
69
  end
70
70
 
71
-
72
- # Other exceptions
73
- class InterfaceSlotNotAvailable < VagrantLibvirtError
74
- error_key(:interface_slot_not_available)
71
+ # Network exceptions
72
+ class ManagementNetworkError < VagrantLibvirtError
73
+ error_key(:management_network_error)
75
74
  end
76
75
 
77
76
  class NetworkNameAndAddressMismatch < VagrantLibvirtError
78
77
  error_key(:network_name_and_address_mismatch)
79
78
  end
80
79
 
80
+ class DHCPMismatch < VagrantLibvirtError
81
+ error_key(:dhcp_mismatch)
82
+ end
83
+
81
84
  class CreateNetworkError < VagrantLibvirtError
82
85
  error_key(:create_network_error)
83
86
  end
@@ -98,12 +101,17 @@ module VagrantPlugins
98
101
  error_key(:activate_network_error)
99
102
  end
100
103
 
104
+ # Other exceptions
105
+ class InterfaceSlotNotAvailable < VagrantLibvirtError
106
+ error_key(:interface_slot_not_available)
107
+ end
108
+
101
109
  class RsyncError < VagrantLibvirtError
102
110
  error_key(:rsync_error)
103
111
  end
104
112
 
105
113
  class DomainNameExists < VagrantLibvirtError
106
- error_key(:domain_name_exists_error)
114
+ error_key(:domain_name_exists)
107
115
  end
108
116
 
109
117
  class NoDomainError < VagrantLibvirtError
@@ -4,7 +4,7 @@
4
4
  <vcpu><%= @cpus %></vcpu>
5
5
 
6
6
  <% if @nested %>
7
- <cpu mode='host-model'>
7
+ <cpu mode='<%= @cpu_mode %>'>
8
8
  <model fallback='allow'>qemu64</model>
9
9
  <feature policy='optional' name='vmx'/>
10
10
  <feature policy='optional' name='svm'/>
@@ -14,6 +14,9 @@
14
14
  <os>
15
15
  <type arch='x86_64'>hvm</type>
16
16
  <boot dev='hd'/>
17
+ <kernel><%= @kernel %></kernel>
18
+ <initrd><%= @initrd %></initrd>
19
+ <cmdline><%= @cmd_line %></cmdline>
17
20
  </os>
18
21
  <features>
19
22
  <acpi/>
@@ -26,7 +29,7 @@
26
29
  <driver name='qemu' type='qcow2' cache='<%= @domain_volume_cache %>'/>
27
30
  <source file='<%= @domain_volume_path %>'/>
28
31
  <%# we need to ensure a unique target dev -%>
29
- <target dev='vda' bus='virtio'/>
32
+ <target dev='vda' bus='<%= @disk_bus %>'/>
30
33
  </disk>
31
34
  <serial type='pty'>
32
35
  <target port='0'/>
@@ -27,6 +27,12 @@ module VagrantPlugins
27
27
  netmask = xml.xpath('/network/ip/@netmask').first
28
28
  netmask = netmask.value if netmask
29
29
 
30
+ if xml.at_xpath('//network/ip/dhcp')
31
+ dhcp_enabled = true
32
+ else
33
+ dhcp_enabled = false
34
+ end
35
+
30
36
  # Calculate network address of network from ip address and
31
37
  # netmask.
32
38
  if ip && netmask
@@ -40,6 +46,7 @@ module VagrantPlugins
40
46
  ip_address: ip,
41
47
  netmask: netmask,
42
48
  network_address: network_address,
49
+ dhcp_enabled: dhcp_enabled,
43
50
  bridge_name: libvirt_network.bridge_name,
44
51
  created: true,
45
52
  active: libvirt_network.active?,
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module ProviderLibvirt
3
- VERSION = '0.0.13'
3
+ VERSION = '0.0.14'
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -89,7 +89,7 @@ en:
89
89
  fog_create_server_error: |-
90
90
  Error while creating domain: %{error_message}
91
91
  domain_name_exists: |-
92
- Name of domain about to create is already taken. Please try to run
92
+ Name `%{domain_name}` of domain about to create is already taken. Please try to run
93
93
  `vagrant up` command again.
94
94
  creating_storage_pool_error: |-
95
95
  There was error while creating libvirt storage pool: %{error_message}
@@ -101,9 +101,14 @@ en:
101
101
  Error while attaching new device to domain. %{error_message}
102
102
  no_ip_address_error: |-
103
103
  No IP address found.
104
+ management_network_error: |-
105
+ Error in specification of management network: %{error_message}.
104
106
  network_name_and_address_mismatch: |-
105
107
  Address %{ip_address} does not match with network name %{network_name}.
106
108
  Please fix your configuration and run vagrant again.
109
+ dhcp_mismatch: |-
110
+ Network %{network_name} exists but does not have dhcp %{requested}.
111
+ Please fix your configuration and run vagrant again.
107
112
  create_network_error: |-
108
113
  Error occured while creating new network: %{error_message}.
109
114
  network_not_available_error: |-
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-libvirt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
5
- prerelease:
4
+ version: 0.0.14
6
5
  platform: ruby
7
6
  authors:
8
7
  - Lukas Stanek
@@ -10,12 +9,11 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-12-12 00:00:00.000000000 Z
12
+ date: 2014-01-21 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: fog
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - '='
21
19
  - !ruby/object:Gem::Version
@@ -23,7 +21,6 @@ dependencies:
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - '='
29
26
  - !ruby/object:Gem::Version
@@ -31,23 +28,20 @@ dependencies:
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: ruby-libvirt
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ~>
32
+ - - "~>"
37
33
  - !ruby/object:Gem::Version
38
34
  version: 0.4.0
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ~>
39
+ - - "~>"
45
40
  - !ruby/object:Gem::Version
46
41
  version: 0.4.0
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: nokogiri
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
46
  - - '='
53
47
  - !ruby/object:Gem::Version
@@ -55,7 +49,6 @@ dependencies:
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
53
  - - '='
61
54
  - !ruby/object:Gem::Version
@@ -63,17 +56,15 @@ dependencies:
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: rake
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - ">="
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  type: :development
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ! '>='
67
+ - - ">="
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0'
79
70
  description: Vagrant provider for libvirt.
@@ -84,7 +75,7 @@ executables: []
84
75
  extensions: []
85
76
  extra_rdoc_files: []
86
77
  files:
87
- - .gitignore
78
+ - ".gitignore"
88
79
  - CHANGELOG.md
89
80
  - Gemfile
90
81
  - LICENSE
@@ -146,27 +137,25 @@ files:
146
137
  homepage: https://github.com/pradels/vagrant-libvirt
147
138
  licenses:
148
139
  - MIT
140
+ metadata: {}
149
141
  post_install_message:
150
142
  rdoc_options: []
151
143
  require_paths:
152
144
  - lib
153
145
  required_ruby_version: !ruby/object:Gem::Requirement
154
- none: false
155
146
  requirements:
156
- - - ! '>='
147
+ - - ">="
157
148
  - !ruby/object:Gem::Version
158
149
  version: '0'
159
150
  required_rubygems_version: !ruby/object:Gem::Requirement
160
- none: false
161
151
  requirements:
162
- - - ! '>='
152
+ - - ">="
163
153
  - !ruby/object:Gem::Version
164
154
  version: '0'
165
155
  requirements: []
166
156
  rubyforge_project:
167
- rubygems_version: 1.8.25
157
+ rubygems_version: 2.0.14
168
158
  signing_key:
169
- specification_version: 3
159
+ specification_version: 4
170
160
  summary: Vagrant provider for libvirt.
171
161
  test_files: []
172
- has_rdoc: