vagrant-kvm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +14 -0
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE +8 -0
  5. data/README.md +90 -0
  6. data/Rakefile +15 -0
  7. data/example_box/README.md +18 -0
  8. data/example_box/box.xml +78 -0
  9. data/example_box/metadata.json +3 -0
  10. data/lib/vagrant-kvm.rb +20 -0
  11. data/lib/vagrant-kvm/action.rb +268 -0
  12. data/lib/vagrant-kvm/action/boot.rb +22 -0
  13. data/lib/vagrant-kvm/action/check_box.rb +36 -0
  14. data/lib/vagrant-kvm/action/check_created.rb +21 -0
  15. data/lib/vagrant-kvm/action/check_kvm.rb +23 -0
  16. data/lib/vagrant-kvm/action/check_running.rb +21 -0
  17. data/lib/vagrant-kvm/action/created.rb +20 -0
  18. data/lib/vagrant-kvm/action/destroy.rb +19 -0
  19. data/lib/vagrant-kvm/action/destroy_confirm.rb +17 -0
  20. data/lib/vagrant-kvm/action/export.rb +57 -0
  21. data/lib/vagrant-kvm/action/forced_halt.rb +21 -0
  22. data/lib/vagrant-kvm/action/import.rb +54 -0
  23. data/lib/vagrant-kvm/action/init_storage_pool.rb +19 -0
  24. data/lib/vagrant-kvm/action/is_paused.rb +20 -0
  25. data/lib/vagrant-kvm/action/is_running.rb +20 -0
  26. data/lib/vagrant-kvm/action/is_saved.rb +20 -0
  27. data/lib/vagrant-kvm/action/match_mac_address.rb +21 -0
  28. data/lib/vagrant-kvm/action/message_not_created.rb +16 -0
  29. data/lib/vagrant-kvm/action/message_will_not_destroy.rb +17 -0
  30. data/lib/vagrant-kvm/action/network.rb +69 -0
  31. data/lib/vagrant-kvm/action/package.rb +20 -0
  32. data/lib/vagrant-kvm/action/package_vagrantfile.rb +31 -0
  33. data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +61 -0
  34. data/lib/vagrant-kvm/action/prune_nfs_exports.rb +20 -0
  35. data/lib/vagrant-kvm/action/resume.rb +25 -0
  36. data/lib/vagrant-kvm/action/setup_package_files.rb +51 -0
  37. data/lib/vagrant-kvm/action/share_folders.rb +76 -0
  38. data/lib/vagrant-kvm/action/suspend.rb +20 -0
  39. data/lib/vagrant-kvm/config.rb +31 -0
  40. data/lib/vagrant-kvm/driver/driver.rb +271 -0
  41. data/lib/vagrant-kvm/errors.rb +11 -0
  42. data/lib/vagrant-kvm/plugin.rb +73 -0
  43. data/lib/vagrant-kvm/provider.rb +104 -0
  44. data/lib/vagrant-kvm/util.rb +12 -0
  45. data/lib/vagrant-kvm/util/kvm_template_renderer.rb +20 -0
  46. data/lib/vagrant-kvm/util/network_definition.rb +106 -0
  47. data/lib/vagrant-kvm/util/vm_definition.rb +192 -0
  48. data/lib/vagrant-kvm/version.rb +5 -0
  49. data/locales/en.yml +4 -0
  50. data/templates/libvirt_domain.erb +64 -0
  51. data/vagrant-kvm.gemspec +58 -0
  52. metadata +191 -0
@@ -0,0 +1,14 @@
1
+ # OS-specific
2
+ .DS_Store
3
+
4
+ # Bundler/Rubygems
5
+ *.gem
6
+ .bundle
7
+ pkg/*
8
+ tags
9
+ Gemfile.lock
10
+
11
+ # Vagrant
12
+ .vagrant
13
+ Vagrantfile
14
+ !example_box/Vagrantfile
@@ -0,0 +1,3 @@
1
+ # 0.1.0 (April 2, 2013)
2
+
3
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ # We depend on Vagrant for development, but we don't add it as a
7
+ # gem dependency because we expect to be installed within the
8
+ # Vagrant environment itself using `vagrant plugin`.
9
+ gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2013 Alex Drahon
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ HE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,90 @@
1
+ # Vagrant KVM Provider
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) 1.1+ plugin that adds a KVM
4
+ provider to Vagrant, allowing Vagrant to control and provision KVM/QEMU VM.
5
+
6
+ **NOTE:** This plugin requires Vagrant 1.1+
7
+ **NOTE:** This plugin requires QEMU 1.2+, it has only been tested on Fedora 18
8
+ at the moment.
9
+
10
+ ## Features/Limitations
11
+
12
+ * Provides the same workflow as the Vagrant VirtualBox provider.
13
+ * Uses VirtualBox boxes almost seamlessly (see below).
14
+ * Uses NFS for sync folders
15
+ * Only works with 1 VM per Vagrantfile for now
16
+ * Only works with private networking for now
17
+
18
+ ## Usage
19
+
20
+ Install using standard Vagrant 1.1+ plugin installation methods. After
21
+ installing, `vagrant up` and specify the `kvm` provider. An example is
22
+ shown below.
23
+
24
+ ```
25
+ $ vagrant plugin install vagrant-kvm
26
+ ...
27
+ $ vagrant up --provider=aws
28
+ ...
29
+ ```
30
+
31
+ Of course prior to doing this, you'll need to obtain a KVM-compatible
32
+ box file for Vagrant.
33
+
34
+ ## Quick Start
35
+
36
+ After installing the plugin (instructions above), the quickest way to get
37
+ started is to use a VirtualBox box and change the provider manually. For
38
+ example:
39
+
40
+ ```
41
+ $ vagrant box add precise32 http://files.vagrantup.com/precise32.box
42
+ ...
43
+ ```
44
+
45
+ The box will be installed in `~/.vagrant.d/boxes/precise32/virtualbox`, you
46
+ need to change this to `~/.vagrant.d/boxes/precise32/kvm` and change the
47
+ provider in `metadata.json`. For example:
48
+
49
+ ```
50
+ mv ~/.vagrant.d/boxes/precise32/virtualbox ~/.vagrant.d/boxes/precise32/kvm
51
+ cat <<EOF >~/.vagrant.d/boxes/precise32/kvm/metadata.json
52
+ > {"provider": "kvm"}
53
+ > EOF
54
+ ```
55
+
56
+ You will need a private network specifying an IP address in your Vagrantfile,
57
+ the minimum Vagrantfile would then be:
58
+
59
+ ```
60
+ Vagrant.configure("2") do |config|
61
+ config.vm.box = "precise32"
62
+ config.vm.network :private_network, ip: "192.168.192.10"
63
+ end
64
+ ```
65
+
66
+ And then run `vagrant up --provider=kvm`.
67
+
68
+ ## Box Format
69
+
70
+ Vagrant providers each require a custom provider-specific box format.
71
+ This folder shows the example contents of a box for the `kvm` provider.
72
+
73
+ There are two box formats for the `kvm` provider:
74
+ 1. VirtualBox box - you need to change the provider to `kvm` in the
75
+ `metadata.json` file, the box will be converted on the fly.
76
+ 2. "Native" box - you need a box.xml file (libvirt domain format) and a raw
77
+ image file (you can convert a .vmdk with qemu-img)
78
+
79
+ To turn this into a native box, you need to create a vagrant image and do:
80
+
81
+ ```
82
+ $ tar cvzf kvm.box ./metadata.json ./Vagrantfile ./box.xml ./box-disk1.img
83
+ ```
84
+
85
+ You need a base MAC address and a private network like in the example.
86
+
87
+
88
+ ## Configuration
89
+
90
+ There are no provider-specific parameters at the moment.
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,18 @@
1
+ # Vagrant KVM Example Box
2
+
3
+ Vagrant providers each require a custom provider-specific box format.
4
+ This folder shows the example contents of a box for the `kvm` provider.
5
+
6
+ There are two box formats for the `kvm` provider:
7
+ 1. VirtualBox box - you need to change the provider to `kvm` in the
8
+ `metadata.json` file, the box will be converted on the fly.
9
+ 2. "Native" box - you need a box.xml file (libvirt domain format) and a raw
10
+ image file (you can convert a .vmdk with qemu-img)
11
+
12
+ To turn this into a native box, you need to create a vagrant image and do:
13
+
14
+ ```
15
+ $ tar cvzf kvm.box ./metadata.json ./Vagrantfile ./box.xml ./box-disk1.img
16
+ ```
17
+
18
+ You need a base MAC address and a private network like in the example.
@@ -0,0 +1,78 @@
1
+ <domain type='kvm'>
2
+ <name>precise32</name>
3
+ <memory unit='KiB'>393216</memory>
4
+ <currentMemory unit='KiB'>393216</currentMemory>
5
+ <vcpu placement='static'>1</vcpu>
6
+ <os>
7
+ <type arch='i686' 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/qemu-kvm</emulator>
21
+ <disk type='file' device='disk'>
22
+ <driver name='qemu' type='raw'/>
23
+ <source file='box-disk1.img'/>
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:12:96:98'/>
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/6'/>
46
+ <target port='0'/>
47
+ <alias name='serial0'/>
48
+ </serial>
49
+ <console type='pty' tty='/dev/pts/6'>
50
+ <source path='/dev/pts/6'/>
51
+ <target type='serial' port='0'/>
52
+ <alias name='serial0'/>
53
+ </console>
54
+ <channel type='spicevmc'>
55
+ <target type='virtio' name='com.redhat.spice.0'/>
56
+ <alias name='channel0'/>
57
+ <address type='virtio-serial' controller='0' bus='0' port='1'/>
58
+ </channel>
59
+ <input type='mouse' bus='ps2'/>
60
+ <graphics type='spice' port='5900' autoport='yes' listen='127.0.0.1'>
61
+ <listen type='address' address='127.0.0.1'/>
62
+ </graphics>
63
+ <sound model='ich6'>
64
+ <alias name='sound0'/>
65
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
66
+ </sound>
67
+ <video>
68
+ <model type='cirrus' vram='9216' heads='1'/>
69
+ <alias name='video0'/>
70
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
71
+ </video>
72
+ <memballoon model='virtio'>
73
+ <alias name='balloon0'/>
74
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
75
+ </memballoon>
76
+ </devices>
77
+ </domain>
78
+
@@ -0,0 +1,3 @@
1
+ {
2
+ "provider": "kvm"
3
+ }
@@ -0,0 +1,20 @@
1
+ require "pathname"
2
+
3
+ require "vagrant-kvm/plugin"
4
+
5
+ module VagrantPlugins
6
+ module ProviderKvm
7
+ lib_path = Pathname.new(File.expand_path("../vagrant-kvm", __FILE__))
8
+ autoload :Action, lib_path.join("action")
9
+ autoload :Driver, lib_path.join("driver/driver")
10
+ autoload :Errors, lib_path.join("errors")
11
+ autoload :Util, lib_path.join("util")
12
+
13
+ # This returns the path to the source of this plugin.
14
+ #
15
+ # @return [Pathname]
16
+ def self.source_root
17
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,268 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module ProviderKvm
7
+ module Action
8
+ # Include the built-in modules so that we can use them as top-level
9
+ # things.
10
+ include Vagrant::Action::Builtin
11
+
12
+ # This action boots the VM, assuming the VM is in a state that requires
13
+ # a bootup (i.e. not saved).
14
+ def self.action_boot
15
+ Vagrant::Action::Builder.new.tap do |b|
16
+ b.use Network
17
+ b.use Provision
18
+ b.use PruneNFSExports
19
+ b.use NFS
20
+ b.use PrepareNFSSettings
21
+ b.use ShareFolders
22
+ b.use SetHostname
23
+ #b.use Customize
24
+ b.use Boot
25
+ end
26
+ end
27
+
28
+ # This is the action that is primarily responsible for completely
29
+ # freeing the resources of the underlying virtual machine.
30
+ def self.action_destroy
31
+ Vagrant::Action::Builder.new.tap do |b|
32
+ b.use CheckKvm
33
+ b.use Call, Created do |env1, b2|
34
+ if !env1[:result]
35
+ b2.use MessageNotCreated
36
+ next
37
+ end
38
+
39
+ b2.use Call, DestroyConfirm do |env2, b3|
40
+ if env2[:result]
41
+ b3.use ConfigValidate
42
+ b3.use EnvSet, :force_halt => true
43
+ b3.use action_halt
44
+ b3.use PruneNFSExports
45
+ b3.use Destroy
46
+ else
47
+ b3.use MessageWillNotDestroy
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ # This is the action that is primarily responsible for halting
55
+ # the virtual machine, gracefully or by force.
56
+ def self.action_halt
57
+ Vagrant::Action::Builder.new.tap do |b|
58
+ b.use CheckKvm
59
+ b.use Call, Created do |env, b2|
60
+ if env[:result]
61
+ b2.use Call, IsPaused do |env2, b3|
62
+ next if !env2[:result]
63
+ b3.use Resume
64
+ end
65
+
66
+ b2.use Call, GracefulHalt, :poweroff, :running do |env2, b3|
67
+ if !env2[:result]
68
+ b3.use ForcedHalt
69
+ end
70
+ end
71
+ else
72
+ b2.use MessageNotCreated
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ # This action packages the virtual machine into a single box file.
79
+ def self.action_package
80
+ Vagrant::Action::Builder.new.tap do |b|
81
+ b.use CheckKvm
82
+ b.use Call, Created do |env1, b2|
83
+ if !env1[:result]
84
+ b2.use MessageNotCreated
85
+ next
86
+ end
87
+
88
+ b2.use SetupPackageFiles
89
+ b2.use action_halt
90
+ #b2.use Export
91
+ b2.use PackageVagrantfile
92
+ b2.use Package
93
+ end
94
+ end
95
+ end
96
+
97
+ # This action just runs the provisioners on the machine.
98
+ def self.action_provision
99
+ Vagrant::Action::Builder.new.tap do |b|
100
+ b.use CheckKvm
101
+ b.use ConfigValidate
102
+ b.use Call, Created do |env1, b2|
103
+ if !env1[:result]
104
+ b2.use MessageNotCreated
105
+ next
106
+ end
107
+
108
+ b2.use Call, IsRunning do |env2, b3|
109
+ if !env2[:result]
110
+ b3.use MessageNotRunning
111
+ next
112
+ end
113
+
114
+ b3.use Provision
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ # This action is responsible for reloading the machine, which
121
+ # brings it down, sucks in new configuration, and brings the
122
+ # machine back up with the new configuration.
123
+ def self.action_reload
124
+ Vagrant::Action::Builder.new.tap do |b|
125
+ b.use CheckKvm
126
+ b.use Call, Created do |env1, b2|
127
+ if !env1[:result]
128
+ b2.use MessageNotCreated
129
+ next
130
+ end
131
+
132
+ b2.use ConfigValidate
133
+ b2.use action_halt
134
+ b2.use action_start
135
+ end
136
+ end
137
+ end
138
+
139
+ # This is the action that is primarily responsible for resuming
140
+ # suspended machines.
141
+ def self.action_resume
142
+ Vagrant::Action::Builder.new.tap do |b|
143
+ b.use CheckKvm
144
+ b.use Call, Created do |env, b2|
145
+ if env[:result]
146
+ b2.use Resume
147
+ else
148
+ b2.use MessageNotCreated
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ # This is the action that will exec into an SSH shell.
155
+ def self.action_ssh
156
+ Vagrant::Action::Builder.new.tap do |b|
157
+ b.use CheckKvm
158
+ b.use CheckCreated
159
+ b.use CheckRunning
160
+ b.use SSHExec
161
+ end
162
+ end
163
+
164
+ # This is the action that will run a single SSH command.
165
+ def self.action_ssh_run
166
+ Vagrant::Action::Builder.new.tap do |b|
167
+ b.use CheckKvm
168
+ b.use CheckCreated
169
+ b.use CheckRunning
170
+ b.use SSHRun
171
+ end
172
+ end
173
+
174
+ # This action starts a VM, assuming it is already imported and exists.
175
+ # A precondition of this action is that the VM exists.
176
+ def self.action_start
177
+ Vagrant::Action::Builder.new.tap do |b|
178
+ b.use CheckKvm
179
+ b.use ConfigValidate
180
+ b.use Call, IsRunning do |env, b2|
181
+ # If the VM is running, then our work here is done, exit
182
+ next if env[:result]
183
+
184
+ b2.use Call, IsSaved do |env2, b3|
185
+ if env2[:result]
186
+ # The VM is saved, so just resume it
187
+ b3.use action_resume
188
+ next
189
+ end
190
+
191
+ b3.use Call, IsPaused do |env3, b4|
192
+ if env3[:result]
193
+ b4.use Resume
194
+ next
195
+ end
196
+
197
+ # The VM is not saved, so we must have to boot it up
198
+ # like normal. Boot!
199
+ b4.use action_boot
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ # This is the action that is primarily responsible for suspending
207
+ # the virtual machine.
208
+ def self.action_suspend
209
+ Vagrant::Action::Builder.new.tap do |b|
210
+ b.use CheckKvm
211
+ b.use Call, Created do |env, b2|
212
+ if env[:result]
213
+ b2.use Suspend
214
+ else
215
+ b2.use MessageNotCreated
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ # This action brings the machine up from nothing, including importing
222
+ # the box, configuring metadata, and booting.
223
+ def self.action_up
224
+ Vagrant::Action::Builder.new.tap do |b|
225
+ b.use CheckKvm
226
+ b.use ConfigValidate
227
+ b.use InitStoragePool
228
+ b.use Call, Created do |env, b2|
229
+ # If the VM is NOT created yet, then do the setup steps
230
+ if !env[:result]
231
+ b2.use CheckBox
232
+ b2.use Import
233
+ b2.use MatchMACAddress
234
+ end
235
+ end
236
+ b.use action_start
237
+ end
238
+ end
239
+
240
+ # The autoload farm
241
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
242
+ autoload :Boot, action_root.join("boot")
243
+ autoload :CheckBox, action_root.join("check_box")
244
+ autoload :CheckCreated, action_root.join("check_created")
245
+ autoload :CheckKvm, action_root.join("check_kvm")
246
+ autoload :CheckRunning, action_root.join("check_running")
247
+ autoload :Created, action_root.join("created")
248
+ autoload :Destroy, action_root.join("destroy")
249
+ autoload :DestroyConfirm, action_root.join("destroy_confirm")
250
+ autoload :ForcedHalt, action_root.join("forced_halt")
251
+ autoload :Import, action_root.join("import")
252
+ autoload :InitStoragePool, action_root.join("init_storage_pool")
253
+ autoload :IsPaused, action_root.join("is_paused")
254
+ autoload :IsRunning, action_root.join("is_running")
255
+ autoload :IsSaved, action_root.join("is_saved")
256
+ autoload :MatchMACAddress, action_root.join("match_mac_address")
257
+ autoload :MessageNotCreated, action_root.join("message_not_created")
258
+ autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
259
+ autoload :Network, action_root.join("network")
260
+ autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings")
261
+ autoload :PruneNFSExports, action_root.join("prune_nfs_exports")
262
+ autoload :Resume, action_root.join("resume")
263
+ autoload :SetupPackageFiles, action_root.join("setup_package_files")
264
+ autoload :ShareFolders, action_root.join("share_folders")
265
+ autoload :Suspend, action_root.join("suspend")
266
+ end
267
+ end
268
+ end