ovfparse 0.0.7 → 0.0.81

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.
Files changed (3) hide show
  1. data/README +3 -2
  2. data/lib/ovfparse/vmpackage.rb +531 -2
  3. metadata +12 -5
data/README CHANGED
@@ -19,8 +19,9 @@ From inside your ovfparse directory:
19
19
  $ rake gem
20
20
  $ cd pkg
21
21
  $ gem install ovfparse[-version]
22
-
23
- [Coming soon: gem install ovfparse (from rubygems.org)]
22
+
23
+ Or from RubyGems:
24
+ $ gem install ovfparse
24
25
 
25
26
  === Example1
26
27
  ------------
@@ -20,6 +20,32 @@ class VmPackage
20
20
  COPYING = 4
21
21
  BOOTING = 5
22
22
  CONFIGURING = 6
23
+
24
+ # List of attributes in an OVF product that we will extract / set
25
+ PRODUCT_ATTRIBUTES = [ {'full_name' => 'ovf:instance', 'node_ref' => 'instance', 'attribute_ref' => 'instance'},
26
+ {'full_name' => 'ovf:class', 'node_ref' => 'class', 'attribute_ref' => 'product_class'} ]
27
+
28
+ # List of elements in an OVF product that we will extract / set
29
+ PRODUCT_ELEMENTS = [ {'full_name' => 'ovf:Info', 'node_ref' => 'Info', 'element_ref' => 'description', 'required' => false},
30
+ {'full_name' => 'ovf:Product', 'node_ref' => 'Product', 'element_ref' => 'name', 'required' => false},
31
+ {'full_name' => 'ovf:Vendor', 'node_ref' => 'Vendor', 'element_ref' => 'vendor', 'required' => false},
32
+ {'full_name' => 'ovf:Version', 'node_ref' => 'Version', 'element_ref' => 'version', 'required' => false} ]
33
+
34
+ # List of attributes in an OVF property that we will extract / set
35
+ PROPERTY_ATTRIBUTES = [ {'full_name' => 'ovf:value', 'node_ref' => 'value', 'attribute_ref' => 'value'},
36
+ {'full_name' => 'ovf:key', 'node_ref' => 'key', 'attribute_ref' => 'key'},
37
+ {'full_name' => 'ovf:userConfigurable', 'node_ref' => 'userConfigurable', 'attribute_ref' => 'userConfigurable'},
38
+ {'full_name' => 'ovf:password', 'node_ref' => 'password', 'attribute_ref' => 'password'},
39
+ {'full_name' => 'ovf:required', 'node_ref' => 'required', 'attribute_ref' => 'required'},
40
+ {'full_name' => 'ovf:type', 'node_ref' => 'type', 'attribute_ref' => 'value_basetype'},
41
+ {'full_name' => 'cops:valueType', 'node_ref' => 'valueType', 'attribute_ref' => 'valueType'},
42
+ {'full_name' => 'cops:uuid', 'node_ref' => 'uuid', 'attribute_ref' => 'uuid'} ]
43
+
44
+ # List of elements in an OVF property that we will extract / set
45
+ PROPERTY_ELEMENTS = [ {'full_name' => 'ovf:Label', 'node_ref' => 'Label', 'element_ref' => 'name', 'required' => false},
46
+ {'full_name' => 'ovf:Description', 'node_ref' => 'Description', 'element_ref' => 'description', 'required' => false},
47
+ {'full_name' => 'cops:Example', 'node_ref' => 'cops:Example', 'element_ref' => 'example', 'required' => true},
48
+ {'full_name' => 'cops:NoneType', 'node_ref' => 'cops:NoneType', 'element_ref' => 'nonetype', 'required' => true} ]
23
49
 
24
50
  OVF_NAMESPACE = {'ovf' => 'http://schemas.dmtf.org/ovf/envelope/1'}
25
51
 
@@ -120,6 +146,510 @@ class VmPackage
120
146
 
121
147
  end
122
148
 
149
+ def checkschema(schema)
150
+ xsd = Nokogiri::XML::Schema(File.read(schema))
151
+ response = ""
152
+
153
+ isValid = true
154
+ xsd.validate(@xml).each do |error|
155
+ response << error.message + "\n"
156
+ isValid = false
157
+ end
158
+
159
+ return [isValid, response]
160
+ end
161
+
162
+ def getVmName
163
+ return xml.xpath('ovf:Envelope/ovf:VirtualSystem')[0]['id']
164
+ end
165
+
166
+ def getVmDescription
167
+ descNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:Info')[0]
168
+ return descNode.nil? ? '' : descNode.content
169
+ end
170
+
171
+ def getVmOS_ID
172
+ return xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]['id']
173
+ end
174
+
175
+ def getVmPatchLevel
176
+ patchNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection/ovf:Description')[0]
177
+ return patchNode.nil? ? '' : patchNode.text
178
+ end
179
+
180
+ def getVmAttributes
181
+ return {
182
+ 'name' => getVmName,
183
+ 'description' => getVmDescription,
184
+ 'OS' => getVmOS_ID,
185
+ 'patch_level' => getVmPatchLevel,
186
+ 'CPUs' => getVmCPUs,
187
+ 'RAM' => getVmRAM
188
+ }
189
+ end
190
+
191
+ def getVmDisks
192
+ disks = Array.new
193
+ filenames = Hash.new
194
+ xml.xpath('ovf:Envelope/ovf:References/ovf:File').each { |node|
195
+ filenames[node['id']] = node['href']
196
+ }
197
+
198
+ xml.xpath('ovf:Envelope/ovf:DiskSection/ovf:Disk').each { |node|
199
+ disks.push({ 'name' => node['diskId'], 'location' => filenames[node['fileRef']], 'size' => node['capacity'] })
200
+ }
201
+
202
+ return disks
203
+ end
204
+
205
+ def getVmNetworks
206
+ networks = Array.new
207
+ xml.xpath('ovf:Envelope/ovf:NetworkSection/ovf:Network').each { |node|
208
+ descriptionNode = node.xpath('ovf:Description')[0]
209
+ text = descriptionNode.nil? ? '' : descriptionNode.text
210
+ networks.push({'location' => node['name'], 'notes' => text })
211
+ }
212
+ return networks
213
+ end
214
+
215
+ # What a long strange trip it's been.
216
+ def getVmProducts
217
+ products = Array.new
218
+ xml.root.add_namespace('cops', 'http://cops.mitre.org/1.1')
219
+ xml.root.add_namespace('cpe', 'http://cpe.mitre.org/dictionary/2.0')
220
+
221
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:ProductSection').each { |productNode|
222
+ product = Hash.new
223
+
224
+ PRODUCT_ATTRIBUTES.each { |attribute_details|
225
+ product[attribute_details['attribute_ref']] = productNode[attribute_details['node_ref']]
226
+ }
227
+
228
+ PRODUCT_ELEMENTS.each { |element_details|
229
+ childNode = productNode.xpath(element_details['full_name'])[0]
230
+ product[element_details['element_ref']] = childNode.nil? ? '' : childNode.content
231
+ }
232
+
233
+ childNode = productNode.xpath('ovf:Icon')[0]
234
+ begin
235
+ product['icon'] = childNode.nil? ? '' :
236
+ (xml.xpath('ovf:Envelope/ovf:References/ovf:File').detect { |file| file['id'] == childNode['fileRef'] })['href']
237
+ rescue
238
+ puts "You have an icon reference to a file that doesn't exist in the References section."
239
+ return ''
240
+ end
241
+
242
+ properties = Array.new
243
+ productNode.xpath('ovf:Property').each { |propertyNode|
244
+ property = Hash.new
245
+ PROPERTY_ATTRIBUTES.each { |attribute_details|
246
+ property[attribute_details['attribute_ref']] = propertyNode[attribute_details['node_ref']]
247
+ }
248
+
249
+ PROPERTY_ELEMENTS.each { |element_details|
250
+ childNode = propertyNode.xpath(element_details['full_name'])[0]
251
+ property[element_details['element_ref']] = childNode.nil? ? '' : childNode.content
252
+ }
253
+
254
+ valueOptionsArray = Array.new
255
+
256
+ node = propertyNode.xpath('cops:ValueOptions')[0]
257
+ if(!node.nil?)
258
+ if (!node['selection'].nil?)
259
+ property['selection'] = node['selection']
260
+ end
261
+ node.xpath('cops:Option').each { |valueOption|
262
+ valueOptionsArray.push(valueOption.content)
263
+ }
264
+ end
265
+
266
+ default = propertyNode['value']
267
+ existingDefault = valueOptionsArray.detect { |option| option == default }
268
+ if (!default.nil? && default != '' && existingDefault.nil?)
269
+ valueOptionsArray.insert(0, default)
270
+ end
271
+
272
+ property['valueoptions'] = valueOptionsArray.join("\n")
273
+
274
+ actions = Array.new
275
+ node = propertyNode.xpath('cops:Action')[0]
276
+ if(!node.nil?)
277
+ node.xpath('cops:FindReplace').each { |findReplace|
278
+ actions.push({'action_type' => 'FindReplace', 'path' => findReplace.xpath('cops:Path')[0].content, 'value' => findReplace.xpath('cops:Token')[0].content})
279
+ }
280
+ node.xpath('cops:Insert').each { |insert|
281
+ lineNumberNode = insert.xpath('cops:LineNumber')[0]
282
+ lineNumber = lineNumberNode.nil? ? '' : lineNumberNode.content
283
+ actions.push({'action_type' => 'Insert', 'path' => insert.xpath('cops:Path')[0].content, 'value' => lineNumber})
284
+ }
285
+ node.xpath('cops:Registry').each { |registry|
286
+ actions.push({'action_type' => 'Registry', 'path' => registry.xpath('cops:RegistryPath')[0].content, 'value' => ''})
287
+ }
288
+ node.xpath('cops:Execute').each { |execute|
289
+ optionsNode = execute.xpath('cops:Options')[0]
290
+ options = optionsNode.nil? ? '' : optionsNode.content
291
+ actions.push({'action_type' => 'Execute', 'path' => execute.xpath('cops:Path')[0].content, 'value' => options})
292
+ }
293
+
294
+ end
295
+
296
+ container = [property, actions]
297
+ properties.push(container)
298
+ }
299
+
300
+ container = [product, properties]
301
+ products.push(container)
302
+ }
303
+ return products
304
+ end
305
+
306
+ def getVmCPUs
307
+ return getVirtualQuantity(3)
308
+ end
309
+
310
+ def getVmRAM
311
+ return getVirtualQuantity(4)
312
+ end
313
+
314
+ def getVirtualQuantity(resource)
315
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item').each { |node|
316
+ resourceType = node.xpath('rasd:ResourceType')[0].text
317
+ resourceType == resource.to_s ? (return node.xpath('rasd:VirtualQuantity')[0].text) : next
318
+ }
319
+ end
320
+
321
+ def setVmName(newValue)
322
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem')[0]['ovf:id'] = newValue
323
+ nameNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:Name')[0] ||
324
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:Info')[0].add_next_sibling(xml.create_element('Name', {}))
325
+ nameNode.content = newValue
326
+ end
327
+
328
+ def setVmDescription(newValue)
329
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:Info')[0].content = newValue
330
+ end
331
+
332
+ def setVmOS_ID(newValue)
333
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]['ovf:id'] = newValue.to_s
334
+ end
335
+
336
+ def setVmPatchLevel(newValue)
337
+ osNode = xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:OperatingSystemSection')[0]
338
+ descNode = osNode.xpath('ovf:Description')[0] || osNode.add_child(xml.create_element('Description', {}))
339
+ descNode.content = newValue
340
+ end
341
+
342
+ def setVmCPUs(newValue)
343
+ setVirtualQuantity(3, newValue)
344
+ end
345
+
346
+ def setVmRAM(newValue)
347
+ setVirtualQuantity(4, newValue)
348
+ end
349
+
350
+ def setVirtualQuantity(resource, newValue)
351
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item').each { |node|
352
+ resourceType = node.xpath('rasd:ResourceType')[0].text
353
+ resourceType == resource.to_s ? (node.xpath('rasd:VirtualQuantity')[0].content = newValue) : next
354
+ }
355
+ end
356
+
357
+ def setVmNetworks(networks)
358
+ networkSection = xml.xpath('ovf:Envelope/ovf:NetworkSection')[0]
359
+ networkNodes = networkSection.xpath('ovf:Network')
360
+
361
+ networkNodes.each { |node|
362
+ updated_network = networks.detect { |network| network.location == node['name'] }
363
+ if(updated_network.nil?)
364
+ node.unlink
365
+ else
366
+ descriptionNode = node.xpath('ovf:Description')[0]
367
+ if((updated_network.notes == '' || updated_network.notes.nil?) && !descriptionNode.nil?)
368
+ descriptionNode.unlink
369
+ elsif(updated_network.notes != '' && !updated_network.notes.nil?)
370
+ descriptionNode = descriptionNode || descriptionNode.add_child(xml.create_element("Description", {}))
371
+ descriptionNode.content = updated_network.notes
372
+ end
373
+ end
374
+ }
375
+
376
+ networks.each { |network|
377
+ if( (networkNodes.detect { |node| network.location == node['name'] }).nil?)
378
+ networkNode = networkSection.add_child(xml.create_element('Network', {'ovf:name' => network.location}))
379
+ if(network.notes != '' && !network.notes.nil?)
380
+ networkNode.add_child(xml.create_element('Description', network.notes))
381
+ end
382
+ end
383
+ }
384
+ end
385
+
386
+ def setVmDisks(disks)
387
+ fileSection = xml.xpath('ovf:Envelope/ovf:References')[0]
388
+ fileNodes = fileSection.xpath('ovf:File')
389
+
390
+ diskSection = xml.xpath('ovf:Envelope/ovf:DiskSection')[0]
391
+ diskNodes = diskSection.xpath('ovf:Disk')
392
+
393
+ icons = Array.new
394
+ xml.xpath('ovf:Envelope/ovf:VirtualSystem/ovf:ProductSection/ovf:Icon').each { |node|
395
+ icons.push(node['fileRef'])
396
+ }
397
+
398
+ fileNodes.each { |file_node|
399
+ updated_disk = disks.detect { |disk| disk.location == file_node['href'] }
400
+ old_disk_node = diskNodes.detect { |old_node| old_node['id'] == file_node['fileRef'] }
401
+
402
+ if(updated_disk.nil?)
403
+ if((icons.detect { |fileRef| fileRef == file_node['id'] }).nil?)
404
+ file_node.unlink
405
+ if(!old_disk_node.nil?)
406
+ old_disk_node.unlink
407
+ end
408
+ end
409
+ else
410
+ file_node['ovf:id'] = updated_disk.name + '_disk'
411
+ old_disk_node['ovf:fileRef'] = updated_disk.name + '_disk'
412
+ old_disk_node['ovf:capacity'] = updated_disk.size.to_s
413
+ old_disk_node['ovf:diskId'] = updated_disk.name
414
+ end
415
+ }
416
+
417
+ disks.each { |disk|
418
+ if( (fileNodes.detect { |node| disk.location == node['href'] }).nil?)
419
+ diskSection.add_child(xml.create_element('Disk', {'ovf:capacity' => disk.size.to_s, 'ovf:capacityAllocationUnits' => "byte * 2^30", 'ovf:diskId' => disk.name, 'ovf:fileRef' => disk.name + '_disk', 'ovf:format' => "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" }))
420
+ fileSection.add_child(xml.create_element('File', {'ovf:href' => disk.location, 'ovf:id' => disk.name + '_disk'}))
421
+ end
422
+ }
423
+ end
424
+
425
+ def setVmAttributes(attributes)
426
+ if attributes['name']
427
+ setVmName(attributes['name'])
428
+ end
429
+ if attributes['description']
430
+ setVmDescription(attributes['description'])
431
+ end
432
+ if attributes['OS']
433
+ setVmOS_ID(attributes['OS'])
434
+ end
435
+ if attributes['patch_level']
436
+ setVmPatchLevel(attributes['patch_level'])
437
+ end
438
+ if attributes['CPUs']
439
+ setVmCPUs(attributes['CPUs'])
440
+ end
441
+ if attributes['RAM']
442
+ setVmRAM(attributes['RAM'])
443
+ end
444
+ end
445
+
446
+ def setProductIcon(new_icon, productNode)
447
+ iconNode = productNode.xpath('ovf:Icon')[0]
448
+ if((new_icon == '' || new_icon.nil?) && !iconNode.nil?)
449
+ (xml.xpath('ovf:Envelope/ovf:References/ovf:File').detect { |fileNode| fileNode['id'] == iconNode['fileRef']}).unlink
450
+ iconNode.unlink
451
+ elsif(new_icon != '' && !new_icon.nil?)
452
+ if(iconNode.nil?)
453
+ productNode.add_child(xml.create_element('Icon', {'ovf:fileRef' => productNode['class'] + '_icon'}))
454
+ xml.xpath('ovf:Envelope/ovf:References')[0].add_child(xml.create_element('File', {'ovf:id' => productNode['class'] + '_icon', 'ovf:href' => new_icon}))
455
+ else
456
+ (xml.xpath('ovf:Envelope/ovf:References/ovf:File').detect { |fileNode| fileNode['id'] == iconNode['fileRef']})['ovf:href'] = new_icon
457
+ end
458
+ end
459
+ end
460
+
461
+ def setElements(updated_element, parent_node, element_list)
462
+ element_list.each { |element_details|
463
+ updated_value = updated_element[element_details['element_ref']]
464
+ element_node = parent_node.xpath(element_details['full_name'])[0]
465
+ if((updated_value == '' || updated_value.nil?) && !element_node.nil?)
466
+ element_node.unlink
467
+ elsif(updated_value != '' && !updated_value.nil?)
468
+ element_node = element_node || parent_node.add_child(xml.create_element(element_details['node_ref'], updated_value))
469
+ element_node.content = updated_value
470
+ if(element_details['required'])
471
+ element_node['ovf:required'] = 'false'
472
+ end
473
+ end
474
+ }
475
+ end
476
+
477
+ def setAttributes(updated_element, parent_node, attribute_list)
478
+ attribute_list.each { |attribute_details|
479
+ updated_value = updated_element[attribute_details['attribute_ref']]
480
+ (updated_value == '' || updated_value.nil?) ? parent_node.delete(attribute_details['node_ref']) : parent_node[attribute_details['full_name']] = updated_value
481
+ }
482
+ end
483
+
484
+ def setVmProducts(products)
485
+ virtualSystem = xml.xpath('ovf:Envelope/ovf:VirtualSystem')[0]
486
+ productNodes = virtualSystem.xpath('ovf:ProductSection')
487
+
488
+ # Removing old ones that don't exist anymore, updating ones that do
489
+ productNodes.each { |productNode|
490
+ updated_product = products.detect { |product| productNode['class'] == product.product_class }
491
+ if(updated_product.nil?)
492
+ productNode.unlink
493
+ else
494
+ setAttributes(updated_product, productNode, PRODUCT_ATTRIBUTES)
495
+ setElements(updated_product, productNode, PRODUCT_ELEMENTS)
496
+ setProductIcon(updated_product.icon, productNode)
497
+ setProperties(productNode, updated_product.coat_properties)
498
+ end
499
+ }
500
+
501
+ # Adding new products
502
+ products.each { |product|
503
+ if((productNodes.detect { |node| node['class'] == product.product_class }).nil?)
504
+ newProductNode = virtualSystem.add_child(xml.create_element('ProductSection', {}))
505
+ setAttributes(product, newProductNode, PRODUCT_ATTRIBUTES)
506
+ setElements(product, newProductNode, PRODUCT_ELEMENTS)
507
+ setProductIcon(product.icon, newProductNode)
508
+ setProperties(newProductNode, product.coat_properties)
509
+ end
510
+ }
511
+ end
512
+
513
+ def setProperties(product, properties)
514
+ propertyNodes = product.xpath('ovf:Property')
515
+
516
+ propertyNodes.each { |propertyNode|
517
+ updated_property = properties.detect { |property| propertyNode['key'] == property.key }
518
+ if(updated_property.nil?)
519
+ propertyNode.unlink
520
+ else
521
+ setAttributes(updated_property, propertyNode, PROPERTY_ATTRIBUTES)
522
+ setElements(updated_property, propertyNode, PROPERTY_ELEMENTS)
523
+ setValueOptions(propertyNode, updated_property)
524
+ propertyNode['ovf:type'] = 'string'
525
+ setActions(propertyNode, updated_property.coat_actions)
526
+ end
527
+ }
528
+
529
+ properties.each { |property|
530
+ if((propertyNodes.detect { |node| node['key'] == property.key }).nil?)
531
+ newPropertyNode = product.add_child(xml.create_element('Property', {}))
532
+ setAttributes(property, newPropertyNode, PROPERTY_ATTRIBUTES)
533
+ setElements(property, newPropertyNode, PROPERTY_ELEMENTS)
534
+ setValueOptions(newPropertyNode, property)
535
+ newPropertyNode['ovf:type'] = 'string'
536
+ setActions(newPropertyNode, property.coat_actions)
537
+ end
538
+ }
539
+ end
540
+
541
+ def setValueOptions(property_node, property)
542
+ values = property.valueoptions.split("\n")
543
+ valueOptionsNode = property_node.xpath('cops:ValueOptions')[0]
544
+ if(values.empty? && !valueOptionsNode.nil?)
545
+ valueOptionsNode.unlink
546
+ elsif(!values.empty?)
547
+ valueOptionsNode = valueOptionsNode || property_node.add_child(xml.create_element('ValueOptions', {}))
548
+ valueOptionsNode.namespace = xml.root.namespace_definitions.detect{ |ns| ns.prefix == 'cops' }
549
+ valueOptionsNode['cops:selection'] = (property.selection || 'single')
550
+ valueOptionsNode['ovf:required'] = 'false'
551
+ valueOptionsNode.children.unlink
552
+ existingDefault = values.detect { |value| value == property.value }
553
+ if(property.value != '' && !property.value.nil? && existingValue.nil?)
554
+ valueOptionsNode.add_child(xml.create_element('Option', property.value))
555
+ end
556
+ values.each { |value|
557
+ valueOptionsNode.add_child(xml.create_element('Option', value))
558
+ }
559
+ end
560
+ end
561
+
562
+ def setActions(property, actions)
563
+ actionsNode = property.xpath('cops:Action')[0]
564
+ if(actions.empty? && !actionsNode.nil?)
565
+ actionsNode.unlink
566
+ elsif(!actions.empty?)
567
+ actionsNode = actionsNode || property.add_child(xml.create_element('Action', {}))
568
+ actionsNode.namespace = xml.root.namespace_definitions.detect{ |ns| ns.prefix == 'cops' }
569
+ actionsNode['ovf:required'] = 'false'
570
+ actionsNode.children.unlink
571
+ actions.each { |action|
572
+ newActionNode = actionsNode.add_child(xml.create_element(action.action_type, {}))
573
+ if(action.action_type == 'FindReplace')
574
+ newActionNode.add_child(xml.create_element('Path', action.path))
575
+ newActionNode.add_child(xml.create_element('Token', action.value))
576
+ elsif(action.action_type == 'Insert')
577
+ newActionNode.add_child(xml.create_element('Path', action.path))
578
+ if(action.value != '' && !action.value.nil?)
579
+ newActionNode.add_child(xml.create_element('LineNumber', action.value))
580
+ end
581
+ elsif(action.action_type == 'Registry')
582
+ newActionNode.add_child(xml.create_element('RegistryPath', action.path))
583
+ elsif(action.action_type == 'Execute')
584
+ newActionNode.add_child(xml.create_element('Path', action.path))
585
+ if(action.value != '' && !action.value.nil?)
586
+ newActionNode.add_child(xml.create_element('Options', action.value))
587
+ end
588
+ end
589
+ }
590
+ end
591
+ end
592
+
593
+ def self.construct_skeleton
594
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
595
+ 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") {
596
+ xml.References{}
597
+ xml.DiskSection{
598
+ xml.Info "Virtual disk information"
599
+ }
600
+ xml.NetworkSection{
601
+ xml.Info "List of logical networks"
602
+ }
603
+ xml.VirtualSystem('ovf:id' => "vm"){
604
+ xml.Info "A virtual machine"
605
+ xml.Name "New Virtual Machine"
606
+ xml.OperatingSystemSection('ovf:id' => "94"){
607
+ xml.Info "The kind of guest operating system"
608
+ }
609
+ xml.VirtualHardwareSection{
610
+ xml.Info "Virtual hardware requirements"
611
+ xml.System{
612
+ xml['vssd'].ElementName "Virtual Hardware Family"
613
+ xml['vssd'].InstanceID "0"
614
+ xml['vssd'].VirtualSystemIdentifier "New Virtual Machine"
615
+ }
616
+ xml.Item{
617
+ xml['rasd'].AllocationUnits "herts * 10^6"
618
+ xml['rasd'].Description "Number of Virtual CPUs"
619
+ xml['rasd'].ElementName "1 Virtual CPU(s)"
620
+ xml['rasd'].InstanceID "1"
621
+ xml['rasd'].ResourceType "3"
622
+ xml['rasd'].VirtualQuantity "1"
623
+ }
624
+ xml.Item{
625
+ xml['rasd'].AllocationUnits "byte * 2^20"
626
+ xml['rasd'].Description "Memory Size"
627
+ xml['rasd'].ElementName "512MB of memory"
628
+ xml['rasd'].InstanceID "2"
629
+ xml['rasd'].ResourceType "4"
630
+ xml['rasd'].VirtualQuantity "512"
631
+ }
632
+ }
633
+ }
634
+ }
635
+ node = Nokogiri::XML::Comment.new(xml.doc, ' skeleton framework constructed by COAT ')
636
+ xml.doc.children[0].add_previous_sibling(node)
637
+ end
638
+ return builder.to_xml
639
+ end
640
+
641
+ def write_xml(file)
642
+ xml.write_xml_to(file)
643
+ end
644
+
645
+ def sign
646
+ node = Nokogiri::XML::Comment.new(xml, ' made with love by the cops ovf authoring tool. ')
647
+ xml.children[0].add_next_sibling(node)
648
+ end
649
+
650
+ def xpath(string)
651
+ puts @xml.xpath(string)
652
+ end
123
653
 
124
654
  end
125
655
 
@@ -185,8 +715,7 @@ end
185
715
  class FileVmPackage < VmPackage
186
716
  def fetch
187
717
  @xml = Nokogiri::XML(File.open(self.url)) do |config|
188
- config.strict.noent
189
- config.strict
718
+ config.noblanks.strict.noent
190
719
  end
191
720
  end
192
721
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ovfparse
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 189
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 7
9
- version: 0.0.7
9
+ - 81
10
+ version: 0.0.81
10
11
  platform: ruby
11
12
  authors:
12
13
  - Jim Barkley
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-21 00:00:00 -04:00
18
+ date: 2011-03-14 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: nokogiri
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 5
27
30
  segments:
28
31
  - 1
29
32
  - 4
@@ -63,23 +66,27 @@ rdoc_options: []
63
66
  require_paths:
64
67
  - lib
65
68
  required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
66
70
  requirements:
67
71
  - - ">="
68
72
  - !ruby/object:Gem::Version
73
+ hash: 3
69
74
  segments:
70
75
  - 0
71
76
  version: "0"
72
77
  required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
73
79
  requirements:
74
80
  - - ">="
75
81
  - !ruby/object:Gem::Version
82
+ hash: 3
76
83
  segments:
77
84
  - 0
78
85
  version: "0"
79
86
  requirements: []
80
87
 
81
88
  rubyforge_project:
82
- rubygems_version: 1.3.6
89
+ rubygems_version: 1.6.2
83
90
  signing_key:
84
91
  specification_version: 3
85
92
  summary: Retrieves and parses files in the Open Virtualization Format