ovfparse 0.0.91 → 0.0.93
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ovfparse/vmpackage.rb +9 -229
- metadata +4 -4
data/lib/ovfparse/vmpackage.rb
CHANGED
@@ -13,13 +13,6 @@ class VmPackage
|
|
13
13
|
|
14
14
|
@type = nil
|
15
15
|
|
16
|
-
UNKNOWN = 0
|
17
|
-
INSTALLED = 1
|
18
|
-
NOT_INSTALLED = 2
|
19
|
-
UNINSTALLED = 3
|
20
|
-
COPYING = 4
|
21
|
-
BOOTING = 5
|
22
|
-
CONFIGURING = 6
|
23
16
|
|
24
17
|
# List of attributes in an OVF product that we will extract / set
|
25
18
|
PRODUCT_ATTRIBUTES = [ {'full_name' => 'ovf:instance', 'node_ref' => 'instance', 'attribute_ref' => 'instance'},
|
@@ -49,7 +42,6 @@ class VmPackage
|
|
49
42
|
|
50
43
|
OVF_NAMESPACE = {'ovf' => 'http://schemas.dmtf.org/ovf/envelope/1'}
|
51
44
|
|
52
|
-
@state = UNKNOWN
|
53
45
|
|
54
46
|
attr_accessor :url, :name, :version, :state, :protocol, :size, :xml
|
55
47
|
|
@@ -172,13 +164,14 @@ class VmPackage
|
|
172
164
|
return xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]['id']
|
173
165
|
end
|
174
166
|
|
175
|
-
|
167
|
+
# note this is not part of the OVF spec. Specific users could overwrite this method to
|
168
|
+
# store/retrieve patch level in the description field, for example.
|
176
169
|
def getVmPatchLevel
|
177
|
-
patchNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection/ovf:Description')[0]
|
178
|
-
return patchNode.nil? ? '' : patchNode.text
|
179
170
|
end
|
180
171
|
|
181
|
-
|
172
|
+
def setVmPatchlevel
|
173
|
+
end
|
174
|
+
|
182
175
|
def getVmAttributes
|
183
176
|
return {
|
184
177
|
'name' => getVmName,
|
@@ -214,99 +207,6 @@ class VmPackage
|
|
214
207
|
return networks
|
215
208
|
end
|
216
209
|
|
217
|
-
# @todo refactor to cops extension module
|
218
|
-
# cpe and cops namespaces are not general purpose
|
219
|
-
def getVmProducts
|
220
|
-
products = Array.new
|
221
|
-
xml.root.add_namespace('cops', 'http://cops.mitre.org/1.1')
|
222
|
-
xml.root.add_namespace('cpe', 'http://cpe.mitre.org/dictionary/2.0')
|
223
|
-
|
224
|
-
xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:ProductSection').each { |productNode|
|
225
|
-
product = Hash.new
|
226
|
-
|
227
|
-
PRODUCT_ATTRIBUTES.each { |attribute_details|
|
228
|
-
product[attribute_details['attribute_ref']] = productNode[attribute_details['node_ref']]
|
229
|
-
}
|
230
|
-
|
231
|
-
PRODUCT_ELEMENTS.each { |element_details|
|
232
|
-
childNode = productNode.xpath(element_details['full_name'])[0]
|
233
|
-
product[element_details['element_ref']] = childNode.nil? ? '' : childNode.content
|
234
|
-
}
|
235
|
-
|
236
|
-
childNode = productNode.xpath('ovf:Icon')[0]
|
237
|
-
begin
|
238
|
-
product['icon'] = childNode.nil? ? '' :
|
239
|
-
(xml.xpath('ovf:Envelope/ovf:References/ovf:File').detect { |file| file['id'] == childNode['fileRef'] })['href']
|
240
|
-
rescue
|
241
|
-
puts "You have an icon reference to a file that doesn't exist in the References section."
|
242
|
-
return ''
|
243
|
-
end
|
244
|
-
|
245
|
-
properties = Array.new
|
246
|
-
productNode.xpath('ovf:Property').each { |propertyNode|
|
247
|
-
property = Hash.new
|
248
|
-
PROPERTY_ATTRIBUTES.each { |attribute_details|
|
249
|
-
property[attribute_details['attribute_ref']] = propertyNode[attribute_details['node_ref']]
|
250
|
-
}
|
251
|
-
|
252
|
-
PROPERTY_ELEMENTS.each { |element_details|
|
253
|
-
childNode = propertyNode.xpath(element_details['full_name'])[0]
|
254
|
-
property[element_details['element_ref']] = childNode.nil? ? '' : childNode.content
|
255
|
-
}
|
256
|
-
|
257
|
-
valueOptionsArray = Array.new
|
258
|
-
|
259
|
-
# @todo refactor to cops extension module
|
260
|
-
node = propertyNode.xpath('cops:ValueOptions')[0]
|
261
|
-
if(!node.nil?)
|
262
|
-
if (!node['selection'].nil?)
|
263
|
-
property['selection'] = node['selection']
|
264
|
-
end
|
265
|
-
node.xpath('cops:Option').each { |valueOption|
|
266
|
-
valueOptionsArray.push(valueOption.content)
|
267
|
-
}
|
268
|
-
end
|
269
|
-
|
270
|
-
default = propertyNode['value']
|
271
|
-
existingDefault = valueOptionsArray.detect { |option| option == default }
|
272
|
-
if (!default.nil? && default != '' && existingDefault.nil?)
|
273
|
-
valueOptionsArray.insert(0, default)
|
274
|
-
end
|
275
|
-
|
276
|
-
property['valueoptions'] = valueOptionsArray.join("\n")
|
277
|
-
|
278
|
-
# @todo refactor to cops extension module
|
279
|
-
actions = Array.new
|
280
|
-
node = propertyNode.xpath('cops:Action')[0]
|
281
|
-
if(!node.nil?)
|
282
|
-
node.xpath('cops:FindReplace').each { |findReplace|
|
283
|
-
actions.push({'action_type' => 'FindReplace', 'path' => findReplace.xpath('cops:Path')[0].content, 'value' => findReplace.xpath('cops:Token')[0].content})
|
284
|
-
}
|
285
|
-
node.xpath('cops:Insert').each { |insert|
|
286
|
-
lineNumberNode = insert.xpath('cops:LineNumber')[0]
|
287
|
-
lineNumber = lineNumberNode.nil? ? '' : lineNumberNode.content
|
288
|
-
actions.push({'action_type' => 'Insert', 'path' => insert.xpath('cops:Path')[0].content, 'value' => lineNumber})
|
289
|
-
}
|
290
|
-
node.xpath('cops:Registry').each { |registry|
|
291
|
-
actions.push({'action_type' => 'Registry', 'path' => registry.xpath('cops:RegistryPath')[0].content, 'value' => ''})
|
292
|
-
}
|
293
|
-
node.xpath('cops:Execute').each { |execute|
|
294
|
-
optionsNode = execute.xpath('cops:Options')[0]
|
295
|
-
options = optionsNode.nil? ? '' : optionsNode.content
|
296
|
-
actions.push({'action_type' => 'Execute', 'path' => execute.xpath('cops:Path')[0].content, 'value' => options})
|
297
|
-
}
|
298
|
-
|
299
|
-
end
|
300
|
-
|
301
|
-
container = [property, actions]
|
302
|
-
properties.push(container)
|
303
|
-
}
|
304
|
-
|
305
|
-
container = [product, properties]
|
306
|
-
products.push(container)
|
307
|
-
}
|
308
|
-
return products
|
309
|
-
end
|
310
210
|
|
311
211
|
def getVmCPUs
|
312
212
|
return getVirtualQuantity(3)
|
@@ -338,13 +238,6 @@ class VmPackage
|
|
338
238
|
xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]['ovf:id'] = newValue.to_s
|
339
239
|
end
|
340
240
|
|
341
|
-
# @todo refactor to cops extension module
|
342
|
-
# currently we're using description field for vmpatchlevel
|
343
|
-
def setVmPatchLevel(newValue)
|
344
|
-
osNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]
|
345
|
-
descNode = osNode.xpath('ovf:Description')[0] || osNode.add_child(xml.create_element('Description', {}))
|
346
|
-
descNode.content = newValue
|
347
|
-
end
|
348
241
|
|
349
242
|
def setVmCPUs(newValue)
|
350
243
|
setVirtualQuantity(3, newValue)
|
@@ -489,119 +382,6 @@ class VmPackage
|
|
489
382
|
}
|
490
383
|
end
|
491
384
|
|
492
|
-
def setVmProducts(products)
|
493
|
-
virtualSystem = xml.xpath('ovf:Envelope/ovf:VirtualSystem')[0]
|
494
|
-
productNodes = virtualSystem.xpath('ovf:ProductSection')
|
495
|
-
|
496
|
-
# @todo refactor to cops extension module, notice the "coat_properties"...
|
497
|
-
# Removing old ones that don't exist anymore, updating ones that do
|
498
|
-
productNodes.each { |productNode|
|
499
|
-
updated_product = products.detect { |product| productNode['class'] == product.product_class }
|
500
|
-
if(updated_product.nil?)
|
501
|
-
productNode.unlink
|
502
|
-
else
|
503
|
-
setAttributes(updated_product, productNode, PRODUCT_ATTRIBUTES)
|
504
|
-
setElements(updated_product, productNode, PRODUCT_ELEMENTS)
|
505
|
-
setProductIcon(updated_product.icon, productNode)
|
506
|
-
setProperties(productNode, updated_product.coat_properties)
|
507
|
-
end
|
508
|
-
}
|
509
|
-
|
510
|
-
# Adding new products
|
511
|
-
products.each { |product|
|
512
|
-
if((productNodes.detect { |node| node['class'] == product.product_class }).nil?)
|
513
|
-
newProductNode = virtualSystem.add_child(xml.create_element('ProductSection', {}))
|
514
|
-
setAttributes(product, newProductNode, PRODUCT_ATTRIBUTES)
|
515
|
-
setElements(product, newProductNode, PRODUCT_ELEMENTS)
|
516
|
-
setProductIcon(product.icon, newProductNode)
|
517
|
-
setProperties(newProductNode, product.coat_properties)
|
518
|
-
end
|
519
|
-
}
|
520
|
-
end
|
521
|
-
|
522
|
-
# @todo refactor to cops extension module, notice the "coat_properties"...
|
523
|
-
def setProperties(product, properties)
|
524
|
-
propertyNodes = product.xpath('ovf:Property')
|
525
|
-
|
526
|
-
propertyNodes.each { |propertyNode|
|
527
|
-
updated_property = properties.detect { |property| propertyNode['key'] == property.key }
|
528
|
-
if(updated_property.nil?)
|
529
|
-
propertyNode.unlink
|
530
|
-
else
|
531
|
-
product.add_child(propertyNode)
|
532
|
-
setAttributes(updated_property, propertyNode, PROPERTY_ATTRIBUTES)
|
533
|
-
setElements(updated_property, propertyNode, PROPERTY_ELEMENTS)
|
534
|
-
setValueOptions(propertyNode, updated_property)
|
535
|
-
propertyNode['ovf:type'] = 'string'
|
536
|
-
setActions(propertyNode, updated_property.coat_actions)
|
537
|
-
end
|
538
|
-
}
|
539
|
-
|
540
|
-
properties.each { |property|
|
541
|
-
if((propertyNodes.detect { |node| node['key'] == property.key }).nil?)
|
542
|
-
newPropertyNode = product.add_child(xml.create_element('Property', {}))
|
543
|
-
setAttributes(property, newPropertyNode, PROPERTY_ATTRIBUTES)
|
544
|
-
setElements(property, newPropertyNode, PROPERTY_ELEMENTS)
|
545
|
-
setValueOptions(newPropertyNode, property)
|
546
|
-
newPropertyNode['ovf:type'] = 'string'
|
547
|
-
setActions(newPropertyNode, property.coat_actions)
|
548
|
-
end
|
549
|
-
}
|
550
|
-
end
|
551
|
-
|
552
|
-
# @todo refactor to cops extension module
|
553
|
-
def setValueOptions(property_node, property)
|
554
|
-
values = property.valueoptions.split("\n")
|
555
|
-
valueOptionsNode = property_node.xpath('cops:ValueOptions')[0]
|
556
|
-
if(values.empty? && !valueOptionsNode.nil?)
|
557
|
-
valueOptionsNode.unlink
|
558
|
-
elsif(!values.empty?)
|
559
|
-
valueOptionsNode = valueOptionsNode.nil? ? property_node.add_child(xml.create_element('ValueOptions', {})) : property_node.add_child(valueOptionsNode)
|
560
|
-
valueOptionsNode.namespace = xml.root.namespace_definitions.detect{ |ns| ns.prefix == 'cops' }
|
561
|
-
valueOptionsNode['cops:selection'] = (property.selection || 'single')
|
562
|
-
valueOptionsNode['ovf:required'] = 'false'
|
563
|
-
valueOptionsNode.children.unlink
|
564
|
-
existingDefault = values.detect { |value| value == property.value }
|
565
|
-
if(property.value != '' && !property.value.nil? && existingValue.nil?)
|
566
|
-
valueOptionsNode.add_child(xml.create_element('Option', property.value))
|
567
|
-
end
|
568
|
-
values.each { |value|
|
569
|
-
valueOptionsNode.add_child(xml.create_element('Option', value))
|
570
|
-
}
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
# @todo refactor to cops extension module
|
575
|
-
def setActions(property, actions)
|
576
|
-
actionsNode = property.xpath('cops:Action')[0]
|
577
|
-
if(actions.empty? && !actionsNode.nil?)
|
578
|
-
actionsNode.unlink
|
579
|
-
elsif(!actions.empty?)
|
580
|
-
actionsNode = actionsNode.nil? ? property.add_child(xml.create_element('Action', {})) : property.add_child(actionsNode)
|
581
|
-
actionsNode.namespace = xml.root.namespace_definitions.detect{ |ns| ns.prefix == 'cops' }
|
582
|
-
actionsNode['ovf:required'] = 'false'
|
583
|
-
actionsNode.children.unlink
|
584
|
-
actions.each { |action|
|
585
|
-
newActionNode = actionsNode.add_child(xml.create_element(action.action_type, {}))
|
586
|
-
if(action.action_type == 'FindReplace')
|
587
|
-
newActionNode.add_child(xml.create_element('Path', action.path))
|
588
|
-
newActionNode.add_child(xml.create_element('Token', action.value))
|
589
|
-
elsif(action.action_type == 'Insert')
|
590
|
-
newActionNode.add_child(xml.create_element('Path', action.path))
|
591
|
-
if(action.value != '' && !action.value.nil?)
|
592
|
-
newActionNode.add_child(xml.create_element('LineNumber', action.value))
|
593
|
-
end
|
594
|
-
elsif(action.action_type == 'Registry')
|
595
|
-
newActionNode.add_child(xml.create_element('RegistryPath', action.path))
|
596
|
-
elsif(action.action_type == 'Execute')
|
597
|
-
newActionNode.add_child(xml.create_element('Path', action.path))
|
598
|
-
if(action.value != '' && !action.value.nil?)
|
599
|
-
newActionNode.add_child(xml.create_element('Options', action.value))
|
600
|
-
end
|
601
|
-
end
|
602
|
-
}
|
603
|
-
end
|
604
|
-
end
|
605
385
|
|
606
386
|
# @todo any need to make this a general purpose "writer" ?
|
607
387
|
def self.construct_skeleton
|
@@ -646,8 +426,8 @@ class VmPackage
|
|
646
426
|
}
|
647
427
|
}
|
648
428
|
}
|
649
|
-
|
650
|
-
node = Nokogiri::XML::Comment.new(xml.doc, ' skeleton framework constructed by
|
429
|
+
|
430
|
+
node = Nokogiri::XML::Comment.new(xml.doc, ' skeleton framework constructed by OVFparse ')
|
651
431
|
xml.doc.children[0].add_previous_sibling(node)
|
652
432
|
end
|
653
433
|
return builder.to_xml
|
@@ -658,8 +438,8 @@ class VmPackage
|
|
658
438
|
end
|
659
439
|
|
660
440
|
# @todo make this a general purpose signing util
|
661
|
-
def sign
|
662
|
-
node = Nokogiri::XML::Comment.new(xml,
|
441
|
+
def sign(signature)
|
442
|
+
node = Nokogiri::XML::Comment.new(xml, signature)
|
663
443
|
xml.children[0].add_next_sibling(node)
|
664
444
|
end
|
665
445
|
|
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: 165
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 93
|
10
|
+
version: 0.0.93
|
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-04-
|
18
|
+
date: 2011-04-13 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|