vagrant-zfs-box 0.0.1
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.
- data/lib/vagrant/downloaders/file.rb +22 -0
- data/lib/vagrant_init.rb +6 -0
- data/lib/vagrant_zfs.rb +14 -0
- data/lib/vagrant_zfs/actions.rb +4 -0
- data/lib/vagrant_zfs/actions/box/destroy.rb +23 -0
- data/lib/vagrant_zfs/actions/box/unpackage.rb +82 -0
- data/lib/vagrant_zfs/actions/vm/destroy.rb +38 -0
- data/lib/vagrant_zfs/actions/vm/import.rb +72 -0
- data/lib/vagrant_zfs/vboxmanage.rb +105 -0
- data/lib/vagrant_zfs/version.rb +3 -0
- data/lib/vagrant_zfs/zfs.rb +79 -0
- data/lib/vagrant_zfs/zfs_config.rb +3 -0
- metadata +57 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Vagrant
|
4
|
+
module Downloaders
|
5
|
+
# "Downloads" a file to a temporary file. Basically, this downloader
|
6
|
+
# simply does a file copy.
|
7
|
+
class File < Base
|
8
|
+
def self.match?(uri)
|
9
|
+
::File.file?(::File.expand_path(uri))
|
10
|
+
end
|
11
|
+
|
12
|
+
def prepare(source_url)
|
13
|
+
raise Errors::DownloaderFileDoesntExist if !::File.file?(::File.expand_path(source_url))
|
14
|
+
end
|
15
|
+
|
16
|
+
def download!(source_url, destination_file)
|
17
|
+
@ui.info I18n.t("vagrant.downloaders.file.download")
|
18
|
+
FileUtils.symlink(::File.expand_path(source_url), destination_file.path, :force => true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/vagrant_init.rb
ADDED
data/lib/vagrant_zfs.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'vagrant/action/builder'
|
3
|
+
require 'vagrant_zfs/zfs_config'
|
4
|
+
require 'vagrant_zfs/zfs'
|
5
|
+
require 'vagrant_zfs/vboxmanage'
|
6
|
+
require 'vagrant_zfs/actions'
|
7
|
+
require 'vagrant_zfs/version'
|
8
|
+
|
9
|
+
Vagrant.config_keys.register(:zfs) { ZfsConfig }
|
10
|
+
Vagrant.actions[:box_remove].replace(Vagrant::Action::Box::Destroy, VagrantZFS::Action::Box::Destroy)
|
11
|
+
Vagrant.actions[:box_add].replace(Vagrant::Action::Box::Unpackage, VagrantZFS::Action::Box::Unpackage)
|
12
|
+
Vagrant.actions[:up].delete(Vagrant::Action::VM::DefaultName)
|
13
|
+
Vagrant.actions[:up].replace(Vagrant::Action::VM::Import, VagrantZFS::Action::VM::Import)
|
14
|
+
Vagrant.actions[:destroy].replace(Vagrant::Action::VM::Destroy, VagrantZFS::Action::VM::Destroy)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module VagrantZFS
|
2
|
+
module Action
|
3
|
+
module Box
|
4
|
+
class Destroy
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@env = env
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
# Delete the existing box
|
12
|
+
env[:ui].info I18n.t("vagrant.actions.box.destroy.destroying", :name => env[:box_name])
|
13
|
+
VagrantZFS::ZFS.destroy_at env['box_directory'].to_s
|
14
|
+
|
15
|
+
# Reload the box collection
|
16
|
+
env[:box_collection].reload!
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'archive/tar/minitar'
|
2
|
+
module VagrantZFS
|
3
|
+
module Action
|
4
|
+
module Box
|
5
|
+
# Unpackages a downloaded box to a given directory with a given
|
6
|
+
# name.
|
7
|
+
#
|
8
|
+
# This variant will first create a ZFS directory from a configured
|
9
|
+
# zpool and then unpack the box into the directory.
|
10
|
+
#
|
11
|
+
# # Required Variables
|
12
|
+
#
|
13
|
+
# * `download.temp_path` - A location for the downloaded box. This is
|
14
|
+
# set by the {Download} action.
|
15
|
+
# * `box` - A {Vagrant::Box} object.
|
16
|
+
#
|
17
|
+
class Unpackage
|
18
|
+
attr_reader :box_directory
|
19
|
+
|
20
|
+
def initialize(app, env)
|
21
|
+
@logger = Log4r::Logger.new("vagrant_zfs::action::box::unpackage")
|
22
|
+
@app = app
|
23
|
+
@env = env
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
@env = env
|
28
|
+
|
29
|
+
setup_box_directory
|
30
|
+
decompress
|
31
|
+
|
32
|
+
@app.call(@env)
|
33
|
+
end
|
34
|
+
|
35
|
+
def recover(env)
|
36
|
+
if box_directory && File.directory?(box_directory)
|
37
|
+
VagrantZFS::ZFS.destroy env[:zfs_name]
|
38
|
+
FileUtils.rm_rf(box_directory)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def zpool
|
43
|
+
# Is the zpool specified in the Vagrantfile?
|
44
|
+
if @env['global_config'].zfs.zpool
|
45
|
+
@env['global_config'].zfs.zpool
|
46
|
+
else
|
47
|
+
# If we have only one zpool available, go with that.
|
48
|
+
zpools = VagrantZFS::ZFS.zpool_list
|
49
|
+
if zpools.length == 1
|
50
|
+
zpools.first
|
51
|
+
else
|
52
|
+
raise Exception, "zpool not specified and more than one available."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def setup_box_directory
|
58
|
+
if File.directory?(@env["box_directory"])
|
59
|
+
raise Errors::BoxAlreadyExists, :name => @env["box_name"]
|
60
|
+
end
|
61
|
+
|
62
|
+
puts "ZPOOL: #{zpool}"
|
63
|
+
@env[:zfs_name] = "#{zpool}/vagrant_#{@env["box_name"]}"
|
64
|
+
mountpoint = "#{@env["box_directory"]}"
|
65
|
+
VagrantZFS::ZFS.create @env[:zfs_name], mountpoint
|
66
|
+
@box_directory = @env["box_directory"]
|
67
|
+
end
|
68
|
+
|
69
|
+
def decompress
|
70
|
+
Dir.chdir(@env["box_directory"]) do
|
71
|
+
@env[:ui].info I18n.t("vagrant.actions.box.unpackage.extracting")
|
72
|
+
begin
|
73
|
+
Archive::Tar::Minitar.unpack(@env["download.temp_path"], @env["box_directory"].to_s)
|
74
|
+
rescue SystemCallError
|
75
|
+
raise Errors::BoxUnpackageFailure
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module VagrantZFS
|
2
|
+
module Action
|
3
|
+
module VM
|
4
|
+
class Destroy
|
5
|
+
def initialize(app, env)
|
6
|
+
@logger = Log4r::Logger.new("vagrant_zfs::action::vm::destroy")
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
env[:ui].info I18n.t("vagrant.actions.vm.destroy.destroying")
|
12
|
+
|
13
|
+
cmd = "VBoxManage showvminfo #{env[:vm].uuid}"
|
14
|
+
stdout, stderr, status = Open3.capture3(*cmd)
|
15
|
+
if status.success? and stderr.empty?
|
16
|
+
instance_name = stdout.lines.grep(/^Name:\s*(.+)/){$1}.first
|
17
|
+
else
|
18
|
+
raise Exception, "Could not find instance name for VM #{env[:vm].uuid}"
|
19
|
+
end
|
20
|
+
|
21
|
+
zpool = 'SSD'
|
22
|
+
fs = "#{zpool}/vagrant_#{env[:vm].config.vm.box}"
|
23
|
+
clonename = "#{fs}/#{instance_name}"
|
24
|
+
snapname = "#{fs}@#{instance_name}"
|
25
|
+
|
26
|
+
env[:vm].driver.delete
|
27
|
+
env[:vm].uuid = nil
|
28
|
+
|
29
|
+
VagrantZFS::ZFS.destroy clonename
|
30
|
+
VagrantZFS::ZFS.destroy snapname
|
31
|
+
|
32
|
+
|
33
|
+
@app.call(env)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module VagrantZFS
|
2
|
+
module Action
|
3
|
+
module VM
|
4
|
+
class Import
|
5
|
+
def initialize(app, env)
|
6
|
+
@logger = Log4r::Logger.new("vagrant_zfs::action::vm::import")
|
7
|
+
@env = env
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def find_basebox_filesystem
|
12
|
+
fs = VagrantZFS::ZFS.mounts.select do |mountpoint,fs|
|
13
|
+
mountpoint == @env[:vm].box.directory.to_s
|
14
|
+
end.first[1]
|
15
|
+
@logger.debug "Found base box filesystem: #{fs}"
|
16
|
+
fs
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(env)
|
20
|
+
env[:ui].info I18n.t("vagrant.actions.vm.import.importing", :name => env[:vm].box.name)
|
21
|
+
|
22
|
+
# Import the virtual machine
|
23
|
+
ovf_file = env[:vm].box.directory.join("box.ovf").to_s
|
24
|
+
|
25
|
+
fs = find_basebox_filesystem
|
26
|
+
|
27
|
+
instance_name = env[:root_path].basename.to_s + "_#{Time.now.to_i}"
|
28
|
+
env[:name] = instance_name
|
29
|
+
|
30
|
+
VagrantZFS::ZFS.snapshot fs, instance_name
|
31
|
+
|
32
|
+
user_home = ENV['HOME']
|
33
|
+
vagrant_home = "#{user_home}/.vagrant.d"
|
34
|
+
instance_root = vagrant_home + "/instances"
|
35
|
+
|
36
|
+
clonename = "#{fs}/#{instance_name}"
|
37
|
+
mountpoint = "#{instance_root}/#{instance_name}"
|
38
|
+
VagrantZFS::ZFS.clone! "#{fs}@#{instance_name}", clonename
|
39
|
+
VagrantZFS::ZFS.set_mountpoint clonename, mountpoint
|
40
|
+
|
41
|
+
hdd = instance_root + "/" + instance_name + "/box-disk1.vmdk"
|
42
|
+
|
43
|
+
env[:vm].uuid = VagrantZFS::VBoxManage.createvm instance_name, instance_root
|
44
|
+
|
45
|
+
VagrantZFS::VBoxManage.setup env[:vm].uuid, hdd
|
46
|
+
|
47
|
+
# # If we got interrupted, then the import could have been
|
48
|
+
# # interrupted and its not a big deal. Just return out.
|
49
|
+
# return if env[:interrupted]
|
50
|
+
|
51
|
+
# Flag as erroneous and return if import failed
|
52
|
+
raise Errors::VMImportFailure if !env[:vm].uuid
|
53
|
+
|
54
|
+
# # Import completed successfully. Continue the chain
|
55
|
+
@app.call(env)
|
56
|
+
end
|
57
|
+
|
58
|
+
def recover(env)
|
59
|
+
if env[:vm].created?
|
60
|
+
return if env["vagrant.error"].is_a?(Errors::VagrantError)
|
61
|
+
|
62
|
+
# Interrupted, destroy the VM. We note that we don't want to
|
63
|
+
# validate the configuration here.
|
64
|
+
destroy_env = env.clone
|
65
|
+
destroy_env[:validate] = false
|
66
|
+
env[:action_runner].run(:destroy, destroy_env)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'open3'
|
2
|
+
module VagrantZFS
|
3
|
+
class VBoxManage
|
4
|
+
def self.exec cmd
|
5
|
+
cmd = "VBoxManage " + cmd
|
6
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
7
|
+
|
8
|
+
if status.success? and stderr.empty?
|
9
|
+
return stdout
|
10
|
+
else
|
11
|
+
raise Exception, "VBoxManage Error: #{cmd}\n #{stdout}\n #{stderr}\n #{status}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.createvm instance_name, instance_root
|
16
|
+
cmd = "createvm --name #{instance_name} --register --basefolder #{instance_root}"
|
17
|
+
lines = self.exec(cmd).split(/\n/)
|
18
|
+
uuid = lines.grep(/^UUID:\s*([-0-9a-z]+)/){$1}.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.modifyvm uuid, arg
|
22
|
+
self.exec "modifyvm #{uuid} #{arg}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.add_nat uuid
|
26
|
+
self.modifyvm uuid, "--nic1 nat"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.cpus uuid, cpus
|
30
|
+
self.modifyvm uuid, "--cpus #{cpus}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.memory uuid, memory
|
34
|
+
self.modifyvm uuid, "--memory #{memory}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.gethduuid file
|
38
|
+
# I found the line number may be 23, but search 40 just to be sure.
|
39
|
+
cmd="head -n 40 #{file}|grep --text --byte-offset --max-count=1 ddb.uuid.image="
|
40
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
41
|
+
unless status.success? and stderr.empty?
|
42
|
+
raise Exception, "gethduuid Error: #{cmd}\n #{stdout}\n #{stderr}\n #{status}"
|
43
|
+
end
|
44
|
+
# UUID format is a string of hyphen-punctuated character groups of 8-4-4-4-12.
|
45
|
+
uuid = stdout.match(/ddb.uuid.image="(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})"/).captures.first
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.sethduuid_shell file
|
49
|
+
# I found the line number may be 23, but search 40 just to be sure.
|
50
|
+
cmd="head -n 40 #{file}|grep --text --byte-offset --max-count=1 ddb.uuid.image="
|
51
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
52
|
+
unless status.success? and stderr.empty?
|
53
|
+
raise Exception, "gethduuid Error: #{cmd}\n #{stdout}\n #{stderr}\n #{status}"
|
54
|
+
end
|
55
|
+
# The number before : is the byte offset number.
|
56
|
+
uuid_offset = stdout.split(':').first.to_i + 'ddb.uuid.image="'.length
|
57
|
+
uuid_length = 36
|
58
|
+
|
59
|
+
# Generate a new UUID
|
60
|
+
stdout, stderr, status = Open3.capture3("uuidgen")
|
61
|
+
unless status.success? and stderr.empty?
|
62
|
+
raise Exception, "gethduuid Error: #{cmd}\n #{stdout}\n #{stderr}\n #{status}"
|
63
|
+
end
|
64
|
+
new_uuid = stdout.chomp
|
65
|
+
|
66
|
+
# Edit the vmdk-file inplace.
|
67
|
+
cmd = "echo #{new_uuid} | dd of=#{file} seek=#{uuid_offset} bs=1 count=#{uuid_length} conv=notrunc"
|
68
|
+
`#{cmd}` ? new_uuid : nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.sethduuid file
|
72
|
+
self.exec "internalcommands sethduuid #{file}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.add_storagectl uuid
|
76
|
+
self.exec "storagectl #{uuid} --name 'SATA Controller' --add sata --controller IntelAHCI --sataportcount 4 --hostiocache on --bootable on"
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.add_disk uuid, hddfile
|
80
|
+
self.exec "storageattach #{uuid} --storagectl 'SATA Controller' --port 0 --type hdd --nonrotational on --medium #{hddfile}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.setup uuid, hddfile
|
84
|
+
uuid_pre = self.gethduuid(hddfile)
|
85
|
+
self.sethduuid hddfile
|
86
|
+
uuid_post = self.gethduuid(hddfile)
|
87
|
+
|
88
|
+
# Did self.sethduuid work?
|
89
|
+
unless uuid_pre != uuid_post
|
90
|
+
puts "VBoxManage internalcommands sethduuid did not work. Trying shell with dd"
|
91
|
+
self.sethduuid_shell hddfile
|
92
|
+
uuid_post = self.gethduuid(hddfile)
|
93
|
+
unless uuid_pre != uuid_post
|
94
|
+
puts "Did not succeed to sethduuid."
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
self.add_storagectl uuid
|
99
|
+
self.add_disk uuid, hddfile
|
100
|
+
self.add_nat uuid
|
101
|
+
self.cpus uuid, "1"
|
102
|
+
self.memory uuid, "512"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'open3'
|
2
|
+
module VagrantZFS
|
3
|
+
class ZFS
|
4
|
+
def self.exec cmd
|
5
|
+
cmd = "zfs " + cmd
|
6
|
+
stdout, stderr, status = Open3.capture3(cmd)
|
7
|
+
|
8
|
+
if status.success? and stderr.empty?
|
9
|
+
return stdout
|
10
|
+
else
|
11
|
+
raise Exception, "ZFS Error: #{cmd}\n #{stdout}\n #{stderr}\n #{status}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.zpool_list
|
16
|
+
`zpool list -H -o name`.split(/\n/)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create fs_name, mountpoint
|
20
|
+
cmd = "create -o mountpoint=#{mountpoint} #{fs_name}"
|
21
|
+
self.exec cmd
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.destroy fs_name
|
25
|
+
cmd = "destroy #{fs_name}"
|
26
|
+
self.exec cmd
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.destroy_at mountpoint
|
30
|
+
fs = VagrantZFS::ZFS.mounts.select do |mounted_at,fs|
|
31
|
+
mounted_at == mountpoint
|
32
|
+
end.first[1]
|
33
|
+
puts "Will destroy #{fs} mounted at #{mountpoint}"
|
34
|
+
self.destroy fs
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.mounts
|
38
|
+
cmd = "get -rHp -oname,value mountpoint"
|
39
|
+
lines = self.exec(cmd).split(/\n/)
|
40
|
+
mounts = lines.collect do |line|
|
41
|
+
fs, path = line.chomp.split(/\t/, 2)
|
42
|
+
[path, fs]
|
43
|
+
end
|
44
|
+
Hash[mounts]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.set_mountpoint fs_name, mountpoint
|
48
|
+
cmd = "set mountpoint=#{mountpoint} #{fs_name}"
|
49
|
+
self.exec cmd
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.snapshot(fsname, snapname)
|
53
|
+
#raise NotFound, "no such filesystem" if !exist?
|
54
|
+
#raise AlreadyExists, "Snapshot #{snapname} already exists" if ZFS("#{fsname}@#{snapname}").exist?
|
55
|
+
|
56
|
+
cmd = "snapshot #{fsname}@#{snapname}"
|
57
|
+
self.exec cmd
|
58
|
+
return "#{fsname}@#{snapname}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.snapshot(fsname, snapname, opts={})
|
62
|
+
#raise NotFound, "no such filesystem" if !exist?
|
63
|
+
#raise AlreadyExists, "Snapshot #{snapname} already exists" if ZFS("#{fsname}@#{snapname}").exist?
|
64
|
+
|
65
|
+
cmd = "snapshot #{fsname}@#{snapname}"
|
66
|
+
self.exec cmd
|
67
|
+
return "#{fsname}@#{snapname}"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Clone snapshot
|
71
|
+
def self.clone!(snapname, clonename)
|
72
|
+
#clonename = clone.name if clone.is_a? ZFS
|
73
|
+
#raise AlreadyExists if ZFS(clone).exist?
|
74
|
+
|
75
|
+
cmd = "clone #{snapname} #{clonename}"
|
76
|
+
self.exec cmd
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-zfs-box
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lars Tobias Skjong-Borsting
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-18 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ZFS plugin that uses snapshots and clones to speed up box creation for
|
15
|
+
Vagrant 1.0
|
16
|
+
email: larstobi@relatime.no
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/vagrant/downloaders/file.rb
|
22
|
+
- lib/vagrant_init.rb
|
23
|
+
- lib/vagrant_zfs/zfs.rb
|
24
|
+
- lib/vagrant_zfs/version.rb
|
25
|
+
- lib/vagrant_zfs/actions/box/destroy.rb
|
26
|
+
- lib/vagrant_zfs/actions/box/unpackage.rb
|
27
|
+
- lib/vagrant_zfs/actions/vm/destroy.rb
|
28
|
+
- lib/vagrant_zfs/actions/vm/import.rb
|
29
|
+
- lib/vagrant_zfs/zfs_config.rb
|
30
|
+
- lib/vagrant_zfs/actions.rb
|
31
|
+
- lib/vagrant_zfs/vboxmanage.rb
|
32
|
+
- lib/vagrant_zfs.rb
|
33
|
+
homepage: http://rubygems.org/gems/vagrant-zfs-box
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.24
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: ZFS plugin for Vagrant 1.0
|
57
|
+
test_files: []
|