vagrant-kvm 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +14 -0
  5. data/CHANGELOG.md +29 -0
  6. data/DEVELOPMENT.md +87 -0
  7. data/Gemfile +1 -0
  8. data/INSTALL.md +229 -0
  9. data/LICENSE +2 -1
  10. data/README.md +154 -63
  11. data/Rakefile +24 -1
  12. data/example_box/README.md +8 -8
  13. data/lib/vagrant-kvm/action.rb +47 -5
  14. data/lib/vagrant-kvm/action/boot.rb +0 -4
  15. data/lib/vagrant-kvm/action/clear_forwarded_ports.rb +53 -0
  16. data/lib/vagrant-kvm/action/forward_ports.rb +104 -0
  17. data/lib/vagrant-kvm/action/import.rb +97 -18
  18. data/lib/vagrant-kvm/action/init_storage_pool.rb +3 -1
  19. data/lib/vagrant-kvm/action/message_not_running.rb +16 -0
  20. data/lib/vagrant-kvm/action/network.rb +12 -13
  21. data/lib/vagrant-kvm/action/package_vagrantfile.rb +3 -1
  22. data/lib/vagrant-kvm/action/prepare_gui.rb +20 -0
  23. data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +8 -16
  24. data/lib/vagrant-kvm/action/prepare_nfs_valid_ids.rb +17 -0
  25. data/lib/vagrant-kvm/action/reset_image_permission.rb +23 -0
  26. data/lib/vagrant-kvm/action/resume_network.rb +28 -0
  27. data/lib/vagrant-kvm/action/share_folders.rb +6 -5
  28. data/lib/vagrant-kvm/action/suspend.rb +8 -1
  29. data/lib/vagrant-kvm/config.rb +103 -2
  30. data/lib/vagrant-kvm/driver/driver.rb +321 -99
  31. data/lib/vagrant-kvm/errors.rb +18 -0
  32. data/lib/vagrant-kvm/provider.rb +4 -1
  33. data/lib/vagrant-kvm/util.rb +3 -0
  34. data/lib/vagrant-kvm/util/commands.rb +23 -0
  35. data/lib/vagrant-kvm/util/definition_attributes.rb +33 -0
  36. data/lib/vagrant-kvm/util/disk_info.rb +48 -0
  37. data/lib/vagrant-kvm/util/network_definition.rb +44 -84
  38. data/lib/vagrant-kvm/util/vm_definition.rb +91 -103
  39. data/lib/vagrant-kvm/version.rb +1 -1
  40. data/locales/en.yml +8 -0
  41. data/locales/ja.yml +14 -0
  42. data/spec/acceptance/vagrant-kvm_spec.rb +80 -0
  43. data/spec/fedora/10.virt.rules +10 -0
  44. data/spec/fedora/50-vagrant-libvirt-access.pkla +6 -0
  45. data/spec/spec_helper.rb +30 -0
  46. data/spec/support/libvirt_helper.rb +37 -0
  47. data/spec/support/vagrant_kvm_helper.rb +39 -0
  48. data/spec/test_files/box.xml +74 -0
  49. data/spec/vagrant-kvm/config_spec.rb +56 -0
  50. data/spec/vagrant-kvm/driver/driver_spec.rb +36 -0
  51. data/spec/vagrant-kvm/errors_spec.rb +25 -0
  52. data/spec/vagrant-kvm/util/network_definition_spec.rb +60 -0
  53. data/spec/vagrant-kvm/util/vm_definition_spec.rb +76 -0
  54. data/templates/libvirt_domain.erb +34 -12
  55. data/templates/libvirt_network.erb +13 -0
  56. data/templates/package_Vagrantfile.erb +11 -0
  57. data/vagrant-kvm.gemspec +1 -2
  58. metadata +41 -42
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module ProviderKvm
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
5
5
  end
@@ -10,3 +10,11 @@ en:
10
10
  kvm_invalid_version: |-
11
11
  Invalid Kvm version detected: %{actual}, but a version %{required} is
12
12
  required.
13
+ kvm_no_qemu_binary: |-
14
+ Executable binary of qemu could not be found. Please re-examine %{cause}.
15
+ kvm_fail_image_conversion: |-
16
+ Failed to convert image to specified format.
17
+ kvm_failed_command: |-
18
+ System command %{cmd} returned with error code %{res}.
19
+ kvm_bad_box_format: |-
20
+ Unsupported box format.
@@ -0,0 +1,14 @@
1
+ en:
2
+ vagrant_kvm:
3
+ test_message: |-
4
+ これはテストメッセージです。
5
+ errors:
6
+ kvm_no_connection: |-
7
+ KVMにLibvirt経由で接続できません。カーネルモジュールの
8
+ 'kvm' 及び、'kvm-intel'か'kvm-amd'が正しくインストールされ、(debian/ubuntuの場合)あなたのユーザIDが
9
+ libvirtグループに属しているか、確認してください。
10
+ kvm_invalid_version: |-
11
+ 不適切なKVMのバージョンが検出されました:バージョン %{actual} が検出されましたが、%{required}
12
+ が必要です。
13
+ kvm_no_qemu_binary: |-
14
+ Qemuの実行バイナリが見つかりません。%{cause}を確認してください。
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'vagrant-kvm' do
4
+ before(:all) do
5
+ create_vagrantfile
6
+ end
7
+
8
+ before(:all) do
9
+ @old_domains = libvirt.domains.count
10
+ @old_pool_files = pool_files.count
11
+ end
12
+
13
+ describe 'up' do
14
+ before(:all) do
15
+ vagrant_up
16
+ end
17
+
18
+ after(:all) do
19
+ vagrant_destroy
20
+ end
21
+
22
+ it'creates new libvirt domain' do
23
+ (libvirt.domains.count - @old_domains).should == 1
24
+ end
25
+
26
+ it 'starts created libvirt domain' do
27
+ expect(libvirt.domain).to be_active
28
+ end
29
+
30
+ it 'creates disk image file' do
31
+ (pool_files.count - @old_pool_files).should == 1
32
+ end
33
+
34
+ it 'creates new pool' do
35
+ expect(libvirt.storage_pools).to include('vagrant')
36
+ end
37
+
38
+ it 'creates new network' do
39
+ expect(libvirt.networks).to include('vagrant')
40
+ end
41
+ end
42
+
43
+ describe 'down' do
44
+ before(:all) do
45
+ vagrant_up
46
+ vagrant_halt
47
+ end
48
+
49
+ after(:all) do
50
+ vagrant_destroy
51
+ end
52
+
53
+ it 'shutdowns domain' do
54
+ expect(libvirt.domain).not_to be_active
55
+ end
56
+ end
57
+
58
+ describe 'destroy' do
59
+ before(:all) do
60
+ vagrant_up
61
+ vagrant_destroy
62
+ end
63
+
64
+ it 'undefines domain' do
65
+ libvirt.domains.count.should == @old_domains
66
+ end
67
+
68
+ it 'removes disk image file' do
69
+ expect(pool_files).to be_empty
70
+ end
71
+
72
+ it 'does not undefine storage pool' do
73
+ expect(libvirt.storage_pools).to include('vagrant')
74
+ end
75
+
76
+ it 'does not undefine new network' do
77
+ expect(libvirt.networks).to include('vagrant')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,10 @@
1
+ polkit.addRule(function(action, subject) {
2
+ polkit.log("action=" + action);
3
+ polkit.log("subject=" + subject);
4
+ var now = new Date();
5
+ polkit.log("now=" + now)
6
+ if ((action.id == "org.libvirt.unix.manage" || action.id == "org.libvirt.unix.monitor") && subject.isInGroup("virt")) {
7
+ return polkit.Result.YES;
8
+ }
9
+ return null;
10
+ });
@@ -0,0 +1,6 @@
1
+ [libvirt Management Access]
2
+ Identity=unix-group:virt
3
+ Action=org.libvirt.unix.manage;org.libvirt.unix.monitor
4
+ ResultAny=yes
5
+ ResultInactive=yes
6
+ ResultActive=yes
@@ -0,0 +1,30 @@
1
+ require 'vagrant-kvm'
2
+ require 'support/libvirt_helper'
3
+ require 'support/vagrant_kvm_helper'
4
+ require 'pry'
5
+
6
+ def libvirt
7
+ @libvirt ||= LibvirtHelper.new
8
+ end
9
+
10
+ RSpec.configure do |spec|
11
+ spec.include VagrantKvmHelper
12
+
13
+ spec.before(:all) do
14
+
15
+ # make sure everything is run in tmp
16
+ Dir.chdir '/tmp'
17
+ end
18
+
19
+ spec.after(:all) do
20
+ libvirt.connection.close
21
+ end
22
+
23
+ at_exit do
24
+ File.delete('Vagrantfile') if File.exists?('Vagrantfile')
25
+ end
26
+ end
27
+
28
+ def test_file(path)
29
+ File.join(File.dirname(__FILE__), "test_files", path)
30
+ end
@@ -0,0 +1,37 @@
1
+ require 'libvirt'
2
+
3
+ class LibvirtHelper
4
+
5
+ attr_reader :connection
6
+
7
+ def initialize
8
+ @connection = Libvirt.open('qemu:///system')
9
+ end
10
+
11
+ def domains
12
+ # list_domains returns IDs of active domains
13
+ # list_defined_domains returns names of inactive domains
14
+ @connection.list_domains + @connection.list_defined_domains
15
+ end
16
+
17
+ def domain
18
+ domain = domains.first
19
+ case domain
20
+ when Integer
21
+ @connection.lookup_domain_by_id(domain)
22
+ when String
23
+ @connection.lookup_domain_by_name(domain)
24
+ else
25
+ raise "Cannot find domain!"
26
+ end
27
+ end
28
+
29
+ def storage_pools
30
+ @connection.list_storage_pools
31
+ end
32
+
33
+ def networks
34
+ @connection.list_networks
35
+ end
36
+
37
+ end # LibvirtHelper
@@ -0,0 +1,39 @@
1
+ module VagrantKvmHelper
2
+
3
+ def create_vagrantfile
4
+ File.open('Vagrantfile', 'w') do |file|
5
+ file.write <<-RUBY
6
+ Vagrant.require_plugin 'vagrant-kvm'
7
+
8
+ Vagrant.configure('2') do |config|
9
+ config.vm.box = 'vagrant-kvm-specs'
10
+ config.vm.network :private_network, ip: '192.168.50.2'
11
+ end
12
+ RUBY
13
+ end
14
+ end
15
+
16
+ def vagrant_up
17
+ silent_exec('bundle exec vagrant up --provider=kvm')
18
+ end
19
+
20
+ def vagrant_halt
21
+ silent_exec('bundle exec vagrant halt')
22
+ end
23
+
24
+ def vagrant_destroy
25
+ silent_exec('bundle exec vagrant destroy -f')
26
+ end
27
+
28
+ def pool_files
29
+ Dir["/home/#{ENV['USER']}/.vagrant.d/tmp/storage-pool/*"]
30
+ end
31
+
32
+ private
33
+
34
+ def silent_exec(cmd)
35
+ cmd << ' 2>&1' unless !!ENV['DEBUG']
36
+ `#{cmd}`
37
+ end
38
+
39
+ end # VagrantKvmHelper
@@ -0,0 +1,74 @@
1
+ <domain type='kvm' id='37'>
2
+ <name>winxp_base</name>
3
+ <memory unit='KiB'>524288</memory>
4
+ <currentMemory unit='KiB'>524288</currentMemory>
5
+ <vcpu placement='static'>1</vcpu>
6
+ <os>
7
+ <type arch='x86_64' machine='pc-1.2'>hvm</type>
8
+ <boot dev='hd'/>
9
+ </os>
10
+ <features>
11
+ <acpi/>
12
+ <apic/>
13
+ <pae/>
14
+ </features>
15
+ <clock offset='utc'/>
16
+ <on_poweroff>destroy</on_poweroff>
17
+ <on_reboot>restart</on_reboot>
18
+ <on_crash>restart</on_crash>
19
+ <devices>
20
+ <emulator>/usr/bin/kvm</emulator>
21
+ <disk type='file' device='disk'>
22
+ <driver name='qemu' type='qcow2'/>
23
+ <source file='winxp.qcow2'/>
24
+ <target dev='vda' bus='virtio'/>
25
+ <alias name='virtio-disk0'/>
26
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
27
+ </disk>
28
+ <controller type='usb' index='0'>
29
+ <alias name='usb0'/>
30
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
31
+ </controller>
32
+ <controller type='virtio-serial' index='0'>
33
+ <alias name='virtio-serial0'/>
34
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
35
+ </controller>
36
+ <interface type='network'>
37
+ <mac address='08:00:27:30:3b:ea'/>
38
+ <source network='vagrant'/>
39
+ <target dev='vnet0'/>
40
+ <model type='virtio'/>
41
+ <alias name='net0'/>
42
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
43
+ </interface>
44
+ <serial type='pty'>
45
+ <source path='/dev/pts/1'/>
46
+ <target port='0'/>
47
+ <alias name='serial0'/>
48
+ </serial>
49
+ <console type='pty' tty='/dev/pts/1'>
50
+ <source path='/dev/pts/1'/>
51
+ <target type='serial' port='0'/>
52
+ <alias name='serial0'/>
53
+ </console>
54
+ <input type='mouse' bus='ps2'/>
55
+ <graphics type='vnc' port='5900' autoport='no' listen='0.0.0.0'>
56
+ <listen type='address' address='0.0.0.0'/>
57
+ </graphics>
58
+ <sound model='ich6'>
59
+ <alias name='sound0'/>
60
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
61
+ </sound>
62
+ <video>
63
+ <model type='cirrus' vram='9216' heads='1'/>
64
+ <alias name='video0'/>
65
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
66
+ </video>
67
+ <memballoon model='virtio'>
68
+ <alias name='balloon0'/>
69
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
70
+ </memballoon>
71
+ </devices>
72
+ <seclabel type='none'/>
73
+ </domain>
74
+
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+ require "vagrant-kvm/config"
3
+
4
+ describe VagrantPlugins::ProviderKvm::Config do
5
+ describe "#machine_type" do
6
+ it "defaults to pc-1.2" do
7
+ should_default(:machine_type, "pc-1.2")
8
+ end
9
+ end
10
+
11
+ describe "#vnc_port" do
12
+ it "defaults to -1" do
13
+ should_default(:vnc_port, -1)
14
+ end
15
+ end
16
+
17
+ describe "#vnc_password" do
18
+ it "defaults to nil" do
19
+ should_default(:vnc_password, nil)
20
+ end
21
+ end
22
+
23
+ describe "#network_model" do
24
+ it "defaults to 'virtio'" do
25
+ should_default(:network_model, 'virtio')
26
+ end
27
+ end
28
+
29
+ describe "#video_model" do
30
+ it "defaults to 'virtio'" do
31
+ should_default(:video_model, 'cirrus')
32
+ end
33
+ end
34
+
35
+ describe "#image_mode" do
36
+ it "sets image_backing to false if clone" do
37
+ subject.image_mode = 'clone'
38
+ subject.finalize!
39
+ subject.image_backing.should be_false
40
+ end
41
+
42
+ it "sets image_backing to true if cow" do
43
+ subject.image_mode = 'cow'
44
+ subject.finalize!
45
+ subject.image_backing.should be_true
46
+ end
47
+ end
48
+
49
+ private
50
+ def should_default(field, default_value)
51
+ instance = described_class.new
52
+ instance.send(field).should == described_class::UNSET_VALUE
53
+ instance.finalize!
54
+ instance.send(field).should == default_value
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module VagrantPlugins
4
+ module ProviderKvm
5
+ module Driver
6
+ describe Driver do
7
+ let(:xml) { test_file "box.xml" }
8
+ let(:volume_name) { "" }
9
+
10
+ before do
11
+ described_class.any_instance.stub(:load_kvm_module!) { true }
12
+ end
13
+
14
+ describe "#import" do
15
+ # FIXME All of these required stubs are a symptom of bad design in the
16
+ # driver class.
17
+ let(:volume) { double(path: "foo") }
18
+ let(:pool) { double(refresh: nil, lookup_volume_by_name: volume) }
19
+ let(:domain) { double(uuid: "abc") }
20
+ let(:conn) { double(version: 1000000000,
21
+ lookup_storage_pool_by_name: pool,
22
+ define_domain_xml: domain) }
23
+ subject do
24
+ described_class.new(nil, conn)
25
+ end
26
+
27
+ it "does not raise exception" do
28
+ expect do
29
+ subject.import(xml, volume_name)
30
+ end.to_not raise_exception
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ module VagrantPlugins::ProviderKvm::Errors
4
+ describe VagrantPlugins::ProviderKvm::Errors do
5
+ it "has translations for all errors" do
6
+ # Load the translations
7
+ VagrantPlugins::ProviderKvm::Plugin.setup_i18n
8
+
9
+ descendants = ObjectSpace.each_object(Class).select { |klass| klass < VagrantKVMError }
10
+
11
+ all_interpolations = {
12
+ required: "",
13
+ cause: "",
14
+ actual: "",
15
+ cmd: "",
16
+ res: "",
17
+ }
18
+
19
+ descendants.each do |klass|
20
+ msg = klass.new(all_interpolations).message
21
+ msg.should_not include("translation missing")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe VagrantPlugins::ProviderKvm::Util::NetworkDefinition do
4
+ let(:name) { 'vagrant' }
5
+ let(:xml) do
6
+ <<-XML
7
+ <network connections='1'>
8
+ <name>vagrant</name>
9
+ <uuid>0b9deaff-7665-d129-02e9-0f0a74054f87</uuid>
10
+ <forward mode='nat'/>
11
+ <bridge name='virbr1' stp='on' delay='0' />
12
+ <mac address='52:54:00:DE:20:0C'/>
13
+ <domain name='vagrant.local'/>
14
+ <ip address='192.168.123.1' netmask='255.255.255.0'>
15
+ <dhcp>
16
+ <range start='192.168.123.100' end='192.168.123.200' />
17
+ <host mac='00:69:0d:c2:52:f7' name='default' ip='192.168.123.10' />
18
+ </dhcp>
19
+ </ip>
20
+ </network>
21
+ XML
22
+ end
23
+
24
+ let(:definition) { described_class.new(name, xml) }
25
+ subject { definition }
26
+
27
+ it "should set the attributes properly" do
28
+ subject.get(:forward).should == 'nat'
29
+ subject.get(:domain_name).should == 'vagrant.local'
30
+ subject.get(:base_ip).should == '192.168.123.1'
31
+ subject.get(:netmask).should == '255.255.255.0'
32
+ subject.get(:range).should == { :start => "192.168.123.100", :end => "192.168.123.200"}
33
+ subject.get(:hosts).should == [ {
34
+ :mac => '00:69:0d:c2:52:f7',
35
+ :name => 'default',
36
+ :ip => '192.168.123.10',
37
+ }]
38
+ end
39
+
40
+
41
+ describe "#==" do
42
+ it "returns true if and only if all attributes are equal" do
43
+ def1 = described_class.new(name, xml)
44
+ def2 = described_class.new(name, xml)
45
+
46
+ def1.should == def2
47
+
48
+ def2.set(:netmask, '255.255.0.0')
49
+ def1.should_not == def2
50
+ end
51
+ end
52
+
53
+ describe "#as_xml" do
54
+ it "should be symetrical" do
55
+ def1 = described_class.new(name, subject.as_xml)
56
+ subject.should == def1
57
+ subject.as_xml.should == def1.as_xml
58
+ end
59
+ end
60
+ end