Revision fa337742

b/lib/ovf.py
72 72
]
73 73

  
74 74
COMPRESSION_TYPE = "gzip"
75
NO_COMPRESSION = [None, "identity"]
75 76
COMPRESS = "compression"
76 77
DECOMPRESS = "decompression"
77 78
ALLOWED_ACTIONS = [COMPRESS, DECOMPRESS]
78 79

  
80
VMDK = "vmdk"
81
RAW = "raw"
82
COW = "cow"
83
ALLOWED_FORMATS = [RAW, COW, VMDK]
84

  
79 85
# ResourceType values
80 86
RASD_TYPE = {
81 87
  "vcpus": "3",
......
85 91
  "disk": "17",
86 92
}
87 93

  
94
SCSI_SUBTYPE = "lsilogic"
95
VS_TYPE = {
96
  "ganeti": "ganeti-ovf",
97
  "external": "vmx-04",
98
}
99

  
88 100
# AllocationUnits values and conversion
89 101
ALLOCATION_UNITS = {
90 102
  'b': ["bytes", "b"],
......
111 123
VERSION = "version"
112 124

  
113 125
# Instance IDs of System and SCSI controller
114
SYSTEM_ID = 0
115
SCSI_ID = 3
126
INSTANCE_ID = {
127
  "system": 0,
128
  "vcpus": 1,
129
  "memory": 2,
130
  "scsi": 3,
131
}
116 132

  
117 133
# Disk format descriptions
118 134
DISK_FORMAT = {
119
  "raw": "http://en.wikipedia.org/wiki/Byte",
120
  "vmdk": "http://www.vmware.com/interfaces/specifications/vmdk.html"
135
  RAW: "http://en.wikipedia.org/wiki/Byte",
136
  VMDK: "http://www.vmware.com/interfaces/specifications/vmdk.html"
121 137
          "#monolithicSparse",
122
  "cow": "http://www.gnome.org/~markmc/qcow-image-format.html",
138
  COW: "http://www.gnome.org/~markmc/qcow-image-format.html",
123 139
}
124 140

  
125 141

  
......
571 587

  
572 588
  @type tree: ET.ElementTree
573 589
  @ivar tree: XML tree that we are constructing
590
  @type virtual_system_type: string
591
  @ivar virtual_system_type: value of vssd:VirtualSystemType, for external usage
592
    in VMWare this requires to be vmx
574 593
  @type hardware_list: list
575 594
  @ivar hardware_list: list of items prepared for VirtualHardwareSection
595
  @type next_instance_id: int
596
  @ivar next_instance_id: next instance id to be used when creating elements on
597
    hardware_list
576 598

  
577 599
  """
578 600
  def __init__(self, has_gnt_section):
......
593 615
    }
594 616
    if has_gnt_section:
595 617
      env_attribs["xmlns:gnt"] = GANETI_SCHEMA
618
      self.virtual_system_type = VS_TYPE["ganeti"]
619
    else:
620
      self.virtual_system_type = VS_TYPE["external"]
596 621
    self.tree = ET.Element("Envelope", attrib=env_attribs)
597 622
    self.hardware_list = []
623
    # INSTANCE_ID contains statically assigned IDs, starting from 0
624
    self.next_instance_id = len(INSTANCE_ID) # FIXME: hackish
598 625

  
599 626
  def SaveDisksData(self, disks):
600 627
    """Convert disk information to certain OVF sections.
......
605 632
    """
606 633
    references = ET.SubElement(self.tree, "References")
607 634
    disk_section = ET.SubElement(self.tree, "DiskSection")
635
    SubElementText(disk_section, "Info", "Virtual disk information")
608 636
    for counter, disk in enumerate(disks):
609 637
      file_id = "file%s" % counter
610 638
      disk_id = "disk%s" % counter
......
627 655
      # Item in VirtualHardwareSection creation
628 656
      disk_item = ET.Element("Item")
629 657
      SubElementText(disk_item, "rasd:ElementName", disk_id)
630
      SubElementText(disk_item, "rasd:ResourceType", RASD_TYPE["disk"])
631 658
      SubElementText(disk_item, "rasd:HostResource", "ovf:/disk/%s" % disk_id)
632
      SubElementText(disk_item, "rasd:Parent", SCSI_ID)
659
      SubElementText(disk_item, "rasd:InstanceID", self.next_instance_id)
660
      SubElementText(disk_item, "rasd:Parent", INSTANCE_ID["scsi"])
661
      SubElementText(disk_item, "rasd:ResourceType", RASD_TYPE["disk"])
633 662
      self.hardware_list.append(disk_item)
663
      self.next_instance_id += 1
634 664

  
635 665
  def SaveNetworksData(self, networks):
636 666
    """Convert network information to NetworkSection.
......
640 670

  
641 671
    """
642 672
    network_section = ET.SubElement(self.tree, "NetworkSection")
673
    SubElementText(network_section, "Info", "List of logical networks")
643 674
    for counter, network in enumerate(networks):
644 675
      network_name = "%s%s" % (network["mode"], counter)
645 676
      network_attrib = {"ovf:name": network_name}
......
647 678

  
648 679
      # Item in VirtualHardwareSection creation
649 680
      network_item = ET.Element("Item")
681
      SubElementText(network_item, "rasd:Address", network["mac"])
682
      SubElementText(network_item, "rasd:Connection", network_name)
650 683
      SubElementText(network_item, "rasd:ElementName", network_name)
684
      SubElementText(network_item, "rasd:InstanceID", self.next_instance_id)
651 685
      SubElementText(network_item, "rasd:ResourceType",
652 686
        RASD_TYPE["ethernet-adapter"])
653
      SubElementText(network_item, "rasd:Connection", network_name)
654
      SubElementText(network_item, "rasd:Address", network["mac"])
655 687
      self.hardware_list.append(network_item)
688
      self.next_instance_id += 1
656 689

  
657 690
  @staticmethod
658 691
  def _SaveNameAndParams(root, data):
......
720 753
    assert(memory > 0)
721 754
    vs_attrib = {"ovf:id": name}
722 755
    virtual_system = ET.SubElement(self.tree, "VirtualSystem", attrib=vs_attrib)
756
    SubElementText(virtual_system, "Info", "A virtual machine")
723 757

  
724 758
    name_section = ET.SubElement(virtual_system, "Name")
725 759
    name_section.text = name
726 760
    os_attrib = {"ovf:id": "0"}
727
    ET.SubElement(virtual_system, "OperatingSystemSection",
761
    os_section = ET.SubElement(virtual_system, "OperatingSystemSection",
728 762
      attrib=os_attrib)
763
    SubElementText(os_section, "Info", "Installed guest operating system")
729 764
    hardware_section = ET.SubElement(virtual_system, "VirtualHardwareSection")
765
    SubElementText(hardware_section, "Info", "Virtual hardware requirements")
730 766

  
731 767
    # System description
732 768
    system = ET.SubElement(hardware_section, "System")
733 769
    SubElementText(system, "vssd:ElementName", "Virtual Hardware Family")
734
    SubElementText(system, "vssd:InstanceId", SYSTEM_ID)
770
    SubElementText(system, "vssd:InstanceID", INSTANCE_ID["system"])
735 771
    SubElementText(system, "vssd:VirtualSystemIdentifier", name)
736
    SubElementText(system, "vssd:VirtualSystemType", "ganeti-ovf")
772
    SubElementText(system, "vssd:VirtualSystemType", self.virtual_system_type)
737 773

  
738 774
    # Item for vcpus
739 775
    vcpus_item = ET.SubElement(hardware_section, "Item")
740 776
    SubElementText(vcpus_item, "rasd:ElementName",
741 777
      "%s virtual CPU(s)" % vcpus)
742
    SubElementText(vcpus_item, "rasd:InstanceID", "1")
778
    SubElementText(vcpus_item, "rasd:InstanceID", INSTANCE_ID["vcpus"])
743 779
    SubElementText(vcpus_item, "rasd:ResourceType", RASD_TYPE["vcpus"])
744 780
    SubElementText(vcpus_item, "rasd:VirtualQuantity", vcpus)
745 781

  
......
747 783
    memory_item = ET.SubElement(hardware_section, "Item")
748 784
    SubElementText(memory_item, "rasd:AllocationUnits", "byte * 2^20")
749 785
    SubElementText(memory_item, "rasd:ElementName", "%sMB of memory" % memory)
750
    SubElementText(memory_item, "rasd:InstanceID", "2")
786
    SubElementText(memory_item, "rasd:InstanceID", INSTANCE_ID["memory"])
751 787
    SubElementText(memory_item, "rasd:ResourceType", RASD_TYPE["memory"])
752 788
    SubElementText(memory_item, "rasd:VirtualQuantity", memory)
753 789

  
754 790
    # Item for scsi controller
755 791
    scsi_item = ET.SubElement(hardware_section, "Item")
756
    SubElementText(scsi_item, "rasd:Address", SYSTEM_ID)
792
    SubElementText(scsi_item, "rasd:Address", INSTANCE_ID["system"])
757 793
    SubElementText(scsi_item, "rasd:ElementName", "scsi_controller0")
794
    SubElementText(scsi_item, "rasd:InstanceID", INSTANCE_ID["scsi"])
795
    SubElementText(scsi_item, "rasd:ResourceSubType", SCSI_SUBTYPE)
758 796
    SubElementText(scsi_item, "rasd:ResourceType", RASD_TYPE["scsi-controller"])
759
    SubElementText(scsi_item, "rasd:InstanceId", "3")
760 797

  
761 798
    # Other items - from self.hardware_list
762
    for counter, item in enumerate(self.hardware_list):
763
      SubElementText(item, "rasd:InstanceID", counter + 4)
799
    for item in self.hardware_list:
764 800
      hardware_section.append(item)
765 801

  
766 802
  def PrettyXmlDump(self):
......
1324 1360
                                   " paths or paths outside main OVF directory")
1325 1361
      disk, _ = os.path.splitext(disk_name)
1326 1362
      disk_path = utils.PathJoin(self.input_dir, disk_name)
1327
      if disk_compression:
1363
      if disk_compression not in NO_COMPRESSION:
1328 1364
        _, disk_path = self._CompressDisk(disk_path, disk_compression,
1329 1365
          DECOMPRESS)
1330 1366
        disk, _ = os.path.splitext(disk)
......
1709 1745
    logging.info("Preparing tarball for the OVF package")
1710 1746
    open(tar_path, mode="w").close()
1711 1747
    ova_package = tarfile.open(name=tar_path, mode="w")
1712
    for file_name in files_list:
1713
      ova_package.add(file_name)
1748
    for file_path in files_list:
1749
      file_name = os.path.basename(file_path)
1750
      ova_package.add(file_path, arcname=file_name)
1714 1751
    ova_package.close()
1715 1752

  
1716 1753
  def Save(self):
b/test/ganeti.ovf_unittest.py
237 237
                "AllocationSettingData\" xmlns:vssd=\"http://schemas.dmtf.org"
238 238
                "/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData\""
239 239
                " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" />")
240
EXPORT_DISKS_EMPTY = "<References /><DiskSection />"
240
EXPORT_DISKS_EMPTY = ("<References /><DiskSection><Info>Virtual disk"
241
                      " information</Info></DiskSection>")
241 242
EXPORT_DISKS = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_disk"
242 243
                ".cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:href="
243 244
                "\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
244
                "</References><DiskSection><Disk ovf:capacity=\"90000\""
245
                " ovf:diskId=\"disk0\" ovf:fileRef=\"file0\" ovf:format=\"http"
246
                "://www.vmware.com/interfaces/specifications/vmdk.html"
247
                "#monolithicSparse\" /><Disk ovf:capacity=\"15\" ovf:diskId="
248
                "\"disk1\" ovf:fileRef=\"file1\" ovf:format=\"http://www.gnome"
249
                ".org/~markmc/qcow-image-format.html\" /></DiskSection>")
250
EXPORT_NETWORKS_EMPTY = "<NetworkSection />"
251
EXPORT_NETWORKS = ("<NetworkSection><Network ovf:name=\"routed0\" />"
252
                   "</NetworkSection>")
245
                "</References><DiskSection><Info>Virtual disk information"
246
                "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\" ovf"
247
                ":fileRef=\"file0\" ovf:format=\"http://www.vmware.com/"
248
                "interfaces/specifications/vmdk.html#monolithicSparse\" /><Disk"
249
                " ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
250
                "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
251
                "-image-format.html\" /></DiskSection>")
252
EXPORT_NETWORKS_EMPTY = ("<NetworkSection><Info>List of logical networks</Info>"
253
                         "</NetworkSection>")
254
EXPORT_NETWORKS = ("<NetworkSection><Info>List of logical networks</Info>"
255
                   "<Network ovf:name=\"routed0\" /></NetworkSection>")
253 256
EXPORT_GANETI_INCOMPLETE = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version>"
254 257
                            "<gnt:AutoBalance>True</gnt:AutoBalance><gnt:"
255 258
                            "OperatingSystem><gnt:Name>lenny-image</gnt:Name>"
......
274 277
EXPORT_SYSTEM = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_"
275 278
                 "disk.cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:"
276 279
                 "href=\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
277
                 "</References><DiskSection><Disk ovf:capacity=\"90000\" ovf:"
278
                 "diskId=\"disk0\" ovf:fileRef=\"file0\" ovf:format=\"http://"
279
                 "www.vmware.com/interfaces/specifications/vmdk.html#monolithic"
280
                 "Sparse\" /><Disk ovf:capacity=\"15\" ovf:diskId=\"disk1\""
281
                 " ovf:fileRef=\"file1\" ovf:format=\"http://www.gnome.org/"
282
                 "~markmc/qcow-image-format.html\" /></DiskSection><Network"
283
                 "Section><Network ovf:name=\"routed0\" /></NetworkSection>"
284
                 "<VirtualSystem ovf:id=\"xen-dev-i1\"><Name>xen-dev-i1</Name>"
285
                 "<OperatingSystemSection ovf:id=\"0\" /><VirtualHardware"
286
                 "Section><System><vssd:ElementName>Virtual Hardware Family"
287
                 "</vssd:ElementName><vssd:InstanceId>0</vssd:InstanceId><vssd:"
280
                 "</References><DiskSection><Info>Virtual disk information"
281
                 "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\""
282
                 " ovf:fileRef=\"file0\" ovf:format=\"http://www.vmware.com"
283
                 "/interfaces/specifications/vmdk.html#monolithicSparse\" />"
284
                 "<Disk ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
285
                 "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
286
                 "-image-format.html\" /></DiskSection><NetworkSection><Info>"
287
                 "List of logical networks</Info><Network ovf:name=\"routed0\""
288
                 " /></NetworkSection><VirtualSystem ovf:id=\"xen-dev-i1\">"
289
                 "<Info>A virtual machine</Info><Name>xen-dev-i1</Name>"
290
                 "<OperatingSystemSection ovf:id=\"0\"><Info>Installed guest"
291
                 " operating system</Info></OperatingSystemSection><Virtual"
292
                 "HardwareSection><Info>Virtual hardware requirements</Info>"
293
                 "<System><vssd:ElementName>Virtual Hardware Family"
294
                 "</vssd:ElementName><vssd:InstanceID>0</vssd:InstanceID><vssd:"
288 295
                 "VirtualSystemIdentifier>xen-dev-i1</vssd:VirtualSystem"
289 296
                 "Identifier><vssd:VirtualSystemType>ganeti-ovf</vssd:Virtual"
290 297
                 "SystemType></System><Item><rasd:ElementName>1 virtual CPU(s)"
......
296 303
                 "InstanceID><rasd:ResourceType>4</rasd:ResourceType><rasd:"
297 304
                 "VirtualQuantity>512</rasd:VirtualQuantity></Item><Item>"
298 305
                 "<rasd:Address>0</rasd:Address><rasd:ElementName>scsi"
299
                 "_controller0</rasd:ElementName><rasd:ResourceType>6</rasd"
300
                 ":ResourceType><rasd:InstanceId>3</rasd:InstanceId></Item>"
301
                 "<Item><rasd:ElementName>disk0</rasd:ElementName><rasd:"
302
                 "ResourceType>17</rasd:ResourceType><rasd:HostResource>ovf:/"
303
                 "disk/disk0</rasd:HostResource><rasd:Parent>3</rasd:Parent>"
304
                 "<rasd:InstanceID>4</rasd:InstanceID></Item><Item><rasd:"
305
                 "ElementName>disk1</rasd:ElementName><rasd:ResourceType>17"
306
                 "</rasd:ResourceType><rasd:HostResource>ovf:/disk/disk1</rasd:"
307
                 "HostResource><rasd:Parent>3</rasd:Parent><rasd:InstanceID>5"
308
                 "</rasd:InstanceID></Item><Item><rasd:ElementName>routed0"
309
                 "</rasd:ElementName><rasd:ResourceType>10</rasd:ResourceType>"
310
                 "<rasd:Connection>routed0</rasd:Connection><rasd:Address>aa:00"
311
                 ":00:d8:2c:1e</rasd:Address><rasd:InstanceID>6</rasd:Instance"
312
                 "ID></Item></VirtualHardwareSection></VirtualSystem>")
306
                 "_controller0</rasd:ElementName><rasd:InstanceID>3"
307
                 "</rasd:InstanceID><rasd:ResourceSubType>lsilogic</rasd"
308
                 ":ResourceSubType><rasd:ResourceType>6</rasd:ResourceType>"
309
                 "</Item><Item><rasd:ElementName>disk0</rasd:ElementName><rasd"
310
                 ":HostResource>ovf:/disk/disk0</rasd:HostResource><rasd"
311
                 ":InstanceID>4</rasd:InstanceID><rasd:Parent>3</rasd:Parent>"
312
                 "<rasd:ResourceType>17</rasd:ResourceType></Item><Item><rasd:"
313
                 "ElementName>disk1</rasd:ElementName><rasd:HostResource>ovf:/"
314
                 "disk/disk1</rasd:HostResource><rasd:InstanceID>5</rasd"
315
                 ":InstanceID><rasd:Parent>3</rasd:Parent><rasd:ResourceType>17"
316
                 "</rasd:ResourceType></Item><Item><rasd:Address>aa:00"
317
                 ":00:d8:2c:1e</rasd:Address><rasd:Connection>routed0</rasd"
318
                 ":Connection><rasd:ElementName>routed0</rasd:ElementName><rasd"
319
                 ":InstanceID>6</rasd:InstanceID><rasd:ResourceType>10</rasd"
320
                 ":ResourceType></Item></VirtualHardwareSection>"
321
                 "</VirtualSystem>")
313 322

  
314 323

  
315 324
def _GetArgs(args, with_name=False):

Also available in: Unified diff