ovfparse 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ovfparse/vmcollection.rb +455 -0
- data/lib/ovfparse/vmpackage.rb +22 -1
- data/lib/ovfparse.rb +1 -0
- metadata +5 -4
@@ -0,0 +1,455 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
class VmCollection
|
5
|
+
@url
|
6
|
+
@base_path
|
7
|
+
@name
|
8
|
+
@version
|
9
|
+
@protocol
|
10
|
+
@size
|
11
|
+
@xml
|
12
|
+
@package_details
|
13
|
+
@ovf_namespace
|
14
|
+
@default_namespace
|
15
|
+
|
16
|
+
|
17
|
+
attr_accessor :url, :base_path, :name, :version, :state, :protocol, :size, :xml, :references, :diskSection, :networkSection, :virtualSystemCollection, :package_details
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@package_details = Array.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
self.uri
|
25
|
+
end
|
26
|
+
|
27
|
+
def uri
|
28
|
+
if (nil==@protocol) then
|
29
|
+
return @url
|
30
|
+
else
|
31
|
+
return (@protocol + "://" + @url)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(uri)
|
36
|
+
@package_details = Array.new
|
37
|
+
if (URI::HTTP==uri.class) then
|
38
|
+
uri = uri.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
42
|
+
@url.sub!(/^\/{0,2}/, '')
|
43
|
+
@protocol.downcase
|
44
|
+
@url.downcase
|
45
|
+
@name = uri.split('/').last
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.create uri
|
49
|
+
(@protocol, @url) = uri.split(":", 2) unless !uri
|
50
|
+
@url.sub!(/^\/{0,2}/, '')
|
51
|
+
@protocol.downcase
|
52
|
+
@url.downcase
|
53
|
+
#if @protocol=='ftp'
|
54
|
+
# FtpVmPackage.new(uri)
|
55
|
+
if @protocol=='http'
|
56
|
+
HttpVmCollection.new(uri)
|
57
|
+
#elsif @protocol=='https'
|
58
|
+
# HttpsVmPackage.new(uri)
|
59
|
+
elsif @protocol=='file'
|
60
|
+
FileVmCollection.new(uri)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def fetch
|
66
|
+
end
|
67
|
+
|
68
|
+
# Caches all of the base elements inside Envelope for fast access
|
69
|
+
def loadElementRefs
|
70
|
+
children = @xml.root.children
|
71
|
+
@ovf_namespace = xml.root.namespace_definitions.detect{|ns| ns.prefix == "ovf"}
|
72
|
+
@default_namespace = xml.root.namespace
|
73
|
+
|
74
|
+
@references = getChildByName(xml.root, 'References')
|
75
|
+
@virtualSystemCollection = getChildByName(xml.root, 'VirtualSystemCollection')
|
76
|
+
|
77
|
+
@diskSection = getChildByName(xml.root, 'DiskSection') || @virtualSystem.add_previous_sibling(xml.create_element('DiskSection', {}))
|
78
|
+
@networkSection = getChildByName(xml.root, 'NetworkSection') || @virtualSystem.add_previous_sibling(xml.create_element('NetworkSection', {}))
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns the first child node of the passed node whose name matches the passed name.
|
82
|
+
def getChildByName(node, childName)
|
83
|
+
return node.nil? ? nil : node.children.detect{ |element| element.name == childName}
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns every child node of the passed node whose name matches the passed name.
|
87
|
+
def getChildrenByName(node, childName)
|
88
|
+
return node.nil? ? [] : node.children.select{ |element| element.name == childName}
|
89
|
+
end
|
90
|
+
|
91
|
+
def checkschema(schema)
|
92
|
+
response = ""
|
93
|
+
|
94
|
+
isValid = true
|
95
|
+
schema.validate(@xml).each do |error|
|
96
|
+
response << error.message + "\n"
|
97
|
+
isValid = false
|
98
|
+
end
|
99
|
+
|
100
|
+
return [isValid, response]
|
101
|
+
end
|
102
|
+
|
103
|
+
def getVmName
|
104
|
+
return virtualSystem['id'] || ''
|
105
|
+
end
|
106
|
+
|
107
|
+
def getVmDescription
|
108
|
+
# ???
|
109
|
+
end
|
110
|
+
|
111
|
+
def getVmDisks
|
112
|
+
disks = Array.new
|
113
|
+
filenames = Hash.new
|
114
|
+
getChildrenByName(references, 'File').each { |node|
|
115
|
+
filenames[node['id']] = node['href']
|
116
|
+
}
|
117
|
+
|
118
|
+
getChildrenByName(diskSection, 'Disk').each { |node|
|
119
|
+
capacity = node['capacity']
|
120
|
+
units = node['capacityAllocationUnits']
|
121
|
+
if(units == "byte * 2^40")
|
122
|
+
capacity = (capacity.to_i * 1099511627776).to_s
|
123
|
+
elsif(units == "byte * 2^30")
|
124
|
+
capacity = (capacity.to_i * 1073741824).to_s
|
125
|
+
elsif(units == "byte * 2^20")
|
126
|
+
capacity = (capacity.to_i * 1048576).to_s
|
127
|
+
elsif(units == "byte * 2^10")
|
128
|
+
capacity = (capacity.to_i * 1024).to_s
|
129
|
+
end
|
130
|
+
thin_size = node['populatedSize']
|
131
|
+
disks.push({ 'name' => node['diskId'], 'location' => filenames[node['fileRef']], 'size' => capacity, 'thin_size' => (thin_size || "-1") })
|
132
|
+
}
|
133
|
+
|
134
|
+
return disks
|
135
|
+
end
|
136
|
+
|
137
|
+
def getVmNetworks
|
138
|
+
networks = Array.new
|
139
|
+
getChildrenByName(networkSection, 'Network').each { |node|
|
140
|
+
descriptionNode = getChildByName(node, 'Description')
|
141
|
+
text = descriptionNode.nil? ? '' : descriptionNode.text
|
142
|
+
networks.push({'location' => node['name'], 'notes' => text })
|
143
|
+
}
|
144
|
+
return networks
|
145
|
+
end
|
146
|
+
|
147
|
+
def getVirtualSystems
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.constructFromVmPackages(packages)
|
151
|
+
packages.each{ |package|
|
152
|
+
addVmPackage(package)
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
def addVmPackage(package)
|
157
|
+
details = PackageDetails.new()
|
158
|
+
details.id = package.getVmName
|
159
|
+
|
160
|
+
newRefs = package.getVmReferences
|
161
|
+
newRefs.each { |newRef|
|
162
|
+
addFileReference(newRef, package, details)
|
163
|
+
}
|
164
|
+
|
165
|
+
newDisks = package.getVmDisks
|
166
|
+
newDisks.each { |newDisk|
|
167
|
+
addDisk(newDisk, package, details)
|
168
|
+
}
|
169
|
+
|
170
|
+
newNetworks = package.getVmNetworks
|
171
|
+
newNetworks.each { |newNetwork|
|
172
|
+
addNetwork(newNetwork, package, details)
|
173
|
+
}
|
174
|
+
|
175
|
+
package_details.push(details)
|
176
|
+
addVirtualSystem(package.virtualSystem)
|
177
|
+
end
|
178
|
+
|
179
|
+
def addFileReference(pendingRef, childPackage, details)
|
180
|
+
# Compare this one to all the existing ones to prevent duplicates
|
181
|
+
isNewRef = true
|
182
|
+
currentFileRefs = getChildrenByName(references, 'File')
|
183
|
+
currentFileRefs.each{ |oldRef|
|
184
|
+
if(compareFileReferences(oldRef, pendingRef))
|
185
|
+
isNewRef = false
|
186
|
+
break
|
187
|
+
end
|
188
|
+
}
|
189
|
+
|
190
|
+
# If it's not a dup, add it
|
191
|
+
if(isNewRef)
|
192
|
+
newFileID = "file" + (currentFileRefs.length + 1).to_s
|
193
|
+
newFile = references.add_child(xml.create_element('File', {'href' => pendingRef['href'], 'id' => newFileID, 'size' => pendingRef['size']}))
|
194
|
+
newFile.attribute("href").namespace = @ovf_namespace
|
195
|
+
newFile.attribute("id").namespace = @ovf_namespace
|
196
|
+
newFile.attribute("size").namespace = @ovf_namespace
|
197
|
+
findReplace(childPackage, pendingRef['id'], newFileID)
|
198
|
+
details.files.push(newFileID)
|
199
|
+
else
|
200
|
+
details.files.push(pendingRef['href'])
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def compareFileReferences(oldRef, newRef)
|
205
|
+
return (oldRef['href'] == newRef['href']) #&& (oldRef['size'] == newRef['size'])
|
206
|
+
end
|
207
|
+
|
208
|
+
def addDisk(newDisk, childPackage, details)
|
209
|
+
# Always add a disk, even if it's a clone, cause this VM will need its own copy
|
210
|
+
isNewDisk = true
|
211
|
+
currentDisks = getChildrenByName(diskSection, 'Disk')
|
212
|
+
#currentDisks.each{ |oldDisk|
|
213
|
+
# if(compareDisks(oldDisk, newDisk))
|
214
|
+
# isNewDisk = false
|
215
|
+
# break
|
216
|
+
# end
|
217
|
+
#}
|
218
|
+
|
219
|
+
if(isNewDisk)
|
220
|
+
newDiskID = "vmdisk" + (currentDisks.length + 1).to_s
|
221
|
+
newDiskNode = diskSection.add_child(xml.create_element('Disk', {
|
222
|
+
'capacity' => newDisk['size'],
|
223
|
+
'diskId' => newDiskID,
|
224
|
+
'fileRef' => getChildrenByName(references, 'File').detect{ |ref| ref['href'] == newDisk['location'] }['id'],
|
225
|
+
'format' => "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized",
|
226
|
+
'populatedSize' => newDisk['thin_size']
|
227
|
+
}))
|
228
|
+
newDiskNode.attribute("capacity").namespace = @ovf_namespace
|
229
|
+
newDiskNode.attribute("diskId").namespace = @ovf_namespace
|
230
|
+
newDiskNode.attribute("fileRef").namespace = @ovf_namespace
|
231
|
+
newDiskNode.attribute("format").namespace = @ovf_namespace
|
232
|
+
newDiskNode.attribute("populatedSize").namespace = @ovf_namespace
|
233
|
+
findReplace(childPackage, newDisk['name'], newDiskID)
|
234
|
+
details.disks.push(newDiskID)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def compareDisks(oldDisk, newDisk)
|
239
|
+
filename = getChildrenByName(references, 'File').detect{ |ref| ref['id'] == oldDisk['fileRef'] }['href']
|
240
|
+
return (filename == newDisk['location'])
|
241
|
+
end
|
242
|
+
|
243
|
+
def addNetwork(newNetwork, childPackage, details)
|
244
|
+
isNewNetwork = true
|
245
|
+
currentNetworks = getChildrenByName(networkSection, 'Network')
|
246
|
+
currentNetworks.each{ |oldNetwork|
|
247
|
+
if(compareNetworks(oldNetwork, newNetwork))
|
248
|
+
isNewNetwork = false
|
249
|
+
break
|
250
|
+
end
|
251
|
+
}
|
252
|
+
|
253
|
+
if(isNewNetwork)
|
254
|
+
newNode = networkSection.add_child(xml.create_element('Network', {'name' => newNetwork['location']}))
|
255
|
+
newNode.attribute("name").namespace = @ovf_namespace
|
256
|
+
newNode.add_child(xml.create_element('Description', newNetwork['notes']))
|
257
|
+
end
|
258
|
+
details.networks.push(newNetwork['location'])
|
259
|
+
end
|
260
|
+
|
261
|
+
def compareNetworks(oldNetwork, newNetwork)
|
262
|
+
return (oldNetwork['name'] == newNetwork['location'])
|
263
|
+
end
|
264
|
+
|
265
|
+
def addVirtualSystem(newSystem)
|
266
|
+
ovfNamespace = xml.root.namespace
|
267
|
+
newNode = virtualSystemCollection.add_child(newSystem.clone)
|
268
|
+
newNode.namespace = ovfNamespace
|
269
|
+
end
|
270
|
+
|
271
|
+
def findReplace(package, oldval, newval)
|
272
|
+
package.xml.xpath("//*").each{ |node|
|
273
|
+
if(node.children.length == 1 && node.children[0].text? && node.content.match(oldval) != nil)
|
274
|
+
node.content = node.content.gsub(oldval, newval)
|
275
|
+
end
|
276
|
+
node.attributes.each{ |key, attr|
|
277
|
+
attr.value = attr.value.gsub(oldval, newval)
|
278
|
+
}
|
279
|
+
}
|
280
|
+
end
|
281
|
+
|
282
|
+
def search(virtualSystem, value)
|
283
|
+
virtualSystem.xpath(".//*").each{ |node|
|
284
|
+
if(node.children.length == 1 && node.children[0].text? && node.content.match(value) != nil)
|
285
|
+
return true
|
286
|
+
end
|
287
|
+
node.attributes.each{ |key, attr|
|
288
|
+
if(attr.value.match(value) != nil)
|
289
|
+
return true
|
290
|
+
end
|
291
|
+
}
|
292
|
+
}
|
293
|
+
return false
|
294
|
+
end
|
295
|
+
|
296
|
+
# @todo any need to make this a general purpose "writer" ?
|
297
|
+
def self.constructSkeleton
|
298
|
+
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
|
299
|
+
xml.Envelope('xmlns' => 'http://schemas.dmtf.org/ovf/envelope/1', 'xmlns:cim' => "http://schemas.dmtf.org/wbem/wscim/1/common", 'xmlns:ovf' => "http://schemas.dmtf.org/ovf/envelope/1", 'xmlns:rasd' => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData", 'xmlns:vmw' => "http://www.vmware.com/schema/ovf", 'xmlns:vssd' => "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData", 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", 'xmlns:cops' => 'http://cops.mitre.org/1.2', 'xmlns:cpe' => 'http://cpe.mitre.org/dictionary/2.0') {
|
300
|
+
xml.References{}
|
301
|
+
xml.DiskSection{
|
302
|
+
xml.Info "Virtual disk information"
|
303
|
+
}
|
304
|
+
xml.NetworkSection{
|
305
|
+
xml.Info "List of logical networks"
|
306
|
+
}
|
307
|
+
xml.VirtualSystemCollection('ovf:id' => "vm_collection"){
|
308
|
+
xml.Info "A collection of virtual machines"
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
node = Nokogiri::XML::Comment.new(xml.doc, ' skeleton framework constructed by OVFparse ')
|
313
|
+
xml.doc.children[0].add_previous_sibling(node)
|
314
|
+
end
|
315
|
+
|
316
|
+
newPackage = NewVmCollection.new
|
317
|
+
newPackage.xml = builder.doc
|
318
|
+
newPackage.loadElementRefs
|
319
|
+
return newPackage
|
320
|
+
end
|
321
|
+
|
322
|
+
def writeXML(filename)
|
323
|
+
file = File.new(filename, "w")
|
324
|
+
file.puts(xml.to_s)
|
325
|
+
file.close
|
326
|
+
end
|
327
|
+
|
328
|
+
def splitIntoPackages
|
329
|
+
packages = Array.new
|
330
|
+
|
331
|
+
i = 0
|
332
|
+
virtualSystems = getChildrenByName(virtualSystemCollection, "VirtualSystem")
|
333
|
+
virtualSystems.each{ |virtualSystem|
|
334
|
+
details = package_details[i]
|
335
|
+
new_package = VmPackage.construct_skeleton
|
336
|
+
new_package.loadElementRefs
|
337
|
+
|
338
|
+
details.files.each{ |file|
|
339
|
+
node = getChildrenByName(references, "File").detect{ |node| node['id'] == file }
|
340
|
+
new_package.references.add_child(node.clone)
|
341
|
+
}
|
342
|
+
|
343
|
+
details.disks.each{ |disk|
|
344
|
+
node = getChildrenByName(diskSection, "Disk").detect{ |node| node['diskId'] == disk }
|
345
|
+
new_package.diskSection.add_child(node.clone)
|
346
|
+
}
|
347
|
+
|
348
|
+
details.networks.each{ |network|
|
349
|
+
node = getChildrenByName(networkSection, "Network").detect{ |node| node['name'] == network }
|
350
|
+
new_package.networkSection.add_child(node.clone)
|
351
|
+
}
|
352
|
+
|
353
|
+
new_package.virtualSystem.children.unlink
|
354
|
+
new_package.virtualSystem.add_child(virtualSystem.clone.children)
|
355
|
+
new_package.virtualSystem.children.each{ |child|
|
356
|
+
child.namespace = new_package.virtualSystem.namespace
|
357
|
+
}
|
358
|
+
packages.push(new_package)
|
359
|
+
|
360
|
+
i += 1
|
361
|
+
}
|
362
|
+
|
363
|
+
return packages
|
364
|
+
end
|
365
|
+
|
366
|
+
def parseXML
|
367
|
+
fileRefs = Hash.new
|
368
|
+
fileNames = Array.new
|
369
|
+
getChildrenByName(references, "File").each{ |fileRef|
|
370
|
+
fileNames.push(fileRef['id'])
|
371
|
+
}
|
372
|
+
|
373
|
+
diskNames = Array.new
|
374
|
+
getChildrenByName(diskSection, "Disk").each{ |disk|
|
375
|
+
diskNames.push(disk['diskId'])
|
376
|
+
fileRefs[disk['diskId']] = disk['fileRef']
|
377
|
+
}
|
378
|
+
|
379
|
+
networkNames = Array.new
|
380
|
+
getChildrenByName(networkSection, "Network").each{ |network|
|
381
|
+
networkNames.push(network['name'])
|
382
|
+
}
|
383
|
+
|
384
|
+
getChildrenByName(virtualSystemCollection, "VirtualSystem").each{ |virtualSystem|
|
385
|
+
details = PackageDetails.new()
|
386
|
+
details.id = virtualSystem['id']
|
387
|
+
|
388
|
+
fileNames.each{ |fileName|
|
389
|
+
if(search(virtualSystem, fileName))
|
390
|
+
details.files.push(fileName)
|
391
|
+
end
|
392
|
+
}
|
393
|
+
|
394
|
+
diskNames.each{ |diskName|
|
395
|
+
if(search(virtualSystem, diskName))
|
396
|
+
details.disks.push(diskName)
|
397
|
+
if(!details.files.include?(fileRefs[diskName]))
|
398
|
+
details.files.push(fileRefs[diskName])
|
399
|
+
end
|
400
|
+
end
|
401
|
+
}
|
402
|
+
|
403
|
+
networkNames.each{ |networkName|
|
404
|
+
if(search(virtualSystem, networkName))
|
405
|
+
details.networks.push(networkName)
|
406
|
+
end
|
407
|
+
}
|
408
|
+
|
409
|
+
package_details.push(details)
|
410
|
+
}
|
411
|
+
end
|
412
|
+
|
413
|
+
end
|
414
|
+
|
415
|
+
class NewVmCollection < VmCollection
|
416
|
+
def initialize
|
417
|
+
@package_details = Array.new
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
class HttpVmCollection < VmCollection
|
422
|
+
def fetch
|
423
|
+
url = URI.parse(URI.escape(self.uri))
|
424
|
+
@xml = Nokogiri::XML(open(url)) do |config|
|
425
|
+
config.noblanks.strict.noent
|
426
|
+
end
|
427
|
+
|
428
|
+
loadElementRefs
|
429
|
+
parseXML
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
class FileVmCollection < VmCollection
|
434
|
+
def fetch
|
435
|
+
@xml = Nokogiri::XML(File.open(self.url)) do |config|
|
436
|
+
config.noblanks.strict.noent
|
437
|
+
end
|
438
|
+
|
439
|
+
loadElementRefs
|
440
|
+
parseXML
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
class PackageDetails
|
445
|
+
|
446
|
+
attr_accessor :id, :files, :disks, :networks
|
447
|
+
|
448
|
+
def initialize
|
449
|
+
@id = ""
|
450
|
+
@files = Array.new
|
451
|
+
@disks = Array.new
|
452
|
+
@networks = Array.new
|
453
|
+
end
|
454
|
+
|
455
|
+
end
|
data/lib/ovfparse/vmpackage.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'nokogiri'
|
1
2
|
require 'open-uri'
|
2
3
|
|
3
4
|
class VmPackage
|
@@ -237,7 +238,9 @@ class VmPackage
|
|
237
238
|
getChildrenByName(diskSection, 'Disk').each { |node|
|
238
239
|
capacity = node['capacity']
|
239
240
|
units = node['capacityAllocationUnits']
|
240
|
-
if(units == "byte * 2^
|
241
|
+
if(units == "byte * 2^40")
|
242
|
+
capacity = (capacity.to_i * 1099511627776).to_s
|
243
|
+
elsif(units == "byte * 2^30")
|
241
244
|
capacity = (capacity.to_i * 1073741824).to_s
|
242
245
|
elsif(units == "byte * 2^20")
|
243
246
|
capacity = (capacity.to_i * 1048576).to_s
|
@@ -261,6 +264,13 @@ class VmPackage
|
|
261
264
|
return networks
|
262
265
|
end
|
263
266
|
|
267
|
+
def getVmReferences
|
268
|
+
refs = Array.new
|
269
|
+
getChildrenByName(references, 'File').each { |node|
|
270
|
+
refs.push({'href' => node['href'], 'id' => node['id'], 'size' => node['size']})
|
271
|
+
}
|
272
|
+
return refs
|
273
|
+
end
|
264
274
|
|
265
275
|
def getVmCPUs
|
266
276
|
return getVirtualQuantity(3)
|
@@ -565,6 +575,17 @@ class VmPackage
|
|
565
575
|
end
|
566
576
|
end
|
567
577
|
|
578
|
+
def setPropertyDefault(key, newVal)
|
579
|
+
getChildrenByName(virtualSystem, "ProductSection").each{ |product|
|
580
|
+
getChildrenByName(product, "Property").each{ |property|
|
581
|
+
if(property['key'] == key)
|
582
|
+
property['ovf:value'] = newVal
|
583
|
+
return
|
584
|
+
end
|
585
|
+
}
|
586
|
+
}
|
587
|
+
end
|
588
|
+
|
568
589
|
def setElements(updated_element, parent_node, element_list)
|
569
590
|
element_list.each { |element_details|
|
570
591
|
updated_value = updated_element[element_details['element_ref']]
|
data/lib/ovfparse.rb
CHANGED
@@ -8,6 +8,7 @@ path = File.expand_path(File.dirname(__FILE__))
|
|
8
8
|
|
9
9
|
require path + '/ovfparse/vmrepository'
|
10
10
|
require path + '/ovfparse/vmpackage'
|
11
|
+
require path + '/ovfparse/vmcollection'
|
11
12
|
require path + '/ovfparse/os_id_table'
|
12
13
|
require path + '/ovfparse/esx4_vmrepository'
|
13
14
|
require path + '/ovfparse/file_vmrepository'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ovfparse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 57
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 1
|
10
|
+
version: 0.9.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jim Barkley
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-10-10 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/ovfparse/marketplace_repository.rb
|
49
49
|
- lib/ovfparse/vc_repository.rb
|
50
50
|
- lib/ovfparse/https_vmrepository.rb
|
51
|
+
- lib/ovfparse/vmcollection.rb
|
51
52
|
- lib/ovfparse/vmrepository.rb
|
52
53
|
- lib/ovfparse/esx_repository.rb
|
53
54
|
- lib/ovfparse/vmpackage.rb
|