ovfparse 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README +65 -0
- data/lib/ovfparse/esx4_vmrepository.rb +34 -0
- data/lib/ovfparse/esx_repository.rb +34 -0
- data/lib/ovfparse/file_vmrepository.rb +46 -0
- data/lib/ovfparse/ftp_vmrepository.rb +41 -0
- data/lib/ovfparse/http_vmrepository.rb +43 -0
- data/lib/ovfparse/https_vmrepository.rb +14 -0
- data/lib/ovfparse/vc4_vmrepository.rb +70 -0
- data/lib/ovfparse/vc_repository.rb +70 -0
- data/lib/ovfparse/vmpackage.rb +198 -0
- data/lib/ovfparse/vmrepository.rb +80 -0
- data/lib/ovfparse.rb +16 -0
- data/lib/test.rb +98 -0
- metadata +87 -0
data/README
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
Project: ovfparse
|
2
|
+
|
3
|
+
Website: http://github.com/ruby-ovf/ovfparse
|
4
|
+
License: GPLv3
|
5
|
+
Mailing list: ruby-ovf@googlegroups.com
|
6
|
+
Source Code: git://github.com/ruby-ovf/ovfparse.git
|
7
|
+
|
8
|
+
== Requirements
|
9
|
+
---------------
|
10
|
+
- ruby
|
11
|
+
- net/ftp
|
12
|
+
- net/http
|
13
|
+
- net/https
|
14
|
+
- nokogiri xml parser (native gem)
|
15
|
+
|
16
|
+
== Install
|
17
|
+
----------
|
18
|
+
From inside your ovfparse directory:
|
19
|
+
$ rake gem
|
20
|
+
$ cd pkg
|
21
|
+
$ gem install ovfparse[-version]
|
22
|
+
|
23
|
+
[Coming soon: gem install ovfparse (from rubygems.org)]
|
24
|
+
|
25
|
+
=== Example1
|
26
|
+
------------
|
27
|
+
uri = "file://../test_files"
|
28
|
+
vmRepo = VmRepository.create(uri) #use factory method to get repo class
|
29
|
+
puts "\n\n****************************\n"
|
30
|
+
puts "protocol: " + vmRepo.protocol + "\n"
|
31
|
+
puts "url: " + vmRepo.url + "\n"
|
32
|
+
puts "uri: " + vmRepo.uri + "\n"
|
33
|
+
puts vmRepo.fetch #shows all the packages available at the repo
|
34
|
+
|
35
|
+
|
36
|
+
=== Example2
|
37
|
+
------------
|
38
|
+
# use factory method to get correct package type
|
39
|
+
package = VmPackage.create("http://ambrosia/repo/someOVF.ovf")
|
40
|
+
# retrieve package
|
41
|
+
package.get
|
42
|
+
# spit out package xml
|
43
|
+
puts package.xml
|
44
|
+
|
45
|
+
|
46
|
+
=== Example3
|
47
|
+
------------
|
48
|
+
# use factory method to get correct package type
|
49
|
+
package = VmPackage.create("http://ambrosia/repo/someOVF.ovf")
|
50
|
+
# retrieve package
|
51
|
+
package.get
|
52
|
+
# spit out specific xml section
|
53
|
+
puts package.ProductSection
|
54
|
+
|
55
|
+
== Useful tips
|
56
|
+
-----------
|
57
|
+
'method_missing' is implemented to return xml nodes of the section that is named like the missing method.
|
58
|
+
For example, if your xml has a section called <FirstName>some data</FirstName> you can simply
|
59
|
+
request the object through any of the following methods:
|
60
|
+
|
61
|
+
node = package.first_name()
|
62
|
+
node = package.first_name
|
63
|
+
node = package.FirstName()
|
64
|
+
node = package.FirstName
|
65
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Esx4VmRepository < VmRepository
|
2
|
+
|
3
|
+
def VmRepository.ESXParse(raw_file_list)
|
4
|
+
file_list = Array.new
|
5
|
+
raw_file_list.each { |text_line|
|
6
|
+
if text_line.include? "Name:" then
|
7
|
+
fragment_arr = text_line.split(" ")
|
8
|
+
file = fragment_arr.last
|
9
|
+
file_list.push(file)
|
10
|
+
end
|
11
|
+
}
|
12
|
+
return file_list
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def fetch
|
17
|
+
if protocol.name != "esx4" then
|
18
|
+
return 'error'
|
19
|
+
end
|
20
|
+
|
21
|
+
#retrieve data from filesystem
|
22
|
+
$cmd = VMWARE_LIBS + "/vminfo.pl --url https://" + url + "/sdk/vimService --fields vmname --folder " + VC_FOLDER + " --username " + VC_USER + " --password " + VC_PASS
|
23
|
+
|
24
|
+
pipe = IO.popen $cmd
|
25
|
+
raw_file_list = pipe.read
|
26
|
+
pipe.close
|
27
|
+
|
28
|
+
#parse out package list
|
29
|
+
package_list = VmRepository::ESXParse(raw_file_list)
|
30
|
+
|
31
|
+
#construct package objects based on results
|
32
|
+
return simplePackageConstruction(package_list)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class EsxRepository < Repository
|
2
|
+
|
3
|
+
def Repository.ESXParse(raw_file_list)
|
4
|
+
file_list = Array.new
|
5
|
+
raw_file_list.each { |text_line|
|
6
|
+
if text_line.include? "Name:" then
|
7
|
+
fragment_arr = text_line.split(" ")
|
8
|
+
file = fragment_arr.last
|
9
|
+
file_list.push(file)
|
10
|
+
end
|
11
|
+
}
|
12
|
+
return file_list
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def fetch
|
17
|
+
if protocol.name != "esx4" then
|
18
|
+
return 'error'
|
19
|
+
end
|
20
|
+
|
21
|
+
#retrieve data from filesystem
|
22
|
+
$cmd = VMWARE_LIBS + "/vminfo.pl --url https://" + url + "/sdk/vimService --fields vmname --folder " + VC_FOLDER + " --username " + VC_USER + " --password " + VC_PASS
|
23
|
+
|
24
|
+
pipe = IO.popen $cmd
|
25
|
+
raw_file_list = pipe.read
|
26
|
+
pipe.close
|
27
|
+
|
28
|
+
#parse out package list
|
29
|
+
package_list = Repository::ESXParse(raw_file_list)
|
30
|
+
|
31
|
+
#construct package objects based on results
|
32
|
+
return simplePackageConstruction(package_list)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class FileVmRepository < VmRepository
|
2
|
+
|
3
|
+
def VmRepository.LSParse (raw_file_text)
|
4
|
+
file_list = Array.new
|
5
|
+
raw_file_text.each { |file_text|
|
6
|
+
ALLOWABLE_PKG_TYPES.each { |type|
|
7
|
+
if file_text.include? type then
|
8
|
+
fragment_arr = file_text.split(" ")
|
9
|
+
file = fragment_arr.last
|
10
|
+
file_list.push(file)
|
11
|
+
end
|
12
|
+
}
|
13
|
+
}
|
14
|
+
return file_list
|
15
|
+
end
|
16
|
+
|
17
|
+
def get
|
18
|
+
#TODO slap a '/' char on the end of self.uri if it doesn't have one, otherwise many servers return 403
|
19
|
+
#if linux
|
20
|
+
$cmd = "ls " + @url
|
21
|
+
#if windows
|
22
|
+
#$cmd = "dir " + url
|
23
|
+
#
|
24
|
+
|
25
|
+
pipe = IO.popen $cmd
|
26
|
+
raw_file_list = pipe.read
|
27
|
+
pipe.close
|
28
|
+
|
29
|
+
return raw_file_list
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def fetch
|
34
|
+
#retrieve data from file system
|
35
|
+
raw_file_list = get
|
36
|
+
|
37
|
+
#parse out package list
|
38
|
+
#if linux
|
39
|
+
package_list = VmRepository::LSParse(raw_file_list)
|
40
|
+
#if windows
|
41
|
+
#package_list = Repository::DIRParse(file_list)
|
42
|
+
|
43
|
+
#construct package objects based on results
|
44
|
+
return simplePackageConstruction(package_list)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class FtpVmRepository < VmRepository
|
2
|
+
|
3
|
+
def VmRepository.FTParse (raw_text_arr)
|
4
|
+
file_list = Array.new
|
5
|
+
raw_text_arr.each { |file_text|
|
6
|
+
ALLOWABLE_PKG_TYPES.each { |type|
|
7
|
+
if file_text.include? type then
|
8
|
+
fragment_arr = file_text.split(" ")
|
9
|
+
file = fragment_arr.last
|
10
|
+
file_list.push(file)
|
11
|
+
break;
|
12
|
+
end
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return file_list
|
16
|
+
end
|
17
|
+
|
18
|
+
def get
|
19
|
+
#TODO slap a '/' char on the end of self.uri if it doesn't have one, otherwise many servers return 403
|
20
|
+
ftp = Net::FTP.new(url.split("/", 2)[0], "anonymous", "cops-bot@mitre.org")
|
21
|
+
ftp.passive = true
|
22
|
+
ftp.chdir(url.split("/", 2)[1])
|
23
|
+
raw_text_arr = ftp.list()
|
24
|
+
ftp.quit()
|
25
|
+
return raw_text_arr
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch
|
29
|
+
#retrieve data from ftp server
|
30
|
+
raw_text_arr = get
|
31
|
+
|
32
|
+
if (raw_text_arr)
|
33
|
+
#parse out package list from index html
|
34
|
+
package_list = VmRepository::FTParse(raw_text_arr)
|
35
|
+
|
36
|
+
#construct package objects based on results
|
37
|
+
return simplePackageConstruction(package_list)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class HttpVmRepository < VmRepository
|
2
|
+
|
3
|
+
def VmRepository.HTTParse (raw_html)
|
4
|
+
file_list = Array.new
|
5
|
+
raw_html.each("</a>") { |file_text|
|
6
|
+
ALLOWABLE_PKG_TYPES.each { |type|
|
7
|
+
if file_text.include? type then
|
8
|
+
fragment = file_text.split("</a>")
|
9
|
+
split_expr = (type + "\">")
|
10
|
+
file = fragment[0].split(split_expr)
|
11
|
+
file_list.push(file[1])
|
12
|
+
break
|
13
|
+
end
|
14
|
+
}
|
15
|
+
}
|
16
|
+
return file_list
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def get
|
21
|
+
#TODO slap a '/' char on the end of self.uri if it doesn't have one, otherwise many servers return 403
|
22
|
+
url = URI.parse(URI.escape(self.uri))
|
23
|
+
req = Net::HTTP::Get.new(url.path)
|
24
|
+
res = Net::HTTP.start(url.host, url.port) {|http|
|
25
|
+
http.request(req)
|
26
|
+
}
|
27
|
+
res.body
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def fetch
|
32
|
+
#retrieve data from http server
|
33
|
+
if (raw_html = get)
|
34
|
+
|
35
|
+
#parse out package list from index html
|
36
|
+
package_list = VmRepository::HTTParse(raw_html)
|
37
|
+
|
38
|
+
#construct package objects based on results
|
39
|
+
return simplePackageConstruction(package_list)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class HttpsVmRepository < HttpVmRepository
|
2
|
+
|
3
|
+
def get
|
4
|
+
#TODO slap a '/' char on the end of self.uri if it doesn't have one, otherwise many servers return 403
|
5
|
+
url = URI.parse(URI.escape(self.uri))
|
6
|
+
http = Net::HTTP.new(url.host, url.port)
|
7
|
+
req = Net::HTTP::Get.new(url.path)
|
8
|
+
http.use_ssl = true
|
9
|
+
#req.basic_auth username, password
|
10
|
+
response = http.request(req)
|
11
|
+
return response.body
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class Vc4VmRepository < VmRepository
|
2
|
+
|
3
|
+
def vcPackageConstruction(raw_file_list)
|
4
|
+
packages = Array.new
|
5
|
+
|
6
|
+
cur_name = ''
|
7
|
+
cur_template = "0"
|
8
|
+
cur_guest = ''
|
9
|
+
|
10
|
+
raw_file_list.each { |text_line|
|
11
|
+
# signifies a new group of information about a machine
|
12
|
+
if text_line=="\n" then
|
13
|
+
cur_name = ''
|
14
|
+
cur_template = "0"
|
15
|
+
cur_guest = ''
|
16
|
+
cur_path = ''
|
17
|
+
elsif text_line.include? "vmPathName" then
|
18
|
+
fragment_arr = text_line.split(" ")
|
19
|
+
cur_path = fragment_arr.last
|
20
|
+
#puts "vmPathName<" + text_line + "|" + cur_path + ">"
|
21
|
+
elsif text_line.include? "Name:" then
|
22
|
+
fragment_arr = text_line.split(" ")
|
23
|
+
cur_name = fragment_arr.last
|
24
|
+
#puts "Name<" + text_line + "|" + cur_name + ">"
|
25
|
+
elsif text_line.include? "Template:"
|
26
|
+
fragment_arr = text_line.split(" ")
|
27
|
+
cur_template = fragment_arr.last
|
28
|
+
#puts "Template<" + text_line + "|" + cur_template + ">"
|
29
|
+
elsif text_line.include? "Guest OS:"
|
30
|
+
fragment_arr = text_line.split("Guest OS:")
|
31
|
+
cur_guest = fragment_arr.last.strip!
|
32
|
+
#puts "Guest<" + text_line + "|" + cur_guest + ">"
|
33
|
+
if cur_template=="1"
|
34
|
+
package = Package.new
|
35
|
+
package.name = cur_name
|
36
|
+
package.description = 'no description available'
|
37
|
+
package.guest_os = cur_guest
|
38
|
+
package.uri = "jbtest" #self.uri + "/" + path
|
39
|
+
package.version = 'Unknown'
|
40
|
+
package.state_id = 1
|
41
|
+
package.repository_id = id
|
42
|
+
packages.push(package)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
#noop
|
46
|
+
end
|
47
|
+
}
|
48
|
+
return packages
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def fetch
|
53
|
+
if protocol.name != "vc4" then
|
54
|
+
return 'error'
|
55
|
+
end
|
56
|
+
|
57
|
+
#retrieve data from filesystem
|
58
|
+
$cmd = VMWARE_LIBS + "/vminfo.pl --url https://" + url + "/sdk/vimService --host xenadu1.mitre.org --folder " + VC_FOLDER + " --username " + VC_USER + " --password " + VC_PASS
|
59
|
+
pipe = IO.popen $cmd
|
60
|
+
raw_file_list = pipe.read
|
61
|
+
pipe.close
|
62
|
+
|
63
|
+
#parse out package list
|
64
|
+
package_list = vcPackageConstruction(raw_file_list)
|
65
|
+
|
66
|
+
return package_list
|
67
|
+
#construct package objects based on results
|
68
|
+
#return simplePackageConstruction(package_list)
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class VcRepository < Repository
|
2
|
+
|
3
|
+
def vcPackageConstruction(raw_file_list)
|
4
|
+
packages = Array.new
|
5
|
+
|
6
|
+
cur_name = ''
|
7
|
+
cur_template = "0"
|
8
|
+
cur_guest = ''
|
9
|
+
|
10
|
+
raw_file_list.each { |text_line|
|
11
|
+
# signifies a new group of information about a machine
|
12
|
+
if text_line=="\n" then
|
13
|
+
cur_name = ''
|
14
|
+
cur_template = "0"
|
15
|
+
cur_guest = ''
|
16
|
+
cur_path = ''
|
17
|
+
elsif text_line.include? "vmPathName" then
|
18
|
+
fragment_arr = text_line.split(" ")
|
19
|
+
cur_path = fragment_arr.last
|
20
|
+
#puts "vmPathName<" + text_line + "|" + cur_path + ">"
|
21
|
+
elsif text_line.include? "Name:" then
|
22
|
+
fragment_arr = text_line.split(" ")
|
23
|
+
cur_name = fragment_arr.last
|
24
|
+
#puts "Name<" + text_line + "|" + cur_name + ">"
|
25
|
+
elsif text_line.include? "Template:"
|
26
|
+
fragment_arr = text_line.split(" ")
|
27
|
+
cur_template = fragment_arr.last
|
28
|
+
#puts "Template<" + text_line + "|" + cur_template + ">"
|
29
|
+
elsif text_line.include? "Guest OS:"
|
30
|
+
fragment_arr = text_line.split("Guest OS:")
|
31
|
+
cur_guest = fragment_arr.last.strip!
|
32
|
+
#puts "Guest<" + text_line + "|" + cur_guest + ">"
|
33
|
+
if cur_template=="1"
|
34
|
+
package = Package.new
|
35
|
+
package.name = cur_name
|
36
|
+
package.description = 'no description available'
|
37
|
+
package.guest_os = cur_guest
|
38
|
+
package.uri = "jbtest" #self.uri + "/" + path
|
39
|
+
package.version = 'Unknown'
|
40
|
+
package.state_id = 1
|
41
|
+
package.repository_id = id
|
42
|
+
packages.push(package)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
#noop
|
46
|
+
end
|
47
|
+
}
|
48
|
+
return packages
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def fetch
|
53
|
+
if protocol.name != "vc4" then
|
54
|
+
return 'error'
|
55
|
+
end
|
56
|
+
|
57
|
+
#retrieve data from filesystem
|
58
|
+
$cmd = VMWARE_LIBS + "/vminfo.pl --url https://" + url + "/sdk/vimService --host xenadu1.mitre.org --folder " + VC_FOLDER + " --username " + VC_USER + " --password " + VC_PASS
|
59
|
+
pipe = IO.popen $cmd
|
60
|
+
raw_file_list = pipe.read
|
61
|
+
pipe.close
|
62
|
+
|
63
|
+
#parse out package list
|
64
|
+
package_list = vcPackageConstruction(raw_file_list)
|
65
|
+
|
66
|
+
return package_list
|
67
|
+
#construct package objects based on results
|
68
|
+
#return simplePackageConstruction(package_list)
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
class VmPackage
|
2
|
+
@url
|
3
|
+
@name
|
4
|
+
@version
|
5
|
+
@protocol
|
6
|
+
@size
|
7
|
+
@xml
|
8
|
+
|
9
|
+
|
10
|
+
OVA = 0
|
11
|
+
OVF = 1
|
12
|
+
ISO = 2
|
13
|
+
|
14
|
+
@type = nil
|
15
|
+
|
16
|
+
UNKNOWN = 0
|
17
|
+
INSTALLED = 1
|
18
|
+
NOT_INSTALLED = 2
|
19
|
+
UNINSTALLED = 3
|
20
|
+
COPYING = 4
|
21
|
+
BOOTING = 5
|
22
|
+
CONFIGURING = 6
|
23
|
+
|
24
|
+
OVF_NAMESPACE = {'ovf' => 'http://schemas.dmtf.org/ovf/envelope/1'}
|
25
|
+
|
26
|
+
@state = UNKNOWN
|
27
|
+
|
28
|
+
attr_accessor :url, :name, :version, :state, :protocol, :size, :xml
|
29
|
+
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
# (@name + " from " + @url + "\n")
|
36
|
+
self.uri
|
37
|
+
end
|
38
|
+
|
39
|
+
def uri
|
40
|
+
if (nil==@protocol) then
|
41
|
+
return @url
|
42
|
+
else
|
43
|
+
return (@protocol + "://" + @url)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(uri)
|
48
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
49
|
+
@url.sub!(/^\/{0,2}/, '')
|
50
|
+
@protocol.downcase
|
51
|
+
@url.downcase
|
52
|
+
@name = uri.split('/').last
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.create uri
|
56
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
57
|
+
@url.sub!(/^\/{0,2}/, '')
|
58
|
+
@protocol.downcase
|
59
|
+
@url.downcase
|
60
|
+
|
61
|
+
if @protocol=='ftp'
|
62
|
+
FtpVmPackage.new(uri)
|
63
|
+
elsif @protocol=='http'
|
64
|
+
HttpVmPackage.new(uri)
|
65
|
+
elsif @protocol=='https'
|
66
|
+
HttpsVmPackage.new(uri)
|
67
|
+
elsif @protocol=='file'
|
68
|
+
FileVmPackage.new(uri)
|
69
|
+
elsif @protocol.match(/esx/)
|
70
|
+
if @protocol.match(/esx4/)
|
71
|
+
Esx4VmPackage.new(uri)
|
72
|
+
else
|
73
|
+
raise NotImplementedError, "Cannot handle this version of ESX: " + @protocol + "\n"
|
74
|
+
end
|
75
|
+
elsif @protocol.match(/vc/)
|
76
|
+
if @protocol.match(/vc4/)
|
77
|
+
Vc4VmPackage.new(uri)
|
78
|
+
else
|
79
|
+
raise NotImplementedError, "Cannot handle this version of VirtualCenter: " + @protocol + "\n"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
raise NotImplementedError, "Unknown Protocol: " + @protocol + " (bad URI string?)\n"
|
83
|
+
VmRepository.new(uri)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
def fetch
|
89
|
+
end
|
90
|
+
|
91
|
+
def referenced_file(element)
|
92
|
+
@xml.xpath("//ovf:References/ovf:File[@ovf:id='#{element['fileRef']}']", OVF_NAMESPACE).first
|
93
|
+
end
|
94
|
+
|
95
|
+
def method_missing(method)
|
96
|
+
puts "WARNING: NoSuchMethod Error: " + method.to_s + " ...trying XPath query \n"
|
97
|
+
|
98
|
+
# try with namespace
|
99
|
+
data = @xml.xpath("//ovf:" + method.to_s)
|
100
|
+
|
101
|
+
|
102
|
+
# try without namespace
|
103
|
+
if nil===data then
|
104
|
+
data = @xml.xpath("//" + method.to_s)
|
105
|
+
end
|
106
|
+
|
107
|
+
# try changing method name without namespace
|
108
|
+
# i.e. egg_and_ham.classify #=> "EggAndHam"
|
109
|
+
if nil==data then
|
110
|
+
data = @xml.xpath("//" + method.to_s.classify)
|
111
|
+
end
|
112
|
+
|
113
|
+
# try changing method name with namespace
|
114
|
+
# i.e. egg_and_ham.classify #=> "EggAndHam"
|
115
|
+
if nil==data then
|
116
|
+
data = @xml.xpath("//ovf:" + method.to_s.classify)
|
117
|
+
end
|
118
|
+
|
119
|
+
return data
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
class HttpVmPackage < VmPackage
|
127
|
+
def fetch
|
128
|
+
url = URI.parse(URI.escape(self.uri))
|
129
|
+
Net::HTTP.start(url.host) { |http|
|
130
|
+
resp = http.get(url.path)
|
131
|
+
open(@name, "wb") { |file|
|
132
|
+
file.write(resp.body)
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
@xml = Nokogiri::XML(File.open(@name)) do |config|
|
137
|
+
config.strict.noent
|
138
|
+
config.strict
|
139
|
+
end
|
140
|
+
|
141
|
+
File.unlink(@name)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class HttpsVmPackage < VmPackage
|
146
|
+
def fetch
|
147
|
+
url = URI.parse(URI.escape(self.uri))
|
148
|
+
http = Net::HTTP.new(url.host, url.port)
|
149
|
+
req = Net::HTTP::Get.new(url.path)
|
150
|
+
http.use_ssl = true
|
151
|
+
response = http.request(req)
|
152
|
+
open(@name, "wb") { |file|
|
153
|
+
file.write(response.body)
|
154
|
+
}
|
155
|
+
|
156
|
+
@xml = Nokogiri::XML(File.open(@name)) do |config|
|
157
|
+
# config.options = Nokogiri::XML::ParseOptions.STRICT | Nokogiri::XML::ParseOptions.NOENT
|
158
|
+
config.strict.noent
|
159
|
+
config.strict
|
160
|
+
end
|
161
|
+
|
162
|
+
File.unlink(@name)
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
class FtpVmPackage < VmPackage
|
169
|
+
def fetch
|
170
|
+
url = URI.parse(URI.escape(self.uri))
|
171
|
+
ftp = Net::FTP.new(url.host, "anonymous", "cops-bot@mitre.org")
|
172
|
+
ftp.passive = true
|
173
|
+
ftp.getbinaryfile(url.path, @name, 1024)
|
174
|
+
ftp.quit()
|
175
|
+
|
176
|
+
@xml = Nokogiri::XML(File.open(@name)) do |config|
|
177
|
+
config.strict.noent
|
178
|
+
config.strict
|
179
|
+
end
|
180
|
+
|
181
|
+
File.unlink(@name)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class FileVmPackage < VmPackage
|
186
|
+
def fetch
|
187
|
+
@xml = Nokogiri::XML(File.open(self.url)) do |config|
|
188
|
+
config.strict.noent
|
189
|
+
config.strict
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class Esx4VmPackage < VmPackage
|
195
|
+
end
|
196
|
+
|
197
|
+
class Vc4VmPackage < VmPackage
|
198
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class VmRepository
|
2
|
+
|
3
|
+
STRICT_CHECKING = true
|
4
|
+
USE_CACHE = true
|
5
|
+
# ALLOWABLE_PKG_TYPES = ["ovf", "vmx", "ova"]
|
6
|
+
ALLOWABLE_PKG_TYPES = ["ovf"]
|
7
|
+
# ALLOWABLE_PROTOCOLS = ["ftp", "http", "https", "file", "smb", "esx4", "vc4"]
|
8
|
+
ALLOWABLE_PROTOCOLS = ["ftp", "http", "https", "file"]
|
9
|
+
|
10
|
+
@url = ''
|
11
|
+
@protocol = ''
|
12
|
+
|
13
|
+
attr_accessor :url, :protocol, :repo
|
14
|
+
|
15
|
+
def initialize(uri)
|
16
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
17
|
+
@url.sub!(/^\/{0,2}/, '')
|
18
|
+
@protocol.downcase
|
19
|
+
@url.downcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create uri
|
23
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
24
|
+
@url.sub!(/^\/{0,2}/, '')
|
25
|
+
@protocol.downcase
|
26
|
+
@url.downcase
|
27
|
+
|
28
|
+
if @protocol=='ftp'
|
29
|
+
FtpVmRepository.new(uri)
|
30
|
+
elsif @protocol=='http'
|
31
|
+
HttpVmRepository.new(uri)
|
32
|
+
elsif @protocol=='https'
|
33
|
+
HttpsVmRepository.new(uri)
|
34
|
+
elsif @protocol=='file'
|
35
|
+
FileVmRepository.new(uri)
|
36
|
+
elsif @protocol.match(/esx/)
|
37
|
+
if @protocol.match(/esx4/)
|
38
|
+
Esx4VmRepository.new(uri)
|
39
|
+
else
|
40
|
+
raise NotImplementedError, "Cannot handle this version of ESX: " + @protocol + "\n"
|
41
|
+
end
|
42
|
+
elsif @protocol.match(/vc/)
|
43
|
+
if @protocol.match(/vc4/)
|
44
|
+
Vc4VmRepository.new(uri)
|
45
|
+
else
|
46
|
+
raise NotImplementedError, "Cannot handle this version of VirtualCenter: " + @protocol + "\n"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise NotImplementedError, "Unknown Repository Protocol: " + @protocol + " (bad URI string?)\n"
|
50
|
+
VmRepository.new(uri)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def uri
|
55
|
+
if (nil==protocol) then
|
56
|
+
return url
|
57
|
+
else
|
58
|
+
return (protocol + "://" + url)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get
|
63
|
+
end
|
64
|
+
|
65
|
+
def fetch
|
66
|
+
end
|
67
|
+
|
68
|
+
def simplePackageConstruction(package_list)
|
69
|
+
packages = Array.new
|
70
|
+
package_list.each { |p|
|
71
|
+
package = VmPackage.create(self.uri + "/" + p)
|
72
|
+
package.name = p
|
73
|
+
package.state = VmPackage::UNKNOWN
|
74
|
+
packages.push(package)
|
75
|
+
}
|
76
|
+
|
77
|
+
return packages
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/ovfparse.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'net/ftp'
|
4
|
+
require 'net/http'
|
5
|
+
require 'net/https'
|
6
|
+
|
7
|
+
path = File.expand_path(File.dirname(__FILE__))
|
8
|
+
|
9
|
+
require path + '/ovfparse/vmrepository'
|
10
|
+
require path + '/ovfparse/vmpackage'
|
11
|
+
require path + '/ovfparse/esx4_vmrepository'
|
12
|
+
require path + '/ovfparse/file_vmrepository'
|
13
|
+
require path + '/ovfparse/ftp_vmrepository'
|
14
|
+
require path + '/ovfparse/http_vmrepository'
|
15
|
+
require path + '/ovfparse/https_vmrepository'
|
16
|
+
require path + '/ovfparse/vc4_vmrepository'
|
data/lib/test.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'ovfparse'
|
3
|
+
|
4
|
+
uri = "file:///Users/ideshmukh/workspace/cops/ovfparse/test_files"
|
5
|
+
vmRepo = VmRepository.create(uri)
|
6
|
+
puts "\n\n****************************\n"
|
7
|
+
puts "protocol: " + vmRepo.protocol + "\n"
|
8
|
+
puts "url: " + vmRepo.url + "\n"
|
9
|
+
puts "uri: " + vmRepo.uri + "\n"
|
10
|
+
packages = vmRepo.fetch
|
11
|
+
puts "packages: " + packages.to_s + "\n"
|
12
|
+
pkg = packages[1]
|
13
|
+
puts "selected package: " + pkg.to_s + "\n"
|
14
|
+
pkg.fetch
|
15
|
+
puts pkg.xml
|
16
|
+
puts "\n\n****************************\n"
|
17
|
+
|
18
|
+
# uri = "http://localhost/repo/"
|
19
|
+
# vmRepo = VmRepository.create(uri)
|
20
|
+
# puts "\n\n****************************\n"
|
21
|
+
# puts "protocol: " + vmRepo.protocol + "\n"
|
22
|
+
# puts "url: " + vmRepo.url + "\n"
|
23
|
+
# puts "uri: " + vmRepo.uri + "\n"
|
24
|
+
# packages = vmRepo.fetch
|
25
|
+
# ovfTest = packages[1]
|
26
|
+
# ovfTest.fetch
|
27
|
+
# puts ovfTest.xml
|
28
|
+
#
|
29
|
+
# repo = VmRepository.create(nil)
|
30
|
+
# puts repo.inspect
|
31
|
+
#
|
32
|
+
# repo = VmRepository.create("http://cops-af-lib.mitre.org/") #shouldn't it uri and not url?
|
33
|
+
# repo = VmRepository.create("http://ambrosia.mitre.org/repo/") #shouldn't it uri and not url?
|
34
|
+
#
|
35
|
+
# ovfs = repo.fetch
|
36
|
+
# ovfs.each { |ovf|
|
37
|
+
# ovf.fetch
|
38
|
+
# products = ovf.ProductSection #equivalent to: (ovf.xml/'ProductSection')
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# package = VmPackage.create("file://ambrosia/public/vmlib/someOVF.ovf")
|
42
|
+
# package = VmPackage.create("http://cops-af-lib.mitre.org//Base OS Package (jeos)-Ubuntu-20090917.ovf")
|
43
|
+
# package.get
|
44
|
+
# puts package.xml
|
45
|
+
# puts package.ProductSection
|
46
|
+
#
|
47
|
+
# uri = "https://localhost/repo/"
|
48
|
+
# vmRepo = VmRepository.create(uri)
|
49
|
+
# puts "\n\n****************************\n"
|
50
|
+
# puts "protocol: " + vmRepo.protocol + "\n"
|
51
|
+
# puts "url: " + vmRepo.url + "\n"
|
52
|
+
# puts "uri: " + vmRepo.uri + "\n"
|
53
|
+
# packages = vmRepo.fetch
|
54
|
+
# ovfTest = packages[1]
|
55
|
+
# ovfTest.get
|
56
|
+
# puts ovfTest.xml
|
57
|
+
#
|
58
|
+
# uri = "ftp://localhost/repo"
|
59
|
+
# vmRepo = VmRepository.create(uri)
|
60
|
+
# puts "\n\n****************************\n"
|
61
|
+
# puts "protocol: " + vmRepo.protocol + "\n"
|
62
|
+
# puts "url: " + vmRepo.url + "\n"
|
63
|
+
# puts "uri: " + vmRepo.uri + "\n"
|
64
|
+
# packages = vmRepo.fetch
|
65
|
+
# ovfTest = packages[1]
|
66
|
+
# ovfTest.get
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
#uri = "esx4://test.com/test"
|
71
|
+
#vmRepo = VmRepository.new(uri)
|
72
|
+
#puts "\n\n****************************\n"
|
73
|
+
#puts "protocol: " + vmRepo.protocol + "\n"
|
74
|
+
#puts "url: " + vmRepo.url + "\n"
|
75
|
+
#puts "uri: " + vmRepo.uri + "\n"
|
76
|
+
#
|
77
|
+
#uri = "vc4://test.com/test"
|
78
|
+
#vmRepo = VmRepository.new(uri)
|
79
|
+
#puts "\n\n****************************\n"
|
80
|
+
#puts "protocol: " + vmRepo.protocol + "\n"
|
81
|
+
#puts "url: " + vmRepo.url + "\n"
|
82
|
+
#puts "uri: " + vmRepo.uri + "\n"
|
83
|
+
#
|
84
|
+
#
|
85
|
+
|
86
|
+
|
87
|
+
#########################################
|
88
|
+
# THESE SHOULD THROW EXCEPTIONS
|
89
|
+
# #######################################
|
90
|
+
#uri = "esx://test.com/test"
|
91
|
+
#vmRepo = VmRepository.new(uri)
|
92
|
+
|
93
|
+
#uri = "vc://test.com/test"
|
94
|
+
#vmRepo = VmRepository.new(uri)
|
95
|
+
|
96
|
+
#uri = "unknown://test.com/test"
|
97
|
+
#vmRepo = VmRepository.new(uri)
|
98
|
+
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ovfparse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Jim Barkley
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-21 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: nokogiri
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 4
|
30
|
+
- 1
|
31
|
+
version: 1.4.1
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Uses net/* libraries and nokogiri xml parser to reach out and retrieve .ovf or .ova packages and parse them.
|
35
|
+
email: jbarkley@mitre.org
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README
|
42
|
+
files:
|
43
|
+
- lib/ovfparse/esx4_vmrepository.rb
|
44
|
+
- lib/ovfparse/esx_repository.rb
|
45
|
+
- lib/ovfparse/file_vmrepository.rb
|
46
|
+
- lib/ovfparse/ftp_vmrepository.rb
|
47
|
+
- lib/ovfparse/http_vmrepository.rb
|
48
|
+
- lib/ovfparse/https_vmrepository.rb
|
49
|
+
- lib/ovfparse/vc4_vmrepository.rb
|
50
|
+
- lib/ovfparse/vc_repository.rb
|
51
|
+
- lib/ovfparse/vmpackage.rb
|
52
|
+
- lib/ovfparse/vmrepository.rb
|
53
|
+
- lib/ovfparse.rb
|
54
|
+
- lib/test.rb
|
55
|
+
- README
|
56
|
+
has_rdoc: true
|
57
|
+
homepage: http://github.com/ruby-ovf/ovfparse
|
58
|
+
licenses: []
|
59
|
+
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.3.6
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Retrieves and parses files in the Open Virtualization Format
|
86
|
+
test_files: []
|
87
|
+
|