vagrant-mutate 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|