vagrant-libvirt 0.0.30 → 0.0.31

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +20 -0
  3. data/Gemfile +6 -1
  4. data/README.md +146 -6
  5. data/example_box/Vagrantfile +1 -1
  6. data/example_box/metadata.json +1 -1
  7. data/lib/vagrant-libvirt.rb +3 -15
  8. data/lib/vagrant-libvirt/action.rb +59 -73
  9. data/lib/vagrant-libvirt/action/create_domain.rb +47 -19
  10. data/lib/vagrant-libvirt/action/create_domain_volume.rb +5 -5
  11. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +82 -36
  12. data/lib/vagrant-libvirt/action/create_networks.rb +99 -54
  13. data/lib/vagrant-libvirt/action/destroy_domain.rb +4 -4
  14. data/lib/vagrant-libvirt/action/destroy_networks.rb +2 -2
  15. data/lib/vagrant-libvirt/action/halt_domain.rb +1 -1
  16. data/lib/vagrant-libvirt/action/handle_box_image.rb +25 -5
  17. data/lib/vagrant-libvirt/action/handle_storage_pool.rb +9 -7
  18. data/lib/vagrant-libvirt/action/is_running.rb +1 -1
  19. data/lib/vagrant-libvirt/action/is_suspended.rb +1 -1
  20. data/lib/vagrant-libvirt/action/package_domain.rb +3 -3
  21. data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +8 -5
  22. data/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb +1 -1
  23. data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +1 -1
  24. data/lib/vagrant-libvirt/action/read_mac_addresses.rb +1 -1
  25. data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +1 -1
  26. data/lib/vagrant-libvirt/action/remove_stale_volume.rb +2 -2
  27. data/lib/vagrant-libvirt/action/resume_domain.rb +1 -1
  28. data/lib/vagrant-libvirt/action/set_boot_order.rb +66 -0
  29. data/lib/vagrant-libvirt/action/set_name_of_domain.rb +3 -2
  30. data/lib/vagrant-libvirt/action/start_domain.rb +1 -1
  31. data/lib/vagrant-libvirt/action/suspend_domain.rb +1 -1
  32. data/lib/vagrant-libvirt/action/wait_till_up.rb +1 -1
  33. data/lib/vagrant-libvirt/cap/mount_p9.rb +2 -1
  34. data/lib/vagrant-libvirt/cap/synced_folder.rb +11 -5
  35. data/lib/vagrant-libvirt/config.rb +44 -5
  36. data/lib/vagrant-libvirt/driver.rb +121 -0
  37. data/lib/vagrant-libvirt/errors.rb +4 -0
  38. data/lib/vagrant-libvirt/plugin.rb +7 -5
  39. data/lib/vagrant-libvirt/provider.rb +54 -12
  40. data/lib/vagrant-libvirt/templates/domain.xml.erb +18 -12
  41. data/lib/vagrant-libvirt/templates/filesystem.xml.erb +1 -1
  42. data/lib/vagrant-libvirt/templates/tunnel_interface.xml.erb +11 -0
  43. data/lib/vagrant-libvirt/util/network_util.rb +11 -1
  44. data/lib/vagrant-libvirt/version.rb +1 -1
  45. data/locales/en.yml +24 -15
  46. data/spec/support/environment_helper.rb +1 -1
  47. data/tools/prepare_redhat_for_box.sh +1 -2
  48. metadata +6 -5
  49. data/lib/vagrant-libvirt/action/connect_libvirt.rb +0 -51
  50. data/lib/vagrant-libvirt/action/read_ssh_info.rb +0 -68
  51. data/lib/vagrant-libvirt/action/read_state.rb +0 -60
@@ -47,6 +47,7 @@ module VagrantPlugins
47
47
  attr_accessor :management_network_name
48
48
  attr_accessor :management_network_address
49
49
  attr_accessor :management_network_mode
50
+ attr_accessor :management_network_mac
50
51
 
51
52
  # Default host prefix (alternative to use project folder name)
52
53
  attr_accessor :default_prefix
@@ -55,9 +56,11 @@ module VagrantPlugins
55
56
  attr_accessor :memory
56
57
  attr_accessor :cpus
57
58
  attr_accessor :cpu_mode
59
+ attr_accessor :loader
58
60
  attr_accessor :boot_order
59
61
  attr_accessor :machine_type
60
62
  attr_accessor :machine_arch
63
+ attr_accessor :machine_virtual_size
61
64
  attr_accessor :disk_bus
62
65
  attr_accessor :nic_model_type
63
66
  attr_accessor :nested
@@ -74,9 +77,17 @@ module VagrantPlugins
74
77
  attr_accessor :video_vram
75
78
  attr_accessor :keymap
76
79
 
80
+ # Sets the max number of NICs that can be created
81
+ # Default set to 8. Don't change the default unless you know
82
+ # what are doing
83
+ attr_accessor :nic_adapter_count
84
+
77
85
  # Storage
78
86
  attr_accessor :disks
79
- attr_accessor :cdroms
87
+ attr_accessor :cdroms
88
+
89
+ # Inputs
90
+ attr_accessor :inputs
80
91
 
81
92
  def initialize
82
93
  @uri = UNSET_VALUE
@@ -91,13 +102,16 @@ module VagrantPlugins
91
102
  @management_network_name = UNSET_VALUE
92
103
  @management_network_address = UNSET_VALUE
93
104
  @management_network_mode = UNSET_VALUE
105
+ @management_network_mac = UNSET_VALUE
94
106
 
95
107
  # Domain specific settings.
96
108
  @memory = UNSET_VALUE
97
109
  @cpus = UNSET_VALUE
98
110
  @cpu_mode = UNSET_VALUE
111
+ @loader = UNSET_VALUE
99
112
  @machine_type = UNSET_VALUE
100
113
  @machine_arch = UNSET_VALUE
114
+ @machine_virtual_size = UNSET_VALUE
101
115
  @disk_bus = UNSET_VALUE
102
116
  @nic_model_type = UNSET_VALUE
103
117
  @nested = UNSET_VALUE
@@ -114,13 +128,18 @@ module VagrantPlugins
114
128
  @video_vram = UNSET_VALUE
115
129
  @keymap = UNSET_VALUE
116
130
 
131
+ @nic_adapter_count = UNSET_VALUE
132
+
117
133
  # Boot order
118
134
  @boot_order = []
119
135
  # Storage
120
136
  @disks = []
121
- @cdroms = []
137
+ @cdroms = []
138
+
139
+ # Inputs
140
+ @inputs = UNSET_VALUE
122
141
  end
123
-
142
+
124
143
  def boot(device)
125
144
  @boot_order << device # append
126
145
  end
@@ -153,7 +172,22 @@ module VagrantPlugins
153
172
  end
154
173
 
155
174
  # is it better to raise our own error, or let libvirt cause the exception?
156
- raise "Only four cdroms may be attached at a time"
175
+ raise 'Only four cdroms may be attached at a time'
176
+ end
177
+
178
+ def input(options={})
179
+ if options[:type].nil? || options[:bus].nil?
180
+ raise 'Input type AND bus must be specified'
181
+ end
182
+
183
+ if @inputs == UNSET_VALUE
184
+ @inputs = []
185
+ end
186
+
187
+ @inputs.push({
188
+ type: options[:type],
189
+ bus: options[:bus]
190
+ })
157
191
  end
158
192
 
159
193
  # NOTE: this will run twice for each time it's needed- keep it idempotent
@@ -277,6 +311,7 @@ module VagrantPlugins
277
311
  @management_network_name = 'vagrant-libvirt' if @management_network_name == UNSET_VALUE
278
312
  @management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
279
313
  @management_network_mode = 'nat' if @management_network_mode == UNSET_VALUE
314
+ @management_network_mac = nil if @management_network_mac == UNSET_VALUE
280
315
 
281
316
  # generate a URI if none is supplied
282
317
  @uri = _generate_uri() if @uri == UNSET_VALUE
@@ -285,8 +320,10 @@ module VagrantPlugins
285
320
  @memory = 512 if @memory == UNSET_VALUE
286
321
  @cpus = 1 if @cpus == UNSET_VALUE
287
322
  @cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
323
+ @loader = nil if @loader == UNSET_VALUE
288
324
  @machine_type = nil if @machine_type == UNSET_VALUE
289
325
  @machine_arch = nil if @machine_arch == UNSET_VALUE
326
+ @machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
290
327
  @disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
291
328
  @nic_model_type = 'virtio' if @nic_model_type == UNSET_VALUE
292
329
  @nested = false if @nested == UNSET_VALUE
@@ -306,13 +343,15 @@ module VagrantPlugins
306
343
  @video_type = 'cirrus' if @video_type == UNSET_VALUE
307
344
  @video_vram = 9216 if @video_vram == UNSET_VALUE
308
345
  @keymap = 'en-us' if @keymap == UNSET_VALUE
309
-
346
+ @nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
347
+
310
348
  # Boot order
311
349
  @boot_order = [] if @boot_order == UNSET_VALUE
312
350
 
313
351
  # Storage
314
352
  @disks = [] if @disks == UNSET_VALUE
315
353
  @cdroms = [] if @cdroms == UNSET_VALUE
354
+ @inputs = [{:type => "mouse", :bus => "ps2"}] if @inputs == UNSET_VALUE
316
355
  end
317
356
 
318
357
  def validate(machine)
@@ -0,0 +1,121 @@
1
+ require 'fog/libvirt'
2
+ require 'log4r'
3
+
4
+ module VagrantPlugins
5
+ module ProviderLibvirt
6
+ class Driver
7
+
8
+ # store the connection at the process level
9
+ #
10
+ # possibly this should be a connection pool using the connection
11
+ # settings as a key to allow per machine connection attributes
12
+ # to be used.
13
+ @@connection = nil
14
+
15
+ def initialize(machine)
16
+ @logger = Log4r::Logger.new('vagrant_libvirt::driver')
17
+ @machine = machine
18
+ end
19
+
20
+ def connection
21
+ # If already connected to libvirt, just use it and don't connect
22
+ # again.
23
+ return @@connection if @@connection
24
+
25
+ # Get config options for libvirt provider.
26
+ config = @machine.provider_config
27
+ uri = config.uri
28
+
29
+ conn_attr = {}
30
+ conn_attr[:provider] = 'libvirt'
31
+ conn_attr[:libvirt_uri] = uri
32
+ conn_attr[:libvirt_username] = config.username if config.username
33
+ conn_attr[:libvirt_password] = config.password if config.password
34
+
35
+ # Setup command for retrieving IP address for newly created machine
36
+ # with some MAC address. Get it from dnsmasq leases table
37
+ ip_command = %q[ awk "/$mac/ {print \$1}" /proc/net/arp ]
38
+ conn_attr[:libvirt_ip_command] = ip_command
39
+
40
+ @logger.info("Connecting to Libvirt (#{uri}) ...")
41
+ begin
42
+ @@connection = Fog::Compute.new(conn_attr)
43
+ rescue Fog::Errors::Error => e
44
+ raise Errors::FogLibvirtConnectionError,
45
+ :error_message => e.message
46
+ end
47
+
48
+ @@connection
49
+ end
50
+
51
+ def get_domain(mid)
52
+ begin
53
+ domain = connection.servers.get(mid)
54
+ rescue Libvirt::RetrieveError => e
55
+ if e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
56
+ @logger.debug("machine #{mid} not found #{e}.")
57
+ return nil
58
+ else
59
+ raise e
60
+ end
61
+ end
62
+
63
+ domain
64
+ end
65
+
66
+ def created?(mid)
67
+ domain = get_domain(mid)
68
+ !domain.nil?
69
+ end
70
+
71
+ def get_ipaddress(machine)
72
+ # Find the machine
73
+ domain = get_domain(machine.id)
74
+
75
+ if domain.nil?
76
+ # The machine can't be found
77
+ return nil
78
+ end
79
+
80
+ # Get IP address from arp table
81
+ ip_address = nil
82
+ begin
83
+ domain.wait_for(2) do
84
+ addresses.each_pair do |type, ip|
85
+ # Multiple leases are separated with a newline, return only
86
+ # the most recent address
87
+ ip_address = ip[0].split("\n").first if ip[0] != nil
88
+ end
89
+ ip_address != nil
90
+ end
91
+ rescue Fog::Errors::TimeoutError
92
+ @logger.info("Timeout at waiting for an ip address for machine %s" % machine.name)
93
+ end
94
+
95
+ if not ip_address
96
+ @logger.info("No arp table entry found for machine %s" % machine.name)
97
+ return nil
98
+ end
99
+
100
+ ip_address
101
+ end
102
+
103
+ def state(machine)
104
+ # may be other error states with initial retreival we can't handle
105
+ begin
106
+ domain = get_domain(machine.id)
107
+ rescue Libvirt::RetrieveError => e
108
+ @logger.debug("Machine #{machine.id} not found #{e}.")
109
+ return :not_created
110
+ end
111
+
112
+ # TODO: terminated no longer appears to be a valid fog state, remove?
113
+ if domain.nil? || domain.state.to_sym == :terminated
114
+ return :not_created
115
+ end
116
+
117
+ return domain.state.gsub("-", "_").to_sym
118
+ end
119
+ end
120
+ end
121
+ end
@@ -106,6 +106,10 @@ module VagrantPlugins
106
106
  error_key(:activate_network_error)
107
107
  end
108
108
 
109
+ class TunnelPortNotDefined < VagrantLibvirtError
110
+ error_key(:tunnel_port_not_defined)
111
+ end
112
+
109
113
  # Other exceptions
110
114
  class InterfaceSlotNotAvailable < VagrantLibvirtError
111
115
  error_key(:interface_slot_not_available)
@@ -23,11 +23,7 @@ module VagrantPlugins
23
23
  Config
24
24
  end
25
25
 
26
- provider('libvirt', parallel: true) do
27
- # Setup logging and i18n
28
- setup_logging
29
- setup_i18n
30
-
26
+ provider('libvirt', parallel: true, box_optional: true) do
31
27
  require_relative 'provider'
32
28
  Provider
33
29
  end
@@ -90,6 +86,12 @@ module VagrantPlugins
90
86
  end
91
87
  end
92
88
 
89
+ # Setup logging and i18n before any autoloading loads other classes
90
+ # with logging configured as this prevents inheritance of the log level
91
+ # from the parent logger.
92
+ setup_logging
93
+ setup_i18n
94
+
93
95
  end
94
96
  end
95
97
  end
@@ -2,6 +2,7 @@ require 'vagrant'
2
2
 
3
3
  module VagrantPlugins
4
4
  module ProviderLibvirt
5
+ autoload :Driver, 'vagrant-libvirt/driver'
5
6
 
6
7
  # This is the base class for a provider for the V2 API. A provider
7
8
  # is responsible for creating compute resources to match the
@@ -22,6 +23,12 @@ module VagrantPlugins
22
23
  nil
23
24
  end
24
25
 
26
+ def driver
27
+ return @driver if @driver
28
+
29
+ @driver = Driver.new(@machine)
30
+ end
31
+
25
32
  # This method is called if the underying machine ID changes. Providers
26
33
  # can use this method to load in new data for the actual backing
27
34
  # machine or to realize that the machine is now gone (the ID can
@@ -33,9 +40,8 @@ module VagrantPlugins
33
40
  # SSH into the machine. If the machine is not at a point where
34
41
  # SSH is even possible, then `nil` should be returned.
35
42
  def ssh_info
36
- # Run a custom action called "read_ssh_info" which does what it says
37
- # and puts the resulting SSH info into the `:machine_ssh_info` key in
38
- # the environment.
43
+ # Return the ssh_info if already retrieved otherwise call the driver
44
+ # and save the result.
39
45
  #
40
46
  # Ssh info has following format..
41
47
  #
@@ -45,8 +51,32 @@ module VagrantPlugins
45
51
  # :username => "mitchellh",
46
52
  # :private_key_path => "/path/to/my/key"
47
53
  #}
48
- env = @machine.action('read_ssh_info')
49
- env[:machine_ssh_info]
54
+ # note that modifing @machine.id or accessing @machine.state is not
55
+ # thread safe, so be careful to avoid these here as this method may
56
+ # be called from other threads of execution.
57
+ return nil if state.id != :running
58
+
59
+ ip = driver.get_ipaddress(@machine)
60
+
61
+ # if can't determine the IP, just return nil and let the core
62
+ # deal with it, similar to the docker provider
63
+ return nil if !ip
64
+
65
+ ssh_info = {
66
+ :host => ip,
67
+ :port => @machine.config.ssh.guest_port,
68
+ :forward_agent => @machine.config.ssh.forward_agent,
69
+ :forward_x11 => @machine.config.ssh.forward_x11,
70
+ }
71
+
72
+ ssh_info[:proxy_command] = (
73
+ "ssh '#{@machine.provider_config.host}' " +
74
+ "-l '#{@machine.provider_config.username}' " +
75
+ "-i '#{@machine.provider_config.id_ssh_key_file}' " +
76
+ "nc %h %p"
77
+ ) if @machine.provider_config.connect_via_ssh
78
+
79
+ ssh_info
50
80
  end
51
81
 
52
82
  def mac_addresses
@@ -64,16 +94,28 @@ module VagrantPlugins
64
94
  # This should return the state of the machine within this provider.
65
95
  # The state must be an instance of {MachineState}.
66
96
  def state
67
- # Run a custom action we define called "read_state" which does
68
- # what it says. It puts the state in the `:machine_state_id`
69
- # key in the environment.
70
- env = @machine.action('read_state')
71
97
 
72
- state_id = env[:machine_state_id]
98
+ state_id = nil
99
+ state_id = :not_created if !@machine.id
100
+ state_id = :not_created if (
101
+ !state_id && (!@machine.id || !driver.created?(@machine.id)))
102
+ # Query the driver for the current state of the machine
103
+ state_id = driver.state(@machine) if @machine.id && !state_id
104
+ state_id = :unknown if !state_id
105
+
106
+ # This is a special pseudo-state so that we don't set the
107
+ # NOT_CREATED_ID while we're setting up the machine. This avoids
108
+ # clearing the data dir.
109
+ state_id = :preparing if @machine.id == "preparing"
73
110
 
74
111
  # Get the short and long description
75
- short = I18n.t("vagrant_libvirt.states.short_#{state_id}")
76
- long = I18n.t("vagrant_libvirt.states.long_#{state_id}")
112
+ short = state_id.to_s.gsub("_", " ")
113
+ long = I18n.t("vagrant_libvirt.states.#{state_id}")
114
+
115
+ # If we're not created, then specify the special ID flag
116
+ if state_id == :not_created
117
+ state_id = Vagrant::MachineState::NOT_CREATED_ID
118
+ end
77
119
 
78
120
  # Return the MachineState object
79
121
  Vagrant::MachineState.new(state_id, short, long)
@@ -3,15 +3,17 @@
3
3
  <memory><%= @memory_size %></memory>
4
4
  <vcpu><%= @cpus %></vcpu>
5
5
 
6
- <% if @nested %>
7
- <cpu mode='<%= @cpu_mode %>'>
8
- <% if @cpu_mode != 'host-passthrough' %>
9
- <model fallback='allow'>qemu64</model>
6
+
7
+ <cpu mode='<%= @cpu_mode %>'>
8
+ <% if @cpu_mode != 'host-passthrough' %>
9
+ <model fallback='allow'>qemu64</model>
10
+ <% if @nested %>
10
11
  <feature policy='optional' name='vmx'/>
11
12
  <feature policy='optional' name='svm'/>
12
13
  <% end %>
13
- </cpu>
14
- <% end %>
14
+ <% end %>
15
+ </cpu>
16
+
15
17
 
16
18
  <os>
17
19
  <% if @machine_type %>
@@ -27,13 +29,11 @@
27
29
  <type>hvm</type>
28
30
  <% end %>
29
31
  <% end %>
32
+ <% if @loader %>
33
+ <loader readonly='yes' type='rom'><%= @loader %></loader>
34
+ <% end %>
30
35
  <% if @boot_order.count >= 1 %>
31
- <% @boot_order.each do |b| %>
32
- <boot dev='<%= b %>'/>
33
- <% end %>
34
36
  <bootmenu enable='yes'/>
35
- <% else %>
36
- <boot dev='hd' />
37
37
  <% end %>
38
38
  <kernel><%= @kernel %></kernel>
39
39
  <initrd><%= @initrd %></initrd>
@@ -46,12 +46,14 @@
46
46
  </features>
47
47
  <clock offset='utc'/>
48
48
  <devices>
49
+ <% if @domain_volume_path %>
49
50
  <disk type='file' device='disk'>
50
51
  <driver name='qemu' type='qcow2' cache='<%= @domain_volume_cache %>'/>
51
52
  <source file='<%= @domain_volume_path %>'/>
52
53
  <%# we need to ensure a unique target dev -%>
53
54
  <target dev='vda' bus='<%= @disk_bus %>'/>
54
55
  </disk>
56
+ <% end %>
55
57
  <%# additional disks -%>
56
58
  <% @disks.each do |d| -%>
57
59
  <disk type='file' device='disk'>
@@ -78,7 +80,11 @@
78
80
  <console type='pty'>
79
81
  <target port='0'/>
80
82
  </console>
81
- <input type='mouse' bus='ps2'/>
83
+
84
+ <% @inputs.each do |input| %>
85
+ <input type='<%= input[:type] %>' bus='<%= input[:bus] %>'/>
86
+ <% end %>
87
+
82
88
  <%# Video device -%>
83
89
  <graphics type='<%= @graphics_type %>' port='<%= @graphics_port %>' autoport='<%= @graphics_autoport %>' listen='<%= @graphics_ip %>' keymap='<%= @keymap %>' <%= @graphics_passwd%> />
84
90
  <video>