vagrant-mutate 0.3.2 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +12 -1
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +12 -8
- data/lib/vagrant-mutate/box/box.rb +12 -13
- data/lib/vagrant-mutate/box/kvm.rb +7 -9
- data/lib/vagrant-mutate/box/libvirt.rb +6 -8
- data/lib/vagrant-mutate/box/virtualbox.rb +49 -52
- data/lib/vagrant-mutate/box_loader.rb +151 -68
- data/lib/vagrant-mutate/converter/converter.rb +19 -22
- data/lib/vagrant-mutate/converter/kvm.rb +12 -16
- data/lib/vagrant-mutate/converter/libvirt.rb +2 -4
- data/lib/vagrant-mutate/errors.rb +7 -4
- data/lib/vagrant-mutate/mutate.rb +10 -10
- data/lib/vagrant-mutate/qemu.rb +25 -27
- data/lib/vagrant-mutate/version.rb +1 -1
- data/lib/vagrant-mutate.rb +0 -2
- data/locales/en.yml +5 -2
- data/test/test.rb +8 -8
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f11d1d281c5163c1fb94808679865f70fdc064e
|
4
|
+
data.tar.gz: eb2f7a13d0d995e1bfb4bd8118341c7a8e66222e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96f137bd296afdfbcc8c5c12ef19dc966bc73ebc291abd1e88c45e26e2292940a01f52b3263193197bbb16c368ac64ad1a761234d06909c996ebd7dbb0e6055c
|
7
|
+
data.tar.gz: d8ff920d3b9c5d818b0b57179bf74382cb5c02972f2b609046e616edfee738447c07c57e5452742d863f9c4453c2a78d4344b9f68a3413d10699fffe7c41bf1d
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 1.0.0 (2015-05-20)
|
2
|
+
* Support versioned boxes (#51)
|
3
|
+
* Support boxes with slash in name (#52)
|
4
|
+
* Rename input provider option (#68)
|
5
|
+
* Allow hyphen in box name when loading from url (#70)
|
6
|
+
|
1
7
|
# 0.3.2 (2015-03-03)
|
2
8
|
* Specify qcow compat instead of using default (#59)
|
3
9
|
* Provide clearer error when qemu-img missing (#62)
|
data/Gemfile
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in vagrant-mutate.gemspec
|
4
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: "https://github.com/mitchellh/vagrant.git"
|
10
|
+
end
|
11
|
+
|
12
|
+
group :plugins do
|
13
|
+
gem "vagrant-mutate", path: "."
|
14
|
+
end
|
15
|
+
|
data/{LICENSE.txt → LICENSE}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -17,25 +17,23 @@ Throughout its development vagrant-mutate has been tested against the following
|
|
17
17
|
* [vagrant-kvm](https://github.com/adrahon/vagrant-kvm) 0.1.4
|
18
18
|
* [vagrant-libvirt](https://github.com/pradels/vagrant-libvirt) 0.0.11
|
19
19
|
|
20
|
-
Vagrant-mutate does not yet fully support [versioned boxes](http://docs.vagrantup.com/v2/boxes/versioning.html). It always assumes a box has the version *0*.
|
21
|
-
|
22
20
|
## Installation
|
23
21
|
|
24
|
-
### qemu-img
|
22
|
+
### qemu-img and libvirt development
|
25
23
|
|
26
|
-
First, you must install [qemu-img](http://wiki.qemu.org/Main_Page). Information on supported versions is listed at [QEMU Version Compatibility](https://github.com/sciurus/vagrant-mutate/wiki/QEMU-Version-Compatibility).
|
24
|
+
First, you must install [qemu-img](http://wiki.qemu.org/Main_Page) and the libvirt development libraries. Information on supported versions is listed at [QEMU Version Compatibility](https://github.com/sciurus/vagrant-mutate/wiki/QEMU-Version-Compatibility).
|
27
25
|
|
28
26
|
#### Debian and derivatives
|
29
27
|
|
30
|
-
apt-get install qemu-utils
|
28
|
+
apt-get install qemu-utils libvirt-dev
|
31
29
|
|
32
30
|
#### Red Hat and derivatives
|
33
31
|
|
34
|
-
yum install qemu-img
|
32
|
+
yum install qemu-img libvirt-devel
|
35
33
|
|
36
34
|
#### OS X
|
37
35
|
|
38
|
-
QEMU
|
36
|
+
QEMU and libvirt are available from [homebrew](http://brew.sh/)
|
39
37
|
|
40
38
|
#### Windows
|
41
39
|
|
@@ -67,7 +65,13 @@ Or if you had already added the box to vagrant and now want to use it with libvi
|
|
67
65
|
|
68
66
|
vagrant mutate precise32 libvirt
|
69
67
|
|
70
|
-
|
68
|
+
The latter syntax works for boxes you added from Vagrant Cloud or Atlas too. If you have installed multiple versions of these boxes, vagrant-mutate will always use the latest one.
|
69
|
+
|
70
|
+
$ vagrant box list
|
71
|
+
hashicorp/precise64 (virtualbox, 1.1.0)
|
72
|
+
$ vagrant mutate hashicorp/precise32 libvirt
|
73
|
+
|
74
|
+
If you have a box for multiple providers, you must specify the provider to use for input using the *--input-provider* option, e.g.
|
71
75
|
|
72
76
|
$ vagrant box list
|
73
77
|
precise32 (kvm)
|
@@ -1,22 +1,22 @@
|
|
1
1
|
module VagrantMutate
|
2
2
|
module Box
|
3
3
|
class Box
|
4
|
+
attr_reader :name, :dir, :version, :provider_name, :supported_input, :supported_output, :image_format, :image_name
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@logger = Log4r::Logger.new('vagrant::mutate')
|
6
|
+
def initialize(env, name, version, dir)
|
7
|
+
@env = env
|
8
|
+
@name = name
|
9
|
+
@dir = dir
|
10
|
+
@version = version
|
11
|
+
@logger = Log4r::Logger.new('vagrant::mutate')
|
12
12
|
end
|
13
13
|
|
14
14
|
def virtual_size
|
15
|
-
extract_from_qemu_info(
|
15
|
+
extract_from_qemu_info(/(\d+) bytes/)
|
16
16
|
end
|
17
17
|
|
18
18
|
def verify_format
|
19
|
-
format_found = extract_from_qemu_info(
|
19
|
+
format_found = extract_from_qemu_info(/file format: (\w+)/)
|
20
20
|
unless format_found == @image_format
|
21
21
|
@env.ui.warn "Expected input image format to be #{@image_format} but "\
|
22
22
|
"it is #{format_found}. Attempting conversion anyway."
|
@@ -24,16 +24,15 @@ module VagrantMutate
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def extract_from_qemu_info(expression)
|
27
|
-
input_file = File.join(
|
27
|
+
input_file = File.join(@dir, image_name)
|
28
28
|
info = `qemu-img info #{input_file}`
|
29
29
|
@logger.debug "qemu-img info output\n#{info}"
|
30
30
|
if info =~ expression
|
31
|
-
return
|
31
|
+
return Regexp.last_match[1]
|
32
32
|
else
|
33
|
-
|
33
|
+
fail Errors::QemuInfoFailed
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
37
36
|
end
|
38
37
|
end
|
39
38
|
end
|
@@ -4,8 +4,7 @@ require 'rexml/document'
|
|
4
4
|
module VagrantMutate
|
5
5
|
module Box
|
6
6
|
class Kvm < Box
|
7
|
-
|
8
|
-
def initialize(env, name, dir)
|
7
|
+
def initialize(env, name, version, dir)
|
9
8
|
super
|
10
9
|
@provider_name = 'kvm'
|
11
10
|
@supported_input = true
|
@@ -14,20 +13,19 @@ module VagrantMutate
|
|
14
13
|
@image_name = 'box-disk1.img'
|
15
14
|
end
|
16
15
|
|
17
|
-
# TODO implement these methods
|
18
|
-
#
|
19
|
-
#
|
16
|
+
# TODO: implement these methods
|
17
|
+
# architecture, mac_address, cpus, memory
|
18
|
+
# to support converting to providers besides libvirt
|
20
19
|
|
21
20
|
def disk_interface
|
22
|
-
domain_file = File.join(
|
21
|
+
domain_file = File.join(@dir, 'box.xml')
|
23
22
|
begin
|
24
|
-
domain = REXML::Document.new(
|
23
|
+
domain = REXML::Document.new(File.read(domain_file))
|
25
24
|
domain.elements['/domain/devices/disk/target'].attributes['bus']
|
26
25
|
rescue => e
|
27
|
-
raise Errors::BoxAttributeError, :
|
26
|
+
raise Errors::BoxAttributeError, error_message: e.message
|
28
27
|
end
|
29
28
|
end
|
30
|
-
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
@@ -3,8 +3,7 @@ require_relative 'box'
|
|
3
3
|
module VagrantMutate
|
4
4
|
module Box
|
5
5
|
class Libvirt < Box
|
6
|
-
|
7
|
-
def initialize(env, name, dir)
|
6
|
+
def initialize(env, name, version, dir)
|
8
7
|
super
|
9
8
|
@provider_name = 'libvirt'
|
10
9
|
@supported_input = true
|
@@ -18,7 +17,7 @@ module VagrantMutate
|
|
18
17
|
# we just generate sane values
|
19
18
|
|
20
19
|
def architecture
|
21
|
-
|
20
|
+
'x86_64'
|
22
21
|
end
|
23
22
|
|
24
23
|
# kvm prefix is 52:54:00
|
@@ -27,21 +26,20 @@ module VagrantMutate
|
|
27
26
|
octets = 3.times.map { rand(255).to_s(16) }
|
28
27
|
@mac = "525400#{octets[0]}#{octets[1]}#{octets[2]}"
|
29
28
|
end
|
30
|
-
|
29
|
+
@mac
|
31
30
|
end
|
32
31
|
|
33
32
|
def cpus
|
34
|
-
|
33
|
+
1
|
35
34
|
end
|
36
35
|
|
37
36
|
def memory
|
38
|
-
|
37
|
+
536_870_912
|
39
38
|
end
|
40
39
|
|
41
40
|
def disk_interface
|
42
|
-
|
41
|
+
'virtio'
|
43
42
|
end
|
44
|
-
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require 'rexml/document'
|
2
2
|
require_relative 'box'
|
3
3
|
|
4
4
|
module VagrantMutate
|
5
5
|
module Box
|
6
6
|
class Virtualbox < Box
|
7
|
-
|
8
|
-
def initialize(env, name, dir)
|
7
|
+
def initialize(env, name, version, dir)
|
9
8
|
super
|
10
|
-
@provider_name
|
9
|
+
@provider_name = 'virtualbox'
|
11
10
|
@supported_input = true
|
12
11
|
@supported_output = false
|
13
12
|
@image_format = 'vmdk'
|
@@ -25,14 +24,14 @@ module VagrantMutate
|
|
25
24
|
# because we try to run in 32-bit vm.
|
26
25
|
# in contrast, running 32-bit box in a 64-bit vm should work.
|
27
26
|
def architecture
|
28
|
-
|
27
|
+
'x86_64'
|
29
28
|
end
|
30
29
|
|
31
30
|
# use mac from the first enabled nic
|
32
31
|
def mac_address
|
33
32
|
mac = nil
|
34
33
|
|
35
|
-
ovf.elements.each(
|
34
|
+
ovf.elements.each('//vbox:Machine/Hardware//Adapter') do |ele|
|
36
35
|
if ele.attributes['enabled'] == 'true'
|
37
36
|
mac = ele.attributes['MACAddress']
|
38
37
|
break
|
@@ -42,64 +41,64 @@ module VagrantMutate
|
|
42
41
|
if mac
|
43
42
|
return mac
|
44
43
|
else
|
45
|
-
|
44
|
+
fail Errors::BoxAttributeError, error_message: 'Could not determine mac address'
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
49
48
|
def cpus
|
50
49
|
cpu_count = nil
|
51
50
|
|
52
|
-
ovf.elements.each(
|
53
|
-
if device.elements[
|
54
|
-
cpu_count = device.elements[
|
51
|
+
ovf.elements.each('//VirtualHardwareSection/Item') do |device|
|
52
|
+
if device.elements['rasd:ResourceType'].text == '3'
|
53
|
+
cpu_count = device.elements['rasd:VirtualQuantity'].text
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
58
57
|
if cpu_count
|
59
58
|
return cpu_count
|
60
59
|
else
|
61
|
-
|
60
|
+
fail Errors::BoxAttributeError, error_message: 'Could not determine number of CPUs'
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
65
64
|
def memory
|
66
65
|
memory_in_bytes = nil
|
67
66
|
|
68
|
-
ovf.elements.each(
|
69
|
-
if device.elements[
|
70
|
-
memory_in_bytes = size_in_bytes(device.elements[
|
71
|
-
|
67
|
+
ovf.elements.each('//VirtualHardwareSection/Item') do |device|
|
68
|
+
if device.elements['rasd:ResourceType'].text == '4'
|
69
|
+
memory_in_bytes = size_in_bytes(device.elements['rasd:VirtualQuantity'].text,
|
70
|
+
device.elements['rasd:AllocationUnits'].text)
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
75
74
|
if memory_in_bytes
|
76
75
|
return memory_in_bytes
|
77
76
|
else
|
78
|
-
|
77
|
+
fail Errors::BoxAttributeError, error_message: 'Could not determine amount of memory'
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
82
81
|
def disk_interface
|
83
82
|
controller_type = {}
|
84
83
|
controller_used_by_disk = nil
|
85
|
-
ovf.elements.each(
|
84
|
+
ovf.elements.each('//VirtualHardwareSection/Item') do |device|
|
86
85
|
# when we find a controller, store its ID and type
|
87
86
|
# when we find a disk, store the ID of the controller it is connected to
|
88
|
-
case device.elements[
|
89
|
-
when
|
90
|
-
|
91
|
-
when
|
92
|
-
controller_type[device.elements[
|
93
|
-
when
|
94
|
-
controller_type[device.elements[
|
95
|
-
when
|
96
|
-
controller_used_by_disk = device.elements[
|
87
|
+
case device.elements['rasd:ResourceType'].text
|
88
|
+
when '5'
|
89
|
+
controller_type[device.elements['rasd:InstanceID'].text] = 'ide'
|
90
|
+
when '6'
|
91
|
+
controller_type[device.elements['rasd:InstanceID'].text] = 'scsi'
|
92
|
+
when '20'
|
93
|
+
controller_type[device.elements['rasd:InstanceID'].text] = 'sata'
|
94
|
+
when '17'
|
95
|
+
controller_used_by_disk = device.elements['rasd:Parent'].text
|
97
96
|
end
|
98
97
|
end
|
99
98
|
if controller_used_by_disk and controller_type[controller_used_by_disk]
|
100
99
|
return controller_type[controller_used_by_disk]
|
101
100
|
else
|
102
|
-
|
101
|
+
fail Errors::BoxAttributeError, error_message: 'Could not determine disk interface'
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
@@ -110,11 +109,11 @@ module VagrantMutate
|
|
110
109
|
return @ovf
|
111
110
|
end
|
112
111
|
|
113
|
-
ovf_file = File.join(
|
112
|
+
ovf_file = File.join(@dir, 'box.ovf')
|
114
113
|
begin
|
115
|
-
@ovf = REXML::Document.new(
|
114
|
+
@ovf = REXML::Document.new(File.read(ovf_file))
|
116
115
|
rescue => e
|
117
|
-
raise Errors::BoxAttributeError, :
|
116
|
+
raise Errors::BoxAttributeError, error_message: e.message
|
118
117
|
end
|
119
118
|
end
|
120
119
|
|
@@ -122,40 +121,38 @@ module VagrantMutate
|
|
122
121
|
# returns quantity in bytes
|
123
122
|
# mib = true to use mebibytes, etc
|
124
123
|
# defaults to false because ovf MB != megabytes
|
125
|
-
def size_in_bytes(qty, unit, mib=false)
|
124
|
+
def size_in_bytes(qty, unit, mib = false)
|
126
125
|
qty = qty.to_i
|
127
126
|
unit = unit.downcase
|
128
|
-
|
127
|
+
unless mib
|
129
128
|
case unit
|
130
|
-
when
|
131
|
-
unit =
|
132
|
-
when
|
133
|
-
unit =
|
134
|
-
when
|
135
|
-
unit =
|
129
|
+
when 'kb', 'kilobytes'
|
130
|
+
unit = 'kib'
|
131
|
+
when 'mb', 'megabytes'
|
132
|
+
unit = 'mib'
|
133
|
+
when 'gb', 'gigabytes'
|
134
|
+
unit = 'gib'
|
136
135
|
end
|
137
136
|
end
|
138
137
|
case unit
|
139
|
-
when
|
138
|
+
when 'b', 'bytes'
|
140
139
|
qty
|
141
|
-
when
|
140
|
+
when 'kb', 'kilobytes'
|
142
141
|
(qty * 1000)
|
143
|
-
when
|
142
|
+
when 'kib', 'kibibytes'
|
144
143
|
(qty * 1024)
|
145
|
-
when
|
146
|
-
(qty *
|
147
|
-
when
|
148
|
-
(qty *
|
149
|
-
when
|
150
|
-
(qty *
|
151
|
-
when
|
152
|
-
(qty *
|
144
|
+
when 'mb', 'megabytes'
|
145
|
+
(qty * 1_000_000)
|
146
|
+
when 'm', 'mib', 'mebibytes'
|
147
|
+
(qty * 1_048_576)
|
148
|
+
when 'gb', 'gigabytes'
|
149
|
+
(qty * 1_000_000_000)
|
150
|
+
when 'g', 'gib', 'gibibytes'
|
151
|
+
(qty * 1_073_741_824)
|
153
152
|
else
|
154
|
-
|
153
|
+
fail ArgumentError, "Unknown unit #{unit}"
|
155
154
|
end
|
156
155
|
end
|
157
|
-
|
158
156
|
end
|
159
|
-
|
160
157
|
end
|
161
158
|
end
|
@@ -1,45 +1,45 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'json'
|
3
3
|
require 'uri'
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require 'vagrant/util/subprocess'
|
5
|
+
require 'vagrant/util/downloader'
|
6
|
+
require 'vagrant/box'
|
7
|
+
require 'vagrant/box_metadata'
|
6
8
|
|
7
9
|
module VagrantMutate
|
8
10
|
class BoxLoader
|
9
|
-
|
10
|
-
def initialize( env )
|
11
|
+
def initialize(env)
|
11
12
|
@env = env
|
12
13
|
@logger = Log4r::Logger.new('vagrant::mutate')
|
13
14
|
@tmp_files = []
|
14
15
|
end
|
15
16
|
|
16
|
-
def prepare_for_output(name, provider_name)
|
17
|
-
@logger.info "Preparing #{name} for output as #{provider_name}"
|
18
|
-
|
19
|
-
|
17
|
+
def prepare_for_output(name, provider_name, version)
|
18
|
+
@logger.info "Preparing #{name} for output as #{provider_name} with version #{version}."
|
19
|
+
safe_name = sanitize_name(name)
|
20
|
+
dir = create_output_dir(safe_name, provider_name, version)
|
21
|
+
box = create_box(provider_name, name, version, dir)
|
20
22
|
|
21
23
|
if box.supported_output
|
22
24
|
return box
|
23
25
|
else
|
24
|
-
|
26
|
+
fail Errors::ProviderNotSupported, provider: provider_name, direction: 'output'
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
def load(box_arg, provider_name)
|
30
|
+
def load(box_arg, provider_name, input_version)
|
29
31
|
if box_arg =~ /:\/\//
|
30
32
|
box = load_from_url(box_arg)
|
31
33
|
elsif File.file?(box_arg)
|
32
34
|
box = load_from_file(box_arg)
|
33
|
-
elsif box_arg =~ /\//
|
34
|
-
raise Errors::CloudNotSupported
|
35
35
|
else
|
36
|
-
box = load_from_boxes_path(box_arg, provider_name)
|
36
|
+
box = load_from_boxes_path(box_arg, provider_name, input_version)
|
37
37
|
end
|
38
38
|
|
39
39
|
if box.supported_input
|
40
40
|
return box
|
41
41
|
else
|
42
|
-
|
42
|
+
fail Errors::ProviderNotSupported, provider: box.provider_name, direction: 'input'
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -49,20 +49,29 @@ module VagrantMutate
|
|
49
49
|
# test that we have a valid url
|
50
50
|
url = URI(url)
|
51
51
|
unless url.scheme and url.host and url.path
|
52
|
-
|
52
|
+
fail Errors::URLError, url: url
|
53
53
|
end
|
54
54
|
|
55
55
|
# extract the name of the box from the url
|
56
56
|
# if it ends in .box remove that extension
|
57
57
|
# if not just remove leading slash
|
58
58
|
name = nil
|
59
|
-
if url.path =~ /(
|
60
|
-
name =
|
59
|
+
if url.path =~ /([-\w]+).box$/
|
60
|
+
name = Regexp.last_match[1]
|
61
61
|
else
|
62
62
|
name = url.path.sub(/^\//, '')
|
63
63
|
end
|
64
64
|
if name.empty?
|
65
|
-
|
65
|
+
fail Errors::URLError, url: url
|
66
|
+
end
|
67
|
+
|
68
|
+
# Extract the version of the box from the URL
|
69
|
+
if url.path =~ /\/([\d.]+)\//
|
70
|
+
version = Regexp.last_match[1]
|
71
|
+
@logger.info "Pulled version from URL (#{version})"
|
72
|
+
else
|
73
|
+
version = '0'
|
74
|
+
@logger.info "No version found in URL, assuming '0'"
|
66
75
|
end
|
67
76
|
|
68
77
|
# using same path as in vagrants box add action
|
@@ -71,38 +80,51 @@ module VagrantMutate
|
|
71
80
|
|
72
81
|
# if this fails it will raise an error and we'll quit
|
73
82
|
@env.ui.info "Downloading box #{name} from #{url}"
|
74
|
-
downloader = Vagrant::Util::Downloader.new(url, download_path,
|
83
|
+
downloader = Vagrant::Util::Downloader.new(url, download_path, ui: @env.ui)
|
75
84
|
downloader.download!
|
76
85
|
|
77
86
|
dir = unpack(download_path)
|
78
|
-
|
79
87
|
provider_name = determine_provider(dir)
|
80
88
|
|
81
|
-
|
89
|
+
create_box(provider_name, name, version, dir)
|
82
90
|
end
|
83
91
|
|
84
92
|
def load_from_file(file)
|
85
93
|
@logger.info "Loading box from file #{file}"
|
86
|
-
name = File.basename(
|
94
|
+
name = File.basename(file, File.extname(file))
|
95
|
+
|
87
96
|
dir = unpack(file)
|
88
97
|
provider_name = determine_provider(dir)
|
98
|
+
version = determine_version(dir)
|
89
99
|
|
90
|
-
|
100
|
+
create_box(provider_name, name, version, dir)
|
91
101
|
end
|
92
102
|
|
93
|
-
def load_from_boxes_path(name, provider_name)
|
94
|
-
@logger.info "Loading box #{name} from vagrants box path"
|
103
|
+
def load_from_boxes_path(name, provider_name, input_version)
|
104
|
+
@logger.info "Loading box #{name} from vagrants box path using provider #{provider_name} and version #{input_version}."
|
105
|
+
safe_name = sanitize_name(name)
|
95
106
|
if provider_name
|
96
|
-
|
107
|
+
@logger.info "Checking directory for provider #{provider_name}."
|
108
|
+
if input_version
|
109
|
+
@logger.info 'Input version provided, using it.'
|
110
|
+
version = input_version
|
111
|
+
else
|
112
|
+
@logger.info 'No version provided, getting it.'
|
113
|
+
version = get_version(safe_name)
|
114
|
+
@logger.info "Version = #{version}"
|
115
|
+
end
|
116
|
+
dir = verify_input_dir(provider_name, safe_name, version)
|
97
117
|
else
|
98
|
-
|
118
|
+
@logger.info 'Working out provider, version and directory...'
|
119
|
+
provider_name, version, dir = find_input_dir(safe_name)
|
99
120
|
end
|
100
|
-
box
|
121
|
+
@logger.info "Creating #{name} box using provider #{provider_name} with version #{version} in #{dir}."
|
122
|
+
create_box(provider_name, name, version, dir)
|
101
123
|
end
|
102
124
|
|
103
125
|
def cleanup
|
104
126
|
unless @tmp_files.empty?
|
105
|
-
@env.ui.info
|
127
|
+
@env.ui.info 'Cleaning up temporary files.'
|
106
128
|
@tmp_files.each do |f|
|
107
129
|
@logger.info "Deleting #{f}"
|
108
130
|
FileUtils.remove_entry_secure(f)
|
@@ -112,82 +134,113 @@ module VagrantMutate
|
|
112
134
|
|
113
135
|
private
|
114
136
|
|
115
|
-
def create_box(provider_name, name, dir)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
137
|
+
def create_box(provider_name, name, version, dir)
|
138
|
+
@logger.info "Creating box #{name} with provider #{provider_name} and version #{version} in #{dir}"
|
139
|
+
case provider_name
|
140
|
+
when 'kvm'
|
141
|
+
require_relative 'box/kvm'
|
142
|
+
Box::Kvm.new(@env, name, version, dir)
|
143
|
+
when 'libvirt'
|
144
|
+
require_relative 'box/libvirt'
|
145
|
+
Box::Libvirt.new(@env, name, version, dir)
|
146
|
+
when 'virtualbox'
|
147
|
+
require_relative 'box/virtualbox'
|
148
|
+
Box::Virtualbox.new(@env, name, version, dir)
|
149
|
+
else
|
150
|
+
fail Errors::ProviderNotSupported, provider: provider_name, direction: 'input or output'
|
151
|
+
end
|
130
152
|
end
|
131
153
|
|
132
|
-
def create_output_dir(name, provider_name)
|
154
|
+
def create_output_dir(name, provider_name, version)
|
133
155
|
# e.g. $HOME/.vagrant.d/boxes/fedora-19/0/libvirt
|
134
|
-
#
|
135
|
-
out_dir = File.join(
|
156
|
+
@logger.info "Attempting to create output dir for #{name} with version #{version} and provider #{provider_name}."
|
157
|
+
out_dir = File.join(@env.boxes_path, name, version, provider_name)
|
158
|
+
@logger.info "Creating out_dir #{out_dir}."
|
136
159
|
begin
|
137
160
|
FileUtils.mkdir_p(out_dir)
|
138
161
|
rescue => e
|
139
|
-
raise Errors::CreateBoxDirFailed, :
|
162
|
+
raise Errors::CreateBoxDirFailed, error_message: e.message
|
140
163
|
end
|
141
164
|
@logger.info "Created output directory #{out_dir}"
|
142
|
-
|
165
|
+
out_dir
|
143
166
|
end
|
144
167
|
|
145
168
|
def unpack(file)
|
146
|
-
@env.ui.info
|
169
|
+
@env.ui.info 'Extracting box file to a temporary directory.'
|
147
170
|
unless File.exist? file
|
148
|
-
|
171
|
+
fail Errors::BoxNotFound, box: file
|
149
172
|
end
|
150
173
|
tmp_dir = Dir.mktmpdir(nil, @env.tmp_path)
|
151
174
|
@tmp_files << tmp_dir
|
152
175
|
result = Vagrant::Util::Subprocess.execute(
|
153
|
-
|
176
|
+
'bsdtar', '-v', '-x', '-m', '-C', tmp_dir.to_s, '-f', file)
|
154
177
|
if result.exit_code != 0
|
155
|
-
|
178
|
+
fail Errors::ExtractBoxFailed, error_message: result.stderr.to_s
|
156
179
|
end
|
157
180
|
@logger.info "Unpacked box to #{tmp_dir}"
|
158
|
-
|
181
|
+
tmp_dir
|
159
182
|
end
|
160
183
|
|
161
184
|
def determine_provider(dir)
|
162
185
|
metadata_file = File.join(dir, 'metadata.json')
|
163
186
|
if File.exist? metadata_file
|
164
187
|
begin
|
165
|
-
metadata = JSON.load(
|
188
|
+
metadata = JSON.load(File.new(metadata_file, 'r'))
|
166
189
|
rescue => e
|
167
|
-
raise Errors::
|
190
|
+
raise Errors::LoadMetadataFailed, error_message: e.message
|
168
191
|
end
|
169
192
|
@logger.info "Determined input provider is #{metadata['provider']}"
|
170
193
|
return metadata['provider']
|
171
194
|
else
|
172
|
-
@logger.info
|
195
|
+
@logger.info 'No metadata found, so assuming input provider is virtualbox'
|
173
196
|
return 'virtualbox'
|
174
197
|
end
|
175
198
|
end
|
176
199
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
200
|
+
def determine_version(dir)
|
201
|
+
metadata_file = File.join(dir, 'metadata.json')
|
202
|
+
if File.exist? metadata_file
|
203
|
+
begin
|
204
|
+
metadata = JSON.load(File.new(metadata_file, 'r'))
|
205
|
+
rescue => e
|
206
|
+
raise Errors::LoadMetadataFailed, error_message: e.message
|
207
|
+
end
|
208
|
+
# Handle single or multiple versions
|
209
|
+
if metadata['versions'].nil?
|
210
|
+
@logger.info 'No versions provided by metadata, asuming version 0'
|
211
|
+
version = '0'
|
212
|
+
elsif metadata['versions'].length > 1
|
213
|
+
metadata['versions'].each do |metadata_version|
|
214
|
+
@logger.info 'Itterating available metadata versions for active version.'
|
215
|
+
next unless metadata_version['status'] == 'active'
|
216
|
+
version = metadata_version['version']
|
217
|
+
end
|
218
|
+
else
|
219
|
+
@logger.info 'Only one metadata version, grabbing version.'
|
220
|
+
version = metadata['versions'][0]['version']
|
221
|
+
end
|
222
|
+
@logger.info "Determined input version is #{version}"
|
223
|
+
return version
|
224
|
+
else
|
225
|
+
@logger.info 'No metadata found, so assuming version is 0'
|
226
|
+
return '0'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def verify_input_dir(provider_name, name, version)
|
231
|
+
input_dir = File.join(@env.boxes_path, name, version, provider_name)
|
180
232
|
if File.directory?(input_dir)
|
181
233
|
@logger.info "Found input directory #{input_dir}"
|
182
234
|
return input_dir
|
183
235
|
else
|
184
|
-
|
236
|
+
fail Errors::BoxNotFound, box: input_dir
|
185
237
|
end
|
186
238
|
end
|
187
239
|
|
188
240
|
def find_input_dir(name)
|
189
|
-
|
190
|
-
|
241
|
+
@logger.info "Looking for input dir for box #{name}."
|
242
|
+
version = get_version(name)
|
243
|
+
box_parent_dir = File.join(@env.boxes_path, name, version)
|
191
244
|
|
192
245
|
if Dir.exist?(box_parent_dir)
|
193
246
|
providers = Dir.entries(box_parent_dir).reject { |entry| entry =~ /^\./ }
|
@@ -198,16 +251,46 @@ module VagrantMutate
|
|
198
251
|
|
199
252
|
case
|
200
253
|
when providers.length < 1
|
201
|
-
|
254
|
+
fail Errors::BoxNotFound, box: name
|
202
255
|
when providers.length > 1
|
203
|
-
|
256
|
+
fail Errors::TooManyBoxesFound, box: name
|
204
257
|
else
|
205
258
|
provider_name = providers.first
|
206
|
-
input_dir = File.join(
|
207
|
-
@logger.info "Found source for box #{name} from provider #{provider_name} at #{input_dir}"
|
208
|
-
return provider_name, input_dir
|
259
|
+
input_dir = File.join(box_parent_dir, provider_name)
|
260
|
+
@logger.info "Found source for box #{name} from provider #{provider_name} with version #{version} at #{input_dir}"
|
261
|
+
return provider_name, version, input_dir
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def get_version(name)
|
266
|
+
# Get a list of directories for this box
|
267
|
+
@logger.info "Getting versions for #{name}."
|
268
|
+
|
269
|
+
box_dir = File.join(@env.boxes_path, name, '*')
|
270
|
+
possible_versions = Dir.glob(box_dir).select { |f| File.directory? f }.map { |x| x.split('/').last }
|
271
|
+
|
272
|
+
@logger.info "Possible_versions = #{possible_versions.inspect}"
|
273
|
+
|
274
|
+
if possible_versions.length > 1
|
275
|
+
@logger.info 'Got multiple possible versions, selecting max value'
|
276
|
+
version = possible_versions.max
|
277
|
+
else
|
278
|
+
@logger.info 'Got a single version, so returning it'
|
279
|
+
version = possible_versions.first
|
209
280
|
end
|
281
|
+
|
282
|
+
@logger.info "Found version #{version}"
|
283
|
+
version
|
210
284
|
end
|
211
285
|
|
286
|
+
def sanitize_name(name)
|
287
|
+
if name =~ /\//
|
288
|
+
@logger.info 'Replacing / with -VAGRANTSLASH-.'
|
289
|
+
name = name.dup
|
290
|
+
name.gsub!('/', '-VAGRANTSLASH-')
|
291
|
+
@logger.info "New name = #{name}."
|
292
|
+
end
|
293
|
+
name
|
294
|
+
end
|
212
295
|
end
|
213
296
|
end
|
@@ -3,7 +3,6 @@ require 'fileutils'
|
|
3
3
|
module VagrantMutate
|
4
4
|
module Converter
|
5
5
|
class Converter
|
6
|
-
|
7
6
|
def self.create(env, input_box, output_box)
|
8
7
|
case output_box.provider_name
|
9
8
|
when 'kvm'
|
@@ -13,7 +12,7 @@ module VagrantMutate
|
|
13
12
|
require_relative 'libvirt'
|
14
13
|
Libvirt.new(env, input_box, output_box)
|
15
14
|
else
|
16
|
-
|
15
|
+
fail Errors::ProviderNotSupported, provider: output_box.provider_name, direction: 'output'
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
@@ -24,9 +23,9 @@ module VagrantMutate
|
|
24
23
|
@logger = Log4r::Logger.new('vagrant::mutate')
|
25
24
|
end
|
26
25
|
|
27
|
-
def convert
|
26
|
+
def convert
|
28
27
|
if @input_box.provider_name == @output_box.provider_name
|
29
|
-
|
28
|
+
fail Errors::ProvidersMatch
|
30
29
|
end
|
31
30
|
|
32
31
|
@env.ui.info "Converting #{@input_box.name} from #{@input_box.provider_name} "\
|
@@ -44,27 +43,27 @@ module VagrantMutate
|
|
44
43
|
def write_metadata
|
45
44
|
metadata = generate_metadata
|
46
45
|
begin
|
47
|
-
File.open(
|
48
|
-
f.write(
|
46
|
+
File.open(File.join(@output_box.dir, 'metadata.json'), 'w') do |f|
|
47
|
+
f.write(JSON.generate(metadata))
|
49
48
|
end
|
50
49
|
rescue => e
|
51
|
-
raise Errors::WriteMetadataFailed, :
|
50
|
+
raise Errors::WriteMetadataFailed, error_message: e.message
|
52
51
|
end
|
53
|
-
@logger.info
|
52
|
+
@logger.info 'Wrote metadata'
|
54
53
|
end
|
55
54
|
|
56
55
|
def write_vagrantfile
|
57
56
|
body = generate_vagrantfile
|
58
57
|
begin
|
59
|
-
File.open(
|
60
|
-
f.puts(
|
61
|
-
f.puts(
|
62
|
-
f.puts(
|
58
|
+
File.open(File.join(@output_box.dir, 'Vagrantfile'), 'w') do |f|
|
59
|
+
f.puts('Vagrant.configure("2") do |config|')
|
60
|
+
f.puts(body)
|
61
|
+
f.puts('end')
|
63
62
|
end
|
64
63
|
rescue => e
|
65
|
-
raise Errors::WriteVagrantfileFailed, :
|
64
|
+
raise Errors::WriteVagrantfileFailed, error_message: e.message
|
66
65
|
end
|
67
|
-
@logger.info
|
66
|
+
@logger.info 'Wrote vagrantfile'
|
68
67
|
end
|
69
68
|
|
70
69
|
def write_disk
|
@@ -76,20 +75,19 @@ module VagrantMutate
|
|
76
75
|
end
|
77
76
|
|
78
77
|
def copy_disk
|
79
|
-
input = File.join(
|
80
|
-
output = File.join(
|
78
|
+
input = File.join(@input_box.dir, @input_box.image_name)
|
79
|
+
output = File.join(@output_box.dir, @output_box.image_name)
|
81
80
|
@logger.info "Copying #{input} to #{output}"
|
82
81
|
begin
|
83
82
|
FileUtils.copy_file(input, output)
|
84
83
|
rescue => e
|
85
|
-
raise Errors::WriteDiskFailed, :
|
84
|
+
raise Errors::WriteDiskFailed, error_message: e.message
|
86
85
|
end
|
87
86
|
end
|
88
87
|
|
89
88
|
def convert_disk
|
90
|
-
input_file = File.join(
|
91
|
-
output_file = File.join(
|
92
|
-
input_format = @input_box.image_format
|
89
|
+
input_file = File.join(@input_box.dir, @input_box.image_name)
|
90
|
+
output_file = File.join(@output_box.dir, @output_box.image_name)
|
93
91
|
output_format = @output_box.image_format
|
94
92
|
|
95
93
|
# p for progress bar
|
@@ -99,10 +97,9 @@ module VagrantMutate
|
|
99
97
|
command = "qemu-img convert #{qemu_options} -O #{output_format} -o compat=1.1 #{input_file} #{output_file}"
|
100
98
|
@logger.info "Running #{command}"
|
101
99
|
unless system(command)
|
102
|
-
|
100
|
+
fail Errors::WriteDiskFailed, error_message: "qemu-img exited with status #{$CHILD_STATUS.exitstatus}"
|
103
101
|
end
|
104
102
|
end
|
105
|
-
|
106
103
|
end
|
107
104
|
end
|
108
105
|
end
|
@@ -3,11 +3,8 @@ require 'erb'
|
|
3
3
|
module VagrantMutate
|
4
4
|
module Converter
|
5
5
|
class Kvm < Converter
|
6
|
-
|
7
6
|
def generate_metadata
|
8
|
-
|
9
|
-
'provider' => @output_box.provider_name,
|
10
|
-
}
|
7
|
+
{ 'provider' => @output_box.provider_name }
|
11
8
|
end
|
12
9
|
|
13
10
|
def generate_vagrantfile
|
@@ -28,36 +25,35 @@ module VagrantMutate
|
|
28
25
|
name = @input_box.name
|
29
26
|
memory = @input_box.memory / 1024 # convert bytes to kib
|
30
27
|
cpus = @input_box.cpus
|
31
|
-
mac = format_mac(
|
28
|
+
mac = format_mac(@input_box.mac_address)
|
32
29
|
arch = @input_box.architecture
|
33
30
|
|
34
31
|
qemu_bin = find_kvm
|
35
32
|
|
36
|
-
File.open(
|
37
|
-
f.write(
|
33
|
+
File.open(File.join(@output_box.dir, 'box.xml'), 'w') do |f|
|
34
|
+
f.write(ERB.new(template).result(binding))
|
38
35
|
end
|
39
36
|
end
|
40
37
|
|
41
38
|
private
|
42
39
|
|
43
40
|
def find_kvm
|
44
|
-
qemu_bin_list = [
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
qemu_bin = qemu_bin_list.
|
41
|
+
qemu_bin_list = ['/usr/bin/qemu-system-x86_64',
|
42
|
+
'/usr/bin/qemu-system-i386',
|
43
|
+
'/usr/bin/qemu-kvm',
|
44
|
+
'/usr/libexec/qemu-kvm',
|
45
|
+
'/usr/bin/kvm']
|
46
|
+
qemu_bin = qemu_bin_list.find { |binary| File.exist? binary }
|
50
47
|
unless qemu_bin
|
51
|
-
|
48
|
+
fail Errors::QemuNotFound
|
52
49
|
end
|
53
|
-
|
50
|
+
qemu_bin
|
54
51
|
end
|
55
52
|
|
56
53
|
# convert to format with colons
|
57
54
|
def format_mac(mac)
|
58
55
|
mac.scan(/(.{2})/).join(':')
|
59
56
|
end
|
60
|
-
|
61
57
|
end
|
62
58
|
end
|
63
59
|
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
module VagrantMutate
|
2
2
|
module Converter
|
3
3
|
class Libvirt < Converter
|
4
|
-
|
5
4
|
def generate_metadata
|
6
|
-
|
5
|
+
{
|
7
6
|
'provider' => @output_box.provider_name,
|
8
7
|
'format' => @output_box.image_format,
|
9
|
-
'virtual_size' => ( @input_box.virtual_size.to_f / (1024 * 1024 * 1024)
|
8
|
+
'virtual_size' => ( @input_box.virtual_size.to_f / (1024 * 1024 * 1024)).ceil
|
10
9
|
}
|
11
10
|
end
|
12
11
|
|
@@ -21,7 +20,6 @@ module VagrantMutate
|
|
21
20
|
def write_specific_files
|
22
21
|
# nothing to do here
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -6,10 +6,6 @@ module VagrantMutate
|
|
6
6
|
error_namespace('vagrant_mutate.errors')
|
7
7
|
end
|
8
8
|
|
9
|
-
class CloudNotSupported < VagrantMutateError
|
10
|
-
error_key(:cloud_not_supported)
|
11
|
-
end
|
12
|
-
|
13
9
|
class ProvidersMatch < VagrantMutateError
|
14
10
|
error_key(:providers_match)
|
15
11
|
end
|
@@ -46,6 +42,10 @@ module VagrantMutate
|
|
46
42
|
error_key(:determine_provider_failed)
|
47
43
|
end
|
48
44
|
|
45
|
+
class LoadMetadataFailed < VagrantMutateError
|
46
|
+
error_key(:load_metadata_failed)
|
47
|
+
end
|
48
|
+
|
49
49
|
class CreateBoxDirFailed < VagrantMutateError
|
50
50
|
error_key(:create_box_dir_failed)
|
51
51
|
end
|
@@ -78,5 +78,8 @@ module VagrantMutate
|
|
78
78
|
error_key(:url_error)
|
79
79
|
end
|
80
80
|
|
81
|
+
class MetadataNotFound < VagrantMutateError
|
82
|
+
error_key(:metadata_not_found)
|
83
|
+
end
|
81
84
|
end
|
82
85
|
end
|
@@ -3,23 +3,26 @@ require 'vagrant-mutate/qemu'
|
|
3
3
|
require 'vagrant-mutate/converter/converter'
|
4
4
|
|
5
5
|
module VagrantMutate
|
6
|
-
|
7
6
|
class Mutate < Vagrant.plugin(2, :command)
|
8
|
-
|
9
7
|
def execute
|
10
8
|
options = {}
|
11
9
|
options[:input_provider] = nil
|
10
|
+
options[:version] = nil
|
12
11
|
|
13
12
|
opts = OptionParser.new do |o|
|
14
13
|
o.banner = 'Usage: vagrant mutate <box-name-or-file-or-url> <provider>'
|
15
|
-
o.on(
|
16
|
-
|
14
|
+
o.on('--input-provider PROVIDER',
|
15
|
+
'Specify provider for input box') do |p|
|
17
16
|
options[:input_provider] = p
|
18
17
|
end
|
18
|
+
o.on('--version VERSION',
|
19
|
+
'Specify version for input box') do |p|
|
20
|
+
options[:version] = p
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
24
|
argv = parse_options(opts)
|
22
|
-
return
|
25
|
+
return unless argv
|
23
26
|
|
24
27
|
unless argv.length == 2
|
25
28
|
@env.ui.info(opts.help)
|
@@ -33,10 +36,10 @@ module VagrantMutate
|
|
33
36
|
Qemu.verify_qemu_version(@env)
|
34
37
|
|
35
38
|
input_loader = BoxLoader.new(@env)
|
36
|
-
input_box = input_loader.load(
|
39
|
+
input_box = input_loader.load(options[:box_arg], options[:input_provider], options[:version])
|
37
40
|
|
38
41
|
output_loader = BoxLoader.new(@env)
|
39
|
-
output_box = output_loader.prepare_for_output(
|
42
|
+
output_box = output_loader.prepare_for_output(input_box.name, options[:output_provider], input_box.version)
|
40
43
|
|
41
44
|
converter = Converter::Converter.create(@env, input_box, output_box)
|
42
45
|
converter.convert
|
@@ -44,9 +47,6 @@ module VagrantMutate
|
|
44
47
|
input_loader.cleanup
|
45
48
|
|
46
49
|
@env.ui.info "The box #{output_box.name} (#{output_box.provider_name}) is now ready to use."
|
47
|
-
|
48
50
|
end
|
49
|
-
|
50
51
|
end
|
51
|
-
|
52
52
|
end
|
data/lib/vagrant-mutate/qemu.rb
CHANGED
@@ -1,40 +1,38 @@
|
|
1
1
|
module VagrantMutate
|
2
2
|
class Qemu
|
3
|
-
|
4
3
|
# http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
4
|
+
def self.verify_qemu_installed
|
5
|
+
logger = Log4r::Logger.new('vagrant::mutate')
|
6
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
7
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
8
|
+
exts.each do |ext|
|
9
|
+
exe = File.join(path, "qemu-img#{ext}")
|
10
|
+
if File.executable? exe
|
11
|
+
logger.info 'Found qemu'
|
12
|
+
return
|
15
13
|
end
|
16
14
|
end
|
17
|
-
# if we make it here qemu-img command was not found
|
18
|
-
raise Errors::QemuImgNotFound
|
19
15
|
end
|
16
|
+
# if we make it here qemu-img command was not found
|
17
|
+
fail Errors::QemuImgNotFound
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
def self.verify_qemu_version(env)
|
21
|
+
usage = `qemu-img --version`
|
22
|
+
if usage =~ /(\d+\.\d+\.\d+)/
|
23
|
+
installed_version = Gem::Version.new(Regexp.last_match[1])
|
24
|
+
# less than 1.2 or equal to 1.6.x
|
25
|
+
if installed_version < Gem::Version.new('1.2.0') or (installed_version >= Gem::Version.new('1.6.0') and installed_version < Gem::Version.new('1.7.0'))
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
env.ui.warn "You have qemu #{installed_version} installed. "\
|
28
|
+
'This version cannot read some virtualbox boxes. '\
|
29
|
+
'If conversion fails, see below for recommendations. '\
|
30
|
+
'https://github.com/sciurus/vagrant-mutate/wiki/QEMU-Version-Compatibility'
|
32
31
|
|
33
|
-
end
|
34
|
-
else
|
35
|
-
raise Errors::ParseQemuVersionFailed
|
36
32
|
end
|
33
|
+
else
|
34
|
+
fail Errors::ParseQemuVersionFailed
|
37
35
|
end
|
38
|
-
|
36
|
+
end
|
39
37
|
end
|
40
38
|
end
|
data/lib/vagrant-mutate.rb
CHANGED
@@ -2,7 +2,6 @@ require 'vagrant-mutate/version'
|
|
2
2
|
require 'vagrant-mutate/errors'
|
3
3
|
|
4
4
|
module VagrantMutate
|
5
|
-
|
6
5
|
def self.source_root
|
7
6
|
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
8
7
|
end
|
@@ -21,5 +20,4 @@ module VagrantMutate
|
|
21
20
|
I18n.reload!
|
22
21
|
end
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
data/locales/en.yml
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
en:
|
2
2
|
vagrant_mutate:
|
3
3
|
errors:
|
4
|
-
cloud_not_supported: |-
|
5
|
-
Vagrant-mutate can not download from Vagrant Cloud for you.
|
6
4
|
providers_match: |-
|
7
5
|
Input and output provider are the same. Aborting.
|
8
6
|
provider_not_supported: |-
|
@@ -24,6 +22,9 @@ en:
|
|
24
22
|
determine_provider_failed: |-
|
25
23
|
Determining provider for box failed with error:
|
26
24
|
%{error_message}
|
25
|
+
load_metadata_failed: |-
|
26
|
+
Loading metadata for box failed with error:
|
27
|
+
%{error_message}
|
27
28
|
create_box_dir_failed: |-
|
28
29
|
Creating directory for box failed with error:
|
29
30
|
%{error_message}
|
@@ -45,3 +46,5 @@ en:
|
|
45
46
|
%{error_message}
|
46
47
|
url_error: |-
|
47
48
|
The url %{url} is not valid
|
49
|
+
metadata_not_found: |-
|
50
|
+
Unable to find metadata file for %{box}
|
data/test/test.rb
CHANGED
@@ -12,7 +12,7 @@ end
|
|
12
12
|
|
13
13
|
def ensure_pkg_dir
|
14
14
|
pkg_dir = File.expand_path('../../pkg', __FILE__)
|
15
|
-
|
15
|
+
unless Dir.exist? pkg_dir
|
16
16
|
Dir.mkdir pkg_dir
|
17
17
|
end
|
18
18
|
end
|
@@ -22,7 +22,7 @@ def build_plugin
|
|
22
22
|
pkg_dir = File.expand_path('../../pkg', __FILE__)
|
23
23
|
working_dir = Dir.pwd
|
24
24
|
Dir.chdir pkg_dir
|
25
|
-
FileUtils.rm(
|
25
|
+
FileUtils.rm(Dir.glob('*.gem'))
|
26
26
|
system('rake build')
|
27
27
|
Dir.chdir working_dir
|
28
28
|
end
|
@@ -56,7 +56,7 @@ end
|
|
56
56
|
|
57
57
|
def test(input, outputs)
|
58
58
|
failures = []
|
59
|
-
test_dir = File.expand_path(
|
59
|
+
test_dir = File.expand_path(File.dirname(__FILE__))
|
60
60
|
|
61
61
|
input_box = File.join(test_dir, 'input', input, 'mutate-test.box')
|
62
62
|
|
@@ -83,19 +83,19 @@ def test(input, outputs)
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
|
86
|
+
failures
|
87
87
|
end
|
88
88
|
|
89
89
|
cleanup
|
90
90
|
ensure_pkg_dir
|
91
91
|
build_plugin
|
92
|
-
failures = test(
|
93
|
-
failures += test(
|
94
|
-
failures += test(
|
92
|
+
failures = test('virtualbox', %w(kvm libvirt))
|
93
|
+
failures += test('libvirt', ['kvm'])
|
94
|
+
failures += test('kvm', ['libvirt'])
|
95
95
|
|
96
96
|
if failures.empty?
|
97
97
|
puts "\nALL TESTS PASSED"
|
98
98
|
else
|
99
99
|
puts "\nTESTS FAILED"
|
100
|
-
failures.each {|f| puts f}
|
100
|
+
failures.each { |f| puts f }
|
101
101
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-mutate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Pitts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -48,7 +48,7 @@ files:
|
|
48
48
|
- ".gitignore"
|
49
49
|
- CHANGELOG.md
|
50
50
|
- Gemfile
|
51
|
-
- LICENSE
|
51
|
+
- LICENSE
|
52
52
|
- README.md
|
53
53
|
- Rakefile
|
54
54
|
- lib/vagrant-mutate.rb
|