vagrant-mutate 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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
- wget http://files.vagrantup.com/precise32.box
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, if you had already added the virtualbox version of the box to vagrant and now want to use it with libvirt
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
- # convert to more standarad format with colons
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
- return device.elements["rasd:VirtualQuantity"].text
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
- return size_in_bytes(device.elements["rasd:VirtualQuantity"].text,
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
- @ovf ||= REXML::Document.new( File.read( File.join( @dir, 'box.ovf') ) )
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 'zlib'
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
- @tmp_dir = nil
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
- unless box.supported_output
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
- return box
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
- unless box.supported_input
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
- if @tmp_dir
116
+ unless @tmp_files.empty?
71
117
  @env.ui.info "Cleaning up temporary files."
72
- @logger.info "Deleting #{@tmp_dir}"
73
- FileUtils.remove_entry_secure(@tmp_dir)
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
- # box may or may not be gzipped
124
- begin
125
- tar = Zlib::GzipReader.new(File.open(file, 'rb'))
126
- rescue
127
- tar = file
128
- end
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
@@ -16,7 +16,7 @@ module VagrantMutate
16
16
 
17
17
  uuid = nil
18
18
  gui = true
19
- disk_bus = 'virtio'
19
+ disk_bus = @input_box.disk_interface
20
20
 
21
21
  image_type = @output_box.image_format
22
22
  disk = @output_box.image_name
@@ -46,9 +46,17 @@ module VagrantMutate
46
46
  error_key(:parse_qemu_version_failed)
47
47
  end
48
48
 
49
- class Errors::DetermineImageSizeFailed < VagrantMutateError
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
- if box_arg =~ /\.box$/
27
- input_box = input_loader.load_from_file(box_arg)
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)
@@ -1,3 +1,3 @@
1
1
  module VagrantMutate
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
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
@@ -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
- <% if disk_bus == 'virtio' %>
28
+ <% if disk_bus == 'virtio' %>
29
29
  <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
30
- <% else %>
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='virtio'/>
26
-
27
- <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
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
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-08 00:00:00.000000000 Z
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