vagrant-libvirt 0.3.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +421 -50
  3. data/lib/vagrant-libvirt/action.rb +7 -1
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +30 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +56 -18
  6. data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -55
  7. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -3
  8. data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
  9. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  10. data/lib/vagrant-libvirt/action/forward_ports.rb +37 -38
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +163 -74
  13. data/lib/vagrant-libvirt/action/is_running.rb +1 -3
  14. data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
  15. data/lib/vagrant-libvirt/action/package_domain.rb +2 -1
  16. data/lib/vagrant-libvirt/action/set_boot_order.rb +6 -2
  17. data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
  18. data/lib/vagrant-libvirt/action/wait_till_up.rb +8 -52
  19. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  20. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  21. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  22. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  23. data/lib/vagrant-libvirt/config.rb +236 -43
  24. data/lib/vagrant-libvirt/driver.rb +49 -32
  25. data/lib/vagrant-libvirt/errors.rb +24 -1
  26. data/lib/vagrant-libvirt/plugin.rb +14 -5
  27. data/lib/vagrant-libvirt/provider.rb +2 -9
  28. data/lib/vagrant-libvirt/templates/domain.xml.erb +35 -10
  29. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  30. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  31. data/lib/vagrant-libvirt/version +1 -1
  32. data/lib/vagrant-libvirt/version.rb +57 -9
  33. data/locales/en.yml +12 -0
  34. data/spec/spec_helper.rb +37 -3
  35. data/spec/support/binding_proc.rb +24 -0
  36. data/spec/support/libvirt_context.rb +2 -0
  37. data/spec/support/matchers/have_file_content.rb +63 -0
  38. data/spec/support/sharedcontext.rb +4 -0
  39. data/spec/unit/action/clean_machine_folder_spec.rb +58 -0
  40. data/spec/unit/action/create_domain_spec.rb +121 -36
  41. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +54 -0
  42. data/spec/unit/action/create_domain_spec/default_domain.xml +49 -0
  43. data/spec/unit/action/create_domain_spec/{default_storage_pool.xml → default_system_storage_pool.xml} +0 -0
  44. data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
  45. data/spec/unit/action/create_domain_volume_spec.rb +102 -0
  46. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  47. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  48. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  49. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  50. data/spec/unit/action/destroy_domain_spec.rb +1 -1
  51. data/spec/unit/action/forward_ports_spec.rb +202 -0
  52. data/spec/unit/action/halt_domain_spec.rb +90 -0
  53. data/spec/unit/action/handle_box_image_spec.rb +363 -0
  54. data/spec/unit/action/start_domain_spec.rb +183 -1
  55. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
  56. data/spec/unit/action/start_domain_spec/default.xml +2 -2
  57. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
  58. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
  59. data/spec/unit/action/wait_till_up_spec.rb +22 -21
  60. data/spec/unit/config_spec.rb +395 -127
  61. data/spec/unit/templates/domain_all_settings.xml +14 -3
  62. data/spec/unit/templates/domain_custom_cpu_model.xml +2 -1
  63. data/spec/unit/templates/domain_defaults.xml +2 -1
  64. data/spec/unit/templates/domain_spec.rb +100 -3
  65. data/spec/unit/templates/tpm/version_1.2.xml +54 -0
  66. data/spec/unit/templates/tpm/version_2.0.xml +53 -0
  67. metadata +105 -19
data/locales/en.yml CHANGED
@@ -72,6 +72,14 @@ en:
72
72
  no_storage_pool: |-
73
73
  No usable storage pool found! Please check if storage pool is
74
74
  created and available.
75
+ box_format_duplicate_volume: |-
76
+ Encountered a duplicate volume name '%{volume}' generated for disk '%{new_disk}', due to already allocated for disk '%{orig_disk}'.
77
+ box_format_missing_attribute: |-
78
+ Invalid box metadata, missing expected attribute: '%{attribute}'
79
+ bad_box_image: |-
80
+ Received error when query the box image details from '%{image}'.
81
+ Stdout: %{out}
82
+ Stderr: %{err}
75
83
  no_box_volume: |-
76
84
  Volume for box image is missing in storage pools. Try to run vagrant
77
85
  again, or check if storage volume is accessible.
@@ -92,10 +100,14 @@ en:
92
100
  Error: %{stderr}
93
101
  no_box_virtual_size: |-
94
102
  No image virtual size specified for box.
103
+ no_disk_virtual_size: |-
104
+ No image virtual size specified for disk with index %{disk_index}.
95
105
  no_box_format: |-
96
106
  No image format specified for box.
97
107
  wrong_box_format: |-
98
108
  Wrong image format specified for box.
109
+ wrong_disk_format: |-
110
+ Wrong image format specified for disk with index %{disk_index}.
99
111
  fog_libvirt_connection_error: |-
100
112
  Error while connecting to Libvirt: %{error_message}
101
113
  fog_create_volume_error: |-
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,43 @@
1
- require 'coveralls'
2
- Coveralls.wear!
1
+ require 'simplecov'
2
+ require 'simplecov-lcov'
3
+
4
+ # patch simplecov configuration
5
+ if ! SimpleCov::Configuration.method_defined? :branch_coverage?
6
+ module SimpleCov
7
+ module Configuration
8
+ def branch_coverage?
9
+ return false
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ SimpleCov::Formatter::LcovFormatter.config do |config|
16
+ config.report_with_single_file = true
17
+ config.single_report_path = 'coverage/lcov.info'
18
+ end
19
+
20
+ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
21
+ [
22
+ SimpleCov::Formatter::HTMLFormatter,
23
+ SimpleCov::Formatter::LcovFormatter,
24
+ ]
25
+ )
26
+ SimpleCov.start do
27
+ add_filter 'spec/'
28
+ end
3
29
 
4
30
  require 'vagrant-libvirt'
5
31
  require 'support/environment_helper'
6
32
  require 'vagrant-spec/unit'
7
33
 
8
- RSpec.configure do |spec|
34
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
35
+
36
+ RSpec.configure do |config|
37
+ # ensure that setting of LIBVIRT_DEFAULT_URI in the environment is not picked
38
+ # up directly by tests, instead they must set as needed. Some build envs will
39
+ # may have it set to 'qemu:///session'.
40
+ config.before(:suite) do
41
+ ENV.delete('LIBVIRT_DEFAULT_URI')
42
+ end
9
43
  end
@@ -0,0 +1,24 @@
1
+ ##
2
+ # A simple extension of the Proc class that supports setting a custom binding
3
+ # and evaluates everything in the Proc using the new binding.
4
+
5
+ class ProcWithBinding < Proc
6
+ ##
7
+ # Set the binding for this instance
8
+
9
+ def apply_binding(bind, *args)
10
+ @binding = bind
11
+ instance_exec(*args, &self)
12
+ end
13
+
14
+ def method_missing(method, *args)
15
+ begin
16
+ method_from_binding = eval("method(#{method.inspect})", @binding)
17
+ return method_from_binding.call(*args)
18
+ rescue NameError
19
+ # fall through on purpose
20
+ end
21
+
22
+ super
23
+ end
24
+ end
@@ -7,6 +7,7 @@ shared_context 'libvirt' do
7
7
  let(:id) { 'dummy-vagrant_dummy' }
8
8
  let(:connection) { double('connection') }
9
9
  let(:domain) { double('domain') }
10
+ let(:logger) { double('logger') }
10
11
 
11
12
  def connection_result(options = {})
12
13
  result = options.fetch(:result, nil)
@@ -26,5 +27,6 @@ shared_context 'libvirt' do
26
27
  allow(domain).to receive(:mac).and_return('9C:D5:53:F1:5A:E7')
27
28
 
28
29
  allow(machine).to receive(:id).and_return(id)
30
+ allow(Log4r::Logger).to receive(:new).and_return(logger)
29
31
  end
30
32
  end
@@ -0,0 +1,63 @@
1
+ require "rspec/expectations/version"
2
+ #
3
+ # Taken from https://github.com/cucumber/aruba/blob/main/lib/aruba/matchers/file/have_file_content.rb
4
+ # with minor modifications
5
+ #
6
+ # @!method have_file_content(content)
7
+ # This matchers checks if <file> has content. `content` can be a string,
8
+ # regexp or an RSpec matcher.
9
+ #
10
+ # @param [String, Regexp, Matcher] content
11
+ # Specifies the content of the file
12
+ #
13
+ # @return [Boolean] The result
14
+ #
15
+ # false:
16
+ # * if file does not exist
17
+ # * if file content is not equal string
18
+ # * if file content does not include regexp
19
+ # * if file content does not match the content specification
20
+ #
21
+ # true:
22
+ # * if file content includes regexp
23
+ # * if file content is equal string
24
+ # * if file content matches the content specification
25
+ #
26
+ # @example Use matcher with string
27
+ #
28
+ # RSpec.describe do
29
+ # it { expect(file1).to have_file_content('a') }
30
+ # end
31
+ #
32
+ # @example Use matcher with regexp
33
+ #
34
+ # RSpec.describe do
35
+ # it { expect(file1).to have_file_content(/a/) }
36
+ # end
37
+ #
38
+ # @example Use matcher with an RSpec matcher
39
+ #
40
+ # RSpec.describe do
41
+ # it { expect(file1).to have_file_content(a_string_starting_with 'a') }
42
+ # it { expect(files1).to include a_file_having_content(a_string_starting_with 'a') }
43
+ # end
44
+ RSpec::Matchers.define :have_file_content do |expected|
45
+ match do |actual|
46
+ next false unless File.exists?(actual)
47
+
48
+ @actual = File.read(actual).chomp
49
+ @expected = if expected.is_a? String
50
+ expected.chomp
51
+ else
52
+ expected
53
+ end
54
+
55
+ values_match?(@expected, @actual)
56
+ end
57
+
58
+ diffable if expected.is_a? String
59
+
60
+ description { "have file content: #{description_of expected}" }
61
+ end
62
+
63
+ RSpec::Matchers.alias_matcher :a_file_having_content, :have_file_content
@@ -3,10 +3,14 @@ require 'spec_helper'
3
3
  shared_context 'unit' do
4
4
  include_context 'vagrant-unit'
5
5
 
6
+ let(:vagrantfile_providerconfig) { '' }
6
7
  let(:vagrantfile) do
7
8
  <<-EOF
8
9
  Vagrant.configure('2') do |config|
9
10
  config.vm.define :test
11
+ config.vm.provider :libvirt do |libvirt|
12
+ #{vagrantfile_providerconfig}
13
+ end
10
14
  end
11
15
  EOF
12
16
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'support/sharedcontext'
3
+
4
+ require 'vagrant-libvirt/action/clean_machine_folder'
5
+
6
+ describe VagrantPlugins::ProviderLibvirt::Action::CleanMachineFolder do
7
+ subject { described_class.new(app, env) }
8
+
9
+ include_context 'unit'
10
+
11
+ describe '#call' do
12
+ before do
13
+ FileUtils.touch(File.join(machine.data_dir, "box.meta"))
14
+ end
15
+
16
+ context 'with default options' do
17
+ it 'should verbosely remove the folder' do
18
+ expect(ui).to receive(:info).with('Deleting the machine folder')
19
+
20
+ expect(subject.call(env)).to be_nil
21
+
22
+ expect(File.exists?(machine.data_dir)).to eq(true)
23
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
24
+ end
25
+ end
26
+
27
+ context 'when the data dir doesn\'t exist' do
28
+ before do
29
+ Dir.mktmpdir do |d|
30
+ # returns a temporary directory that has been already deleted when running
31
+ expect(machine).to receive(:data_dir).and_return(d.to_s).exactly(3).times
32
+ end
33
+ end
34
+
35
+ it 'should remove the folder' do
36
+ expect(ui).to receive(:info).with('Deleting the machine folder')
37
+
38
+ expect(subject.call(env)).to be_nil
39
+
40
+ expect(File.exists?(machine.data_dir)).to eq(true)
41
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
42
+ end
43
+ end
44
+
45
+ context 'with quiet option enabled' do
46
+ subject { described_class.new(app, env, {:quiet => true}) }
47
+
48
+ it 'should quietly remove the folder' do
49
+ expect(ui).to_not receive(:info).with('Deleting the machine folder')
50
+
51
+ expect(subject.call(env)).to be_nil
52
+
53
+ expect(File.exists?(machine.data_dir)).to eq(true)
54
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
55
+ end
56
+ end
57
+ end
58
+ end
@@ -15,7 +15,8 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
15
15
  let(:servers) { double('servers') }
16
16
  let(:volumes) { double('volumes') }
17
17
 
18
- let(:storage_pool_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), test_file)) }
18
+ let(:domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), domain_xml_file)) }
19
+ let(:storage_pool_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), storage_pool_xml_file)) }
19
20
  let(:libvirt_storage_pool) { double('storage_pool') }
20
21
 
21
22
  describe '#call' do
@@ -26,59 +27,143 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
26
27
 
27
28
  allow(connection).to receive(:servers).and_return(servers)
28
29
  allow(connection).to receive(:volumes).and_return(volumes)
30
+
31
+ allow(logger).to receive(:info)
32
+
33
+ env[:domain_name] = "vagrant-test_default"
34
+
35
+ env[:box_volumes] = []
36
+ env[:box_volumes].push({
37
+ :path=>"/test/box.img",
38
+ :name=>"test_vagrant_box_image_1.1.1_0.img",
39
+ :virtual_size=>5
40
+ })
41
+ # should be ignored for system session and used for user session
42
+ allow(Process).to receive(:uid).and_return(9999)
43
+ allow(Process).to receive(:gid).and_return(9999)
29
44
  end
30
45
 
31
- context 'default pool' do
32
- let(:test_file) { 'default_storage_pool.xml' }
46
+ context 'connection => qemu:///system' do
47
+ context 'default pool' do
48
+ let(:domain_xml_file) { 'default_domain.xml' }
49
+ let(:storage_pool_xml_file) { 'default_system_storage_pool.xml' }
33
50
 
34
- it 'should execute correctly' do
35
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
36
- expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
37
- expect(servers).to receive(:create).and_return(machine)
51
+ it 'should execute correctly' do
52
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
53
+ expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
54
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
55
+ expect(volumes).to_not receive(:create) # additional disks only
38
56
 
39
- expect(subject.call(env)).to be_nil
40
- end
57
+ expect(subject.call(env)).to be_nil
58
+ end
41
59
 
42
- context 'additional disks' do
43
- let(:vagrantfile) do
44
- <<-EOF
45
- Vagrant.configure('2') do |config|
46
- config.vm.define :test
47
- config.vm.provider :libvirt do |libvirt|
48
- libvirt.storage :file, :size => '20G'
60
+ context 'additional disks' do
61
+ let(:vagrantfile) do
62
+ <<-EOF
63
+ Vagrant.configure('2') do |config|
64
+ config.vm.define :test
65
+ config.vm.provider :libvirt do |libvirt|
66
+ libvirt.storage :file, :size => '20G'
67
+ end
49
68
  end
69
+ EOF
50
70
  end
51
- EOF
52
- end
53
71
 
54
- context 'volume create failed' do
55
- it 'should raise an exception' do
56
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
57
- expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
58
- expect(volumes).to receive(:create).and_raise(Libvirt::Error)
72
+ context 'volume create failed' do
73
+ it 'should raise an exception' do
74
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
75
+ expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
76
+ expect(volumes).to receive(:create).and_raise(Libvirt::Error)
59
77
 
60
- expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::FogCreateDomainVolumeError)
78
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::FogCreateDomainVolumeError)
79
+ end
80
+ end
81
+
82
+ context 'volume create succeeded' do
83
+ let(:domain_xml_file) { 'additional_disks_domain.xml' }
84
+
85
+ it 'should complete' do
86
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
87
+ expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
88
+ expect(volumes).to receive(:create).with(
89
+ hash_including(
90
+ :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
91
+ :owner => 0,
92
+ :group => 0,
93
+ :pool_name => "default",
94
+ )
95
+ )
96
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
97
+
98
+ expect(subject.call(env)).to be_nil
99
+ end
61
100
  end
62
101
  end
102
+ end
63
103
 
64
- context 'volume create succeeded' do
65
- it 'should complete' do
66
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
67
- expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
68
- expect(volumes).to receive(:create)
69
- expect(servers).to receive(:create).and_return(machine)
104
+ context 'no default pool' do
105
+ it 'should raise an exception' do
106
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(nil)
70
107
 
71
- expect(subject.call(env)).to be_nil
72
- end
108
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::NoStoragePool)
73
109
  end
74
110
  end
75
111
  end
76
112
 
77
- context 'no default pool' do
78
- it 'should raise an exception' do
79
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(nil)
113
+ context 'connection => qemu:///session' do
114
+ let(:vagrantfile) do
115
+ <<-EOF
116
+ Vagrant.configure('2') do |config|
117
+ config.vm.define :test
118
+ config.vm.provider :libvirt do |libvirt|
119
+ libvirt.qemu_use_session = true
120
+ end
121
+ end
122
+ EOF
123
+ end
124
+
125
+ context 'default pool' do
126
+ let(:storage_pool_xml_file) { 'default_user_storage_pool.xml' }
127
+
128
+ it 'should execute correctly' do
129
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
130
+ expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
131
+ expect(servers).to receive(:create).and_return(machine)
132
+
133
+ expect(subject.call(env)).to be_nil
134
+ end
80
135
 
81
- expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::NoStoragePool)
136
+ context 'additional disks' do
137
+ let(:vagrantfile) do
138
+ <<-EOF
139
+ Vagrant.configure('2') do |config|
140
+ config.vm.define :test
141
+ config.vm.provider :libvirt do |libvirt|
142
+ libvirt.qemu_use_session = true
143
+ libvirt.storage :file, :size => '20G'
144
+ end
145
+ end
146
+ EOF
147
+ end
148
+
149
+ context 'volume create succeeded' do
150
+ it 'should complete' do
151
+ expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
152
+ expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
153
+ expect(volumes).to receive(:create).with(
154
+ hash_including(
155
+ :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
156
+ :owner => 9999,
157
+ :group => 9999,
158
+ :pool_name => "default",
159
+ )
160
+ )
161
+ expect(servers).to receive(:create).and_return(machine)
162
+
163
+ expect(subject.call(env)).to be_nil
164
+ end
165
+ end
166
+ end
82
167
  end
83
168
  end
84
169
  end
@@ -0,0 +1,54 @@
1
+ <domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
2
+ <name>vagrant-test_default</name>
3
+ <title></title>
4
+ <description>Source: /rootpath/Vagrantfile</description>
5
+ <uuid></uuid>
6
+ <memory>524288</memory>
7
+ <vcpu>1</vcpu>
8
+
9
+
10
+ <cpu mode='host-model'>
11
+ <model fallback='allow'></model>
12
+ </cpu>
13
+
14
+
15
+ <os>
16
+ <type>hvm</type>
17
+ <kernel></kernel>
18
+ <initrd></initrd>
19
+ <cmdline></cmdline>
20
+ </os>
21
+ <features>
22
+ <acpi/>
23
+ <apic/>
24
+ <pae/>
25
+ </features>
26
+ <clock offset='utc'>
27
+ </clock>
28
+ <devices>
29
+ <disk type='file' device='disk'>
30
+ <driver name='qemu' type='qcow2' cache='default'/>
31
+ <source file='/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2'/>
32
+ <target dev='vdb' bus='virtio'/>
33
+ </disk>
34
+
35
+
36
+ <serial type='pty'>
37
+ <target port='0'/>
38
+ </serial>
39
+ <console type='pty'>
40
+ <target port='0'/>
41
+ </console>
42
+
43
+
44
+ <input type='mouse' bus='ps2'/>
45
+
46
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us' />
47
+ <video>
48
+ <model type='cirrus' vram='9216' heads='1'/>
49
+ </video>
50
+
51
+
52
+ </devices>
53
+
54
+ </domain>