vagrant-mutate 0.1.4 → 0.1.5
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/CHANGELOG.md +6 -0
- data/README.md +6 -3
- data/lib/vagrant-mutate/box/virtualbox.rb +67 -8
- data/lib/vagrant-mutate/box_loader.rb +72 -29
- data/lib/vagrant-mutate/converter/kvm.rb +1 -1
- data/lib/vagrant-mutate/errors.rb +9 -1
- data/lib/vagrant-mutate/mutate.rb +3 -7
- data/lib/vagrant-mutate/version.rb +1 -1
- data/locales/en.yml +5 -0
- data/templates/kvm/box.xml.erb +7 -3
- data/test/expected_output/virtualbox/kvm/box.xml +7 -4
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 0.1.5 (2013-12-17)
|
2
|
+
* Preserve dsik interface type when coverting to KVM (#21)
|
3
|
+
* Remove dependency in minitar (#24)
|
4
|
+
* Support downloading input box (#9)
|
5
|
+
* Handle errors when reading ovf file
|
6
|
+
|
1
7
|
# 0.1.4 (2013-12-08)
|
2
8
|
* Rework box and converter implementation (#7)
|
3
9
|
* Write disk images as sparse files (#13)
|
data/README.md
CHANGED
@@ -41,14 +41,17 @@ To install from source, clone the repository and run `rake build`. That will pro
|
|
41
41
|
|
42
42
|
The basic usage is
|
43
43
|
|
44
|
-
vagrant mutate box-name-or-file output-provider
|
44
|
+
vagrant mutate box-name-or-file-or-url output-provider
|
45
45
|
|
46
46
|
For example, if you wanted to download a box created for virtualbox and add it to vagrant for libvirt
|
47
47
|
|
48
|
-
|
48
|
+
vagrant mutate http://files.vagrantup.com/precise32.box libvirt
|
49
|
+
|
50
|
+
Or if you had already downloaded it
|
51
|
+
|
49
52
|
vagrant mutate precise32.box libvirt
|
50
53
|
|
51
|
-
Or
|
54
|
+
Or if you had already added the virtualbox version of the box to vagrant and now want to use it with libvirt
|
52
55
|
|
53
56
|
vagrant mutate precise32 libvirt
|
54
57
|
|
@@ -26,38 +26,97 @@ module VagrantMutate
|
|
26
26
|
|
27
27
|
# use mac from the first enabled nic
|
28
28
|
def mac_address
|
29
|
+
mac = nil
|
30
|
+
|
29
31
|
ovf.elements.each("//vbox:Machine/Hardware//Adapter") do |ele|
|
30
32
|
if ele.attributes['enabled'] == 'true'
|
31
|
-
mac = ele.attributes['MACAddress']
|
32
|
-
|
33
|
-
return mac[0..1] + ":" + mac[2..3] + ":" +
|
34
|
-
mac[4..5] + ":" + mac[6..7] + ":" +
|
35
|
-
mac[8..9] + ":" + mac[10..11]
|
33
|
+
mac = format_mac( ele.attributes['MACAddress'] )
|
34
|
+
break
|
36
35
|
end
|
37
36
|
end
|
37
|
+
|
38
|
+
if mac
|
39
|
+
return mac
|
40
|
+
else
|
41
|
+
raise Errors::BoxAttributeError, :error_message => 'Could not determine mac address'
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
def cpus
|
46
|
+
cpu_count = nil
|
47
|
+
|
41
48
|
ovf.elements.each("//VirtualHardwareSection/Item") do |device|
|
42
49
|
if device.elements["rasd:ResourceType"].text == '3'
|
43
|
-
|
50
|
+
cpu_count = device.elements["rasd:VirtualQuantity"].text
|
44
51
|
end
|
45
52
|
end
|
53
|
+
|
54
|
+
if cpu_count
|
55
|
+
return cpu_count
|
56
|
+
else
|
57
|
+
raise Errors::BoxAttributeError, :error_message => 'Could not determine number of CPUs'
|
58
|
+
end
|
46
59
|
end
|
47
60
|
|
48
61
|
def memory
|
62
|
+
memory_in_bytes = nil
|
63
|
+
|
49
64
|
ovf.elements.each("//VirtualHardwareSection/Item") do |device|
|
50
65
|
if device.elements["rasd:ResourceType"].text == '4'
|
51
|
-
|
66
|
+
memory_in_bytes = size_in_bytes(device.elements["rasd:VirtualQuantity"].text,
|
52
67
|
device.elements["rasd:AllocationUnits"].text)
|
53
68
|
end
|
54
69
|
end
|
70
|
+
|
71
|
+
if memory_in_bytes
|
72
|
+
return memory_in_bytes
|
73
|
+
else
|
74
|
+
raise Errors::BoxAttributeError, :error_message => 'Could not determine amount of memory'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def disk_interface
|
79
|
+
controller_type = {}
|
80
|
+
controller_used_by_disk = nil
|
81
|
+
ovf.elements.each("//VirtualHardwareSection/Item") do |device|
|
82
|
+
# when we find a controller, store its ID and type
|
83
|
+
# when we find a disk, store the ID of the controller it is connected to
|
84
|
+
case device.elements["rasd:ResourceType"].text
|
85
|
+
when "5"
|
86
|
+
controller_type[device.elements["rasd:InstanceID"].text] = 'ide'
|
87
|
+
when "6"
|
88
|
+
controller_type[device.elements["rasd:InstanceID"].text] = 'scsi'
|
89
|
+
when "20"
|
90
|
+
controller_type[device.elements["rasd:InstanceID"].text] = 'sata'
|
91
|
+
when "17"
|
92
|
+
controller_used_by_disk = device.elements["rasd:Parent"].text
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if controller_used_by_disk and controller_type[controller_used_by_disk]
|
96
|
+
return controller_type[controller_used_by_disk]
|
97
|
+
else
|
98
|
+
raise Errors::BoxAttributeError, :error_message => 'Could not determine disk interface'
|
99
|
+
end
|
55
100
|
end
|
56
101
|
|
57
102
|
private
|
58
103
|
|
59
104
|
def ovf
|
60
|
-
|
105
|
+
if @ovf
|
106
|
+
return @ovf
|
107
|
+
end
|
108
|
+
|
109
|
+
ovf_file = File.join( @dir, 'box.ovf')
|
110
|
+
begin
|
111
|
+
@ovf = REXML::Document.new( File.read(ovf_file) )
|
112
|
+
rescue => e
|
113
|
+
raise Errors::BoxAttributeError, :error_message => e.message
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# convert to more standard format with colons
|
118
|
+
def format_mac(mac)
|
119
|
+
mac.scan(/(.{2})/).join(':')
|
61
120
|
end
|
62
121
|
|
63
122
|
# Takes a quantity and a unit
|
@@ -1,17 +1,16 @@
|
|
1
|
-
require 'archive/tar/minitar'
|
2
1
|
require 'fileutils'
|
3
2
|
require 'json'
|
4
|
-
require '
|
3
|
+
require 'uri'
|
4
|
+
require "vagrant/util/subprocess"
|
5
|
+
require "vagrant/util/downloader"
|
5
6
|
|
6
7
|
module VagrantMutate
|
7
8
|
class BoxLoader
|
8
9
|
|
9
|
-
include Archive::Tar
|
10
|
-
|
11
10
|
def initialize( env )
|
12
11
|
@env = env
|
13
12
|
@logger = Log4r::Logger.new('vagrant::mutate')
|
14
|
-
@
|
13
|
+
@tmp_files = []
|
15
14
|
end
|
16
15
|
|
17
16
|
def create_box(provider_name, name, dir)
|
@@ -36,26 +35,74 @@ module VagrantMutate
|
|
36
35
|
dir = create_output_dir(name, provider_name)
|
37
36
|
box = create_box(provider_name, name, dir)
|
38
37
|
|
39
|
-
|
38
|
+
if box.supported_output
|
39
|
+
return box
|
40
|
+
else
|
40
41
|
raise Errors::ProviderNotSupported, :provider => provider_name, :direction => 'output'
|
41
42
|
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def load(box_arg)
|
46
|
+
if box_arg =~ /:\/\//
|
47
|
+
box = load_from_url(box_arg)
|
48
|
+
elsif box_arg =~ /\.box$/
|
49
|
+
box = load_from_file(box_arg)
|
50
|
+
else
|
51
|
+
box = load_by_name(box_arg)
|
52
|
+
end
|
53
|
+
|
54
|
+
if box.supported_input
|
55
|
+
return box
|
56
|
+
else
|
57
|
+
raise Errors::ProviderNotSupported, :provider => provider_name, :direction => 'input'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_from_url(url)
|
62
|
+
@logger.info "Loading box from url #{url}"
|
63
|
+
|
64
|
+
# test that we have a valid url
|
65
|
+
url = URI(url)
|
66
|
+
unless url.scheme and url.host and url.path
|
67
|
+
raise Errors::URLError, :url => url
|
68
|
+
end
|
69
|
+
|
70
|
+
# extract the name of the box from the url
|
71
|
+
# if it ends in .box remove that extension
|
72
|
+
# if not just remove leading slash
|
73
|
+
name = nil
|
74
|
+
if url.path =~ /(\w+).box$/
|
75
|
+
name = $1
|
76
|
+
else
|
77
|
+
name = url.path.sub(/^\//, '')
|
78
|
+
end
|
79
|
+
if name.empty?
|
80
|
+
raise Errors::URLError, :url => url
|
81
|
+
end
|
82
|
+
|
83
|
+
# using same path as in vagrants box add action
|
84
|
+
download_path = File.join(@env.tmp_path, 'box' + Digest::SHA1.hexdigest(url.to_s))
|
85
|
+
@tmp_files << download_path
|
86
|
+
|
87
|
+
# if this fails it will raise an error and we'll quit
|
88
|
+
@env.ui.info "Downloading box #{name} from #{url}"
|
89
|
+
downloader = Vagrant::Util::Downloader.new(url, download_path, { :ui => @env.ui })
|
90
|
+
downloader.download!
|
42
91
|
|
43
|
-
|
92
|
+
dir = unpack(download_path)
|
93
|
+
|
94
|
+
provider_name = determine_provider(dir)
|
95
|
+
|
96
|
+
box = create_box(provider_name, name, dir)
|
44
97
|
end
|
45
98
|
|
46
99
|
def load_from_file(file)
|
47
100
|
@logger.info "Loading box from file #{file}"
|
48
101
|
name = File.basename( file, File.extname(file) )
|
49
102
|
dir = unpack(file)
|
50
|
-
@tmp_dir = dir
|
51
103
|
provider_name = determine_provider(dir)
|
52
|
-
box = create_box(provider_name, name, dir)
|
53
104
|
|
54
|
-
|
55
|
-
raise Errors::ProviderNotSupported, :provider => provider_name, :direction => 'input'
|
56
|
-
end
|
57
|
-
|
58
|
-
return box
|
105
|
+
box = create_box(provider_name, name, dir)
|
59
106
|
end
|
60
107
|
|
61
108
|
def load_by_name(name)
|
@@ -63,14 +110,15 @@ module VagrantMutate
|
|
63
110
|
dir = find_input_dir(name)
|
64
111
|
# cheat for now since only supported input is virtualbox
|
65
112
|
box = create_box('virtualbox', name, dir)
|
66
|
-
return box
|
67
113
|
end
|
68
114
|
|
69
115
|
def cleanup
|
70
|
-
|
116
|
+
unless @tmp_files.empty?
|
71
117
|
@env.ui.info "Cleaning up temporary files."
|
72
|
-
@
|
73
|
-
|
118
|
+
@tmp_files.each do |f|
|
119
|
+
@logger.info "Deleting #{f}"
|
120
|
+
FileUtils.remove_entry_secure(f)
|
121
|
+
end
|
74
122
|
end
|
75
123
|
end
|
76
124
|
|
@@ -120,17 +168,12 @@ module VagrantMutate
|
|
120
168
|
unless File.exists? file
|
121
169
|
raise Errors::BoxNotFound, :box => file
|
122
170
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
begin
|
130
|
-
tmp_dir = Dir.mktmpdir
|
131
|
-
Minitar.unpack(tar, tmp_dir)
|
132
|
-
rescue => e
|
133
|
-
raise Errors::ExtractBoxFailed, :error_message => e.message
|
171
|
+
tmp_dir = Dir.mktmpdir(nil, @env.tmp_path)
|
172
|
+
@tmp_files << tmp_dir
|
173
|
+
result = Vagrant::Util::Subprocess.execute(
|
174
|
+
"bsdtar", "-v", "-x", "-m", "-C", tmp_dir.to_s, "-f", file)
|
175
|
+
if result.exit_code != 0
|
176
|
+
raise Errors::ExtractBoxFailed, :error_message => result.stderr.to_s
|
134
177
|
end
|
135
178
|
@logger.info "Unpacked box to #{tmp_dir}"
|
136
179
|
return tmp_dir
|
@@ -46,9 +46,17 @@ module VagrantMutate
|
|
46
46
|
error_key(:parse_qemu_version_failed)
|
47
47
|
end
|
48
48
|
|
49
|
-
class
|
49
|
+
class DetermineImageSizeFailed < VagrantMutateError
|
50
50
|
error_key(:determine_image_size_failed)
|
51
51
|
end
|
52
52
|
|
53
|
+
class BoxAttributeError < VagrantMutateError
|
54
|
+
error_key(:box_attribute_error)
|
55
|
+
end
|
56
|
+
|
57
|
+
class URLError < VagrantMutateError
|
58
|
+
error_key(:url_error)
|
59
|
+
end
|
60
|
+
|
53
61
|
end
|
54
62
|
end
|
@@ -20,15 +20,11 @@ module VagrantMutate
|
|
20
20
|
box_arg = argv[0]
|
21
21
|
output_provider_arg = argv[1]
|
22
22
|
|
23
|
-
input_loader = BoxLoader.new(@env)
|
24
|
-
output_loader = BoxLoader.new(@env)
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
input_box = input_loader.load_by_name(box_arg)
|
30
|
-
end
|
24
|
+
input_loader = BoxLoader.new(@env)
|
25
|
+
input_box = input_loader.load(box_arg)
|
31
26
|
|
27
|
+
output_loader = BoxLoader.new(@env)
|
32
28
|
output_box = output_loader.prepare_for_output( input_box.name, output_provider_arg)
|
33
29
|
|
34
30
|
converter = Converter::Converter.create(@env, input_box, output_box)
|
data/locales/en.yml
CHANGED
@@ -29,3 +29,8 @@ en:
|
|
29
29
|
Determining the version of qemu-img installed failed
|
30
30
|
determine_image_size_failed: |-
|
31
31
|
Determining the virtual size of the disk image failed
|
32
|
+
box_attribute_error: |-
|
33
|
+
Error determining information about the input box:
|
34
|
+
%{error_message}
|
35
|
+
url_error: |-
|
36
|
+
The url %{url} is not valid
|
data/templates/kvm/box.xml.erb
CHANGED
@@ -25,12 +25,16 @@
|
|
25
25
|
<driver name='qemu' type='<%= image_type %>'/>
|
26
26
|
<source file='<%= disk %>'/>
|
27
27
|
<target dev='vda' bus='<%= disk_bus %>'/>
|
28
|
-
|
28
|
+
<% if disk_bus == 'virtio' %>
|
29
29
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
30
|
-
|
30
|
+
</disk>
|
31
|
+
<% else %>
|
31
32
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
32
|
-
<% end %>
|
33
33
|
</disk>
|
34
|
+
<controller type='<%= disk_bus %>' index='0'>
|
35
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
36
|
+
</controller>
|
37
|
+
<% end %>
|
34
38
|
<controller type='usb' index='0'>
|
35
39
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
36
40
|
</controller>
|
@@ -22,11 +22,14 @@
|
|
22
22
|
<disk type='file' device='disk'>
|
23
23
|
<driver name='qemu' type='qcow2'/>
|
24
24
|
<source file='box-disk1.img'/>
|
25
|
-
<target dev='vda' bus='
|
26
|
-
|
27
|
-
<address type='
|
28
|
-
|
25
|
+
<target dev='vda' bus='sata'/>
|
26
|
+
|
27
|
+
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
29
28
|
</disk>
|
29
|
+
<controller type='sata' index='0'>
|
30
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
31
|
+
</controller>
|
32
|
+
|
30
33
|
<controller type='usb' index='0'>
|
31
34
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
32
35
|
</controller>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-mutate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: archive-tar-minitar
|