ovfparse 0.0.7
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/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
|
+
|