diskid 0.1.3 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +35 -6
- data/Rakefile +1 -0
- data/bin/diskid +46 -22
- data/bin/diskid-ws +31 -16
- data/lib/diskid.rb +68 -1
- metadata +29 -18
data/README.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# DiskID
|
2
2
|
|
3
|
+
Get info from a virtual disk file.
|
4
|
+
|
5
|
+
$ diskid micro-frameos.vmdk
|
6
|
+
|
7
|
+
diskid.frameos.org
|
8
|
+
|
9
|
+
file name: micro-frameos.vmdk
|
10
|
+
file format: vmdk
|
11
|
+
virtual size: 1.2G (1287651328 bytes)
|
12
|
+
disk size: 274M (287593984 bytes)
|
13
|
+
|
3
14
|
## Installation
|
4
15
|
|
5
16
|
gem install diskid
|
@@ -10,9 +21,9 @@ Internet access is also required, as diskid sends a few bytes to http://diskid.f
|
|
10
21
|
|
11
22
|
## Usage
|
12
23
|
|
13
|
-
diskid
|
24
|
+
diskid --help
|
14
25
|
|
15
|
-
|
26
|
+
### EXAMPLES
|
16
27
|
|
17
28
|
$ diskid ubuntu64-1104.vmdk
|
18
29
|
|
@@ -20,15 +31,33 @@ i.e.
|
|
20
31
|
|
21
32
|
file name: ubuntu64-1104.vmdk
|
22
33
|
file format: vmdk
|
23
|
-
virtual size: 9.0G
|
24
|
-
disk size: 319M
|
34
|
+
virtual size: 9.0G
|
35
|
+
disk size: 319M
|
25
36
|
|
26
37
|
|
27
38
|
PROTIP: You don't need to install diskid to use the service
|
28
39
|
|
29
|
-
head -n 20 ubuntu64-1104.vmdk > /tmp/dchunk && curl -X POST -F chunk=@/tmp/dchunk http://diskid.frameos.org
|
40
|
+
head -n 20 ubuntu64-1104.vmdk > /tmp/dchunk && curl -X POST -F chunk=@/tmp/dchunk http://diskid.frameos.org/?format=text
|
30
41
|
|
42
|
+
JSON output:
|
31
43
|
|
44
|
+
$ diskid --format json ubuntu64-1104.vmdk
|
45
|
+
|
46
|
+
diskid.frameos.org
|
47
|
+
|
48
|
+
{"file_name":"ubuntu64-1104.vmdk","format":"vmdk","virtual_size":"9.0G","disk_size":"319M"}
|
49
|
+
|
50
|
+
Valid output formats:
|
51
|
+
|
52
|
+
* json
|
53
|
+
* text
|
54
|
+
* xml
|
55
|
+
|
56
|
+
## NERD STUFF
|
57
|
+
|
58
|
+
DiskID Webservice is a thin wrapper around the bleeding edge version of qemu-img from the QEMU project: http://qemu.org
|
59
|
+
|
60
|
+
All the magic happens there!
|
32
61
|
|
33
62
|
Copyright (c) 2011 Sergio Rubio. See LICENSE.txt for
|
34
63
|
further details.
|
data/Rakefile
CHANGED
@@ -19,6 +19,7 @@ Jeweler::Tasks.new do |gem|
|
|
19
19
|
gem.add_runtime_dependency 'clamp'
|
20
20
|
gem.add_runtime_dependency 'alchemist'
|
21
21
|
gem.add_runtime_dependency 'rest-client'
|
22
|
+
gem.add_runtime_dependency 'json'
|
22
23
|
# dependencies defined in Gemfile
|
23
24
|
end
|
24
25
|
Jeweler::RubygemsDotOrgTasks.new
|
data/bin/diskid
CHANGED
@@ -2,30 +2,54 @@
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'clamp'
|
4
4
|
require 'rest-client'
|
5
|
+
require 'alchemist'
|
6
|
+
require 'diskid'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
puts "Supported formats: vvfat vpc vmdk vdi sheepdog raw host_cdrom host_floppy host_device file qed qcow2 qcow parallels nbd dmg tftp ftps ftp https http cow cloop bochs blkverify blkdebug"
|
12
|
-
exit 1
|
13
|
-
end
|
14
|
-
host = 'diskid.frameos.org'
|
8
|
+
class DiskIDCommand < Clamp::Command
|
9
|
+
parameter 'FILE', "Disk file", :attribute_name => 'file'
|
10
|
+
option '--server-port', "PORT", "DiskID service port", :default => '80'
|
11
|
+
option '--server-host', "HOST", "DiskID service host", :default => 'diskid.frameos.org'
|
12
|
+
option '--format', "FORMAT", "Disk info output format (text, json, xml)", :default => 'text'
|
15
13
|
|
16
|
-
puts "\n#{host}\n\n"
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
def execute
|
16
|
+
|
17
|
+
if file.nil? or not File.exist?(file)
|
18
|
+
puts
|
19
|
+
puts "Usage: diskid path-to-disk-file"
|
20
|
+
puts
|
21
|
+
puts "Supported formats: vvfat vpc vmdk vdi sheepdog raw host_cdrom host_floppy host_device file qed qcow2 qcow parallels nbd dmg tftp ftps ftp https http cow cloop bochs blkverify blkdebug"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "\n#{server_host}\n\n"
|
26
|
+
|
27
|
+
begin
|
28
|
+
RestClient.get "http://#{server_host}:#{server_port}/service-check"
|
29
|
+
rescue => e
|
30
|
+
$stderr.puts "Couldn't reach http://#{server_host}."
|
31
|
+
exit 1
|
32
|
+
end
|
24
33
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
fsize = File.size(file).bytes.to.megabytes.to_f.round
|
35
|
+
unit = 'M'
|
36
|
+
if fsize > 1024
|
37
|
+
fsize = fsize.megabytes.to.gigabytes.to_f.round
|
38
|
+
unit = 'G'
|
39
|
+
end
|
40
|
+
|
41
|
+
fsize = "#{fsize}#{unit}"
|
42
|
+
|
43
|
+
#out = `head -n 20 #{file}|curl -s -X POST -F client_version=#{DiskID::VERSION} -F chunk=@- -F file_size=#{fsize} -F file_name=#{File.basename(file)} http://#{server_host}:#{server_port}/?format=#{format} 2>&1`
|
44
|
+
out = RestClient.post "http://#{server_host}:#{server_port}/",
|
45
|
+
:chunk => File.read(file, 20000),
|
46
|
+
:client_version => DiskID::VERSION,
|
47
|
+
:file_size => fsize,
|
48
|
+
:file_name => File.basename(file),
|
49
|
+
:format => format
|
50
|
+
puts out
|
51
|
+
end
|
31
52
|
end
|
53
|
+
|
54
|
+
DiskIDCommand.run
|
55
|
+
|
data/bin/diskid-ws
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'sinatra'
|
3
3
|
require 'alchemist'
|
4
|
+
require 'diskid'
|
4
5
|
|
5
6
|
DOCS = """
|
6
7
|
<h1>Virtual Disk Identification Service</h1>
|
@@ -33,31 +34,41 @@ This web service gives you info about a virtual disk file.
|
|
33
34
|
class DiskIDWS < Sinatra::Base
|
34
35
|
|
35
36
|
post '/' do
|
37
|
+
# post using CURL
|
36
38
|
tmpfile = params[:chunk][:tempfile] rescue nil
|
39
|
+
# File was posted using diskid client
|
40
|
+
if not tmpfile
|
41
|
+
tmpfile = File.open("/tmp/diskid_#{Time.now.to_i}", 'w+')
|
42
|
+
tmpfile.write(params[:chunk])
|
43
|
+
end
|
37
44
|
file_name = (params[:file_name] || '') rescue ''
|
38
45
|
|
39
46
|
if tmpfile.nil?
|
40
47
|
halt 400, "Couldn't understand the file you sent me dude."
|
41
48
|
end
|
42
|
-
file_size = params[:file_size]
|
43
|
-
out = `qemu-img-bleeding info #{tmpfile.path}`
|
44
|
-
if $? != 0
|
45
|
-
halt 400, "Couldn't understand the file you sent me dude."
|
46
|
-
end
|
47
|
-
|
49
|
+
file_size = params[:file_size] || ''
|
48
50
|
begin
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
inspector = DiskID::Inspector.new(tmpfile.path)
|
52
|
+
di = inspector.inspect
|
53
|
+
di.file_name = file_name
|
54
|
+
di.disk_size = file_size
|
55
|
+
if params[:format] == 'json'
|
56
|
+
buf = di.to_json
|
57
|
+
elsif params[:format] == 'xml'
|
58
|
+
buf = di.to_xml
|
53
59
|
else
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
out = di.to_hash
|
61
|
+
buf = ''
|
62
|
+
if file_name.empty?
|
63
|
+
buf << "\nSome fields are being omitted and 'disk size:' won't be accurate.\n"
|
64
|
+
buf << "Use diskid command for better results\n\n"
|
65
|
+
else
|
66
|
+
buf << "file_name: #{file_name}\n"
|
67
|
+
end
|
68
|
+
out.each do |k,v|
|
69
|
+
buf << "#{k}: #{v}\n" if k != 'file_name'
|
70
|
+
end
|
58
71
|
end
|
59
|
-
|
60
|
-
buf << "disk size: #{'%.0f' % file_size.to_i.bytes.to.megabytes.to_f}M (#{file_size} bytes)\n"
|
61
72
|
tmpfile.close
|
62
73
|
FileUtils.rm_f tmpfile.path
|
63
74
|
buf
|
@@ -72,6 +83,10 @@ class DiskIDWS < Sinatra::Base
|
|
72
83
|
DOCS
|
73
84
|
end
|
74
85
|
|
86
|
+
get '/' do
|
87
|
+
DOCS
|
88
|
+
end
|
89
|
+
|
75
90
|
error do
|
76
91
|
DOCS
|
77
92
|
end
|
data/lib/diskid.rb
CHANGED
@@ -1,3 +1,70 @@
|
|
1
1
|
module DiskID
|
2
|
-
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
VERSION = "0.2"
|
6
|
+
|
7
|
+
class DiskInfo
|
8
|
+
|
9
|
+
attr_accessor :file_name, :format, :virtual_size, :disk_size
|
10
|
+
|
11
|
+
def initialize(params)
|
12
|
+
@hash = params
|
13
|
+
@file_name = @hash['file_name']
|
14
|
+
@format = @hash['format']
|
15
|
+
@virtual_size = @hash['virtual_size']
|
16
|
+
@disk_size = @hash['disk_size']
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_json
|
20
|
+
to_hash.to_json
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml
|
24
|
+
buf = ""
|
25
|
+
buf << "<disk_info>"
|
26
|
+
buf << "<file_name>#{@file_name}</file_name>"
|
27
|
+
buf << "<format>#{@format}</format>"
|
28
|
+
buf << "<virtual_size>#{@virtual_size}</virtual_size>"
|
29
|
+
buf << "<disk_size>#{@disk_size}</disk_size>"
|
30
|
+
buf << "</disk_info>"
|
31
|
+
buf
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_hash
|
35
|
+
{
|
36
|
+
'file_name' => @file_name,
|
37
|
+
'format' => @format,
|
38
|
+
'virtual_size' => @virtual_size,
|
39
|
+
'disk_size' => @disk_size
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class Inspector
|
46
|
+
|
47
|
+
|
48
|
+
def initialize(file, qemu_img_bin='qemu-img-bleeding')
|
49
|
+
@qemu_img_bin = qemu_img_bin
|
50
|
+
@file = file
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
out = `#{@qemu_img_bin} info #{@file}`
|
55
|
+
raise Exception.new("Error getting info from #{@file}") if $? != 0
|
56
|
+
|
57
|
+
md = /image:(.*)$\nfile format:(.*)$\nvirtual size:(.*)$\ndisk size:(.*)\n/.match out
|
58
|
+
@file_name,@format,@virtual_size,@disk_size = [md[1], md[2], md[3], md[4]].map { |e| e.strip.chomp }
|
59
|
+
@virtual_size = @virtual_size.split()[0]
|
60
|
+
DiskInfo.new({
|
61
|
+
'file_name' => @file_name,
|
62
|
+
'format' => @format,
|
63
|
+
'virtual_size' => @virtual_size,
|
64
|
+
'disk_size' => @disk_size
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
3
70
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diskid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|
16
|
-
requirement: &
|
16
|
+
requirement: &14447600 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *14447600
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &14446900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.0.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *14446900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: jeweler
|
38
|
-
requirement: &
|
38
|
+
requirement: &14446160 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.6.4
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *14446160
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rcov
|
49
|
-
requirement: &
|
49
|
+
requirement: &14445460 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *14445460
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: sinatra
|
60
|
-
requirement: &
|
60
|
+
requirement: &14444720 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *14444720
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: clamp
|
71
|
-
requirement: &
|
71
|
+
requirement: &14443980 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *14443980
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: alchemist
|
82
|
-
requirement: &
|
82
|
+
requirement: &14443500 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *14443500
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rest-client
|
93
|
-
requirement: &
|
93
|
+
requirement: &14443020 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,7 +98,18 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *14443020
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: json
|
104
|
+
requirement: &14442520 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *14442520
|
102
113
|
description: Virtual Disk Identification Service
|
103
114
|
email: rubiojr@frameos.org
|
104
115
|
executables:
|