[et-mgmt-tools] [PATCH 10 of 11] Support CD-ROMs
john.levon at sun.com
john.levon at sun.com
Mon Jul 7 22:51:40 UTC 2008
# HG changeset patch
# User john.levon at sun.com
# Date 1215470463 25200
# Node ID bed866186030cc9549f6a020e0abda871fc008c2
# Parent 26beabc283b11e40ed01584be33678fd0840fed2
Support CD-ROMs
Add support for CD-ROMs and also extend disk handling with some hokey checks
for block versus file.
Signed-off-by: John Levon <john.levon at sun.com>
diff --git a/virtconv/parsers/virtimage.py b/virtconv/parsers/virtimage.py
--- a/virtconv/parsers/virtimage.py
+++ b/virtconv/parsers/virtimage.py
@@ -35,7 +35,7 @@ pv_boot_template = """
<os>
<loader>pygrub</loader>
</os>
- %(pv_disks)s
+ %(disks)s
</boot>
"""
@@ -47,7 +47,7 @@ hvm_boot_template = """
<os>
<loader dev="hd" />
</os>
- %(hvm_disks)s
+ %(disks)s
</boot>
"""
@@ -73,6 +73,71 @@ image_template = """
</image>
"""
+def export_disks(vm):
+ """
+ Export code for the disks. Slightly tricky for two reasons.
+
+ We can't handle duplicate disks: some vmx files define SCSI/IDE devices
+ that point to the same storage, and Xen isn't happy about that. We
+ just ignore any entries that have duplicate paths.
+
+ Since there is no meaningful SCSI support in rombios/qemu, we
+ forcibly switch the disks to IDE, and expect the guest OS to cope
+ (which at least Linux does admirably).
+ """
+
+ paths = []
+
+ disks = {}
+
+ for (bus, instance), disk in sorted(vm.disks.iteritems()):
+
+ if disk.path and disk.path in paths:
+ continue
+
+ if bus == "scsi":
+ instance = 0
+ while disks.get(("ide", instance)):
+ instance += 1
+
+ disks[("ide", instance)] = disk
+
+ if disk.path:
+ paths += [ disk.path ]
+
+ diskout = []
+ storage = []
+
+ for (bus, instance), disk in sorted(disks.iteritems()):
+
+ # virt-image XML cannot handle an empty CD device
+ if not disk.path:
+ continue
+
+ path = disk.path
+ drive_nr = ascii_letters[int(instance) % 26]
+
+ disk_prefix = "xvd"
+ if vm.type == vmconfig.VM_TYPE_HVM:
+ if bus == "ide":
+ disk_prefix = "hd"
+ else:
+ disk_prefix = "sd"
+
+ # FIXME: needs updating for later Xen enhancements; need to
+ # implement capabilities checking for max disks etc.
+ diskout.append("""<drive disk="%s" target="%s%s" />\n""" %
+ (path, disk_prefix, drive_nr))
+
+ type = "raw"
+ if disk.type == vmconfig.DISK_TYPE_ISO:
+ type = "iso"
+ storage.append(
+ """<disk file="%s" use="system" format="%s"/>\n""" %
+ (path, type))
+
+ return storage, diskout
+
def export_os_params(vm):
"""
Export OS-specific parameters.
@@ -143,26 +208,7 @@ class virtimage_parser(vmconfig.parser):
if not vm.memory:
raise ValueError("VM must have a memory setting")
- pv_disks = []
- hvm_disks = []
- storage_disks = []
-
- # create disk filename lists for xml template
- for devid, disk in sorted(vm.disks.iteritems()):
- if disk.type != vmconfig.DISK_TYPE_DISK:
- continue
-
- path = disk.path
- drive_nr = ascii_letters[int(devid[1]) % 26]
-
- # FIXME: needs updating for later Xen enhancements; need to
- # implement capabilities checking for max disks etc.
- pv_disks.append("""<drive disk="%s" target="xvd%s" />\n""" %
- (path, drive_nr))
- hvm_disks.append("""<drive disk="%s" target="hd%s" />\n""" %
- (path, drive_nr))
- storage_disks.append(
- """<disk file="%s" use="system" format="raw"/>\n""" % path)
+ (storage, disks) = export_disks(vm)
# Hmm. Any interface is a good interface?
interface = None
@@ -177,8 +223,7 @@ class virtimage_parser(vmconfig.parser):
boot_template = hvm_boot_template
boot_xml = boot_template % {
- "pv_disks" : "".join(pv_disks),
- "hvm_disks" : "".join(hvm_disks),
+ "disks" : "".join(disks),
"arch" : vm.arch,
"acpi" : acpi,
"apic" : apic,
@@ -192,7 +237,7 @@ class virtimage_parser(vmconfig.parser):
# Mb to Kb
"memory" : int(vm.memory) * 1024,
"interface" : interface,
- "storage" : "".join(storage_disks),
+ "storage" : "".join(storage),
}
outfile = open(output_file, "w")
diff --git a/virtconv/parsers/virtinstance.py b/virtconv/parsers/virtinstance.py
--- a/virtconv/parsers/virtinstance.py
+++ b/virtconv/parsers/virtinstance.py
@@ -22,6 +22,8 @@ import virtconv.vmconfig as vmconfig
import virtconv.vmconfig as vmconfig
import virtinst.FullVirtGuest as fv
+import os
+import stat
import re
bootloaders = {
@@ -50,10 +52,10 @@ consoles = {
}
disk_template = """
-<disk type='block' device='disk'>
- <driver name='phy' />
- <source dev='%(path)s' />
+<disk %(typeattr)s device='%(device)s'>
+ %(hostdev)s
<target dev='%(prefix)s%(dev)s' />
+ %(readonly)s
</disk>
"""
@@ -104,7 +106,7 @@ def export_netdevs(vm):
netdevs = []
- for number, netdev in sorted(vm.netdevs.iteritems()):
+ for netdev in vm.netdevs.values():
mac = ""
if netdev.mac != "auto":
mac = "<mac address='%s' />" % netdev.mac
@@ -142,30 +144,97 @@ def export_netdevs(vm):
def export_disks(vm):
"""
- Export code for the disks.
- """
-
- disk_prefix = "xvd"
- if (vm.type == vmconfig.VM_TYPE_HVM):
- disk_prefix = "hd"
-
- disks = []
-
- for devid, disk in sorted(vm.disks.iteritems()):
- if disk.type != vmconfig.DISK_TYPE_DISK:
+ Export code for the disks. Slightly tricky for two reasons.
+
+ We can't handle duplicate disks: some vmx files define SCSI/IDE devices
+ that point to the same storage, and Xen isn't happy about that. We
+ just ignore any entries that have duplicate paths.
+
+ Since there is no meaningful SCSI support in rombios/qemu, we
+ forcibly switch the disks to IDE, and expect the guest OS to cope
+ (which at least Linux does admirably).
+ """
+
+ out = []
+ paths = []
+
+ disks = {}
+
+ for (bus, instance), disk in sorted(vm.disks.iteritems()):
+
+ if disk.path and disk.path in paths:
continue
+
+ if bus == "scsi":
+ instance = 0
+ while disks.get(("ide", instance)):
+ instance += 1
+
+ disks[("ide", instance)] = disk
+
+ if disk.path:
+ paths += [ disk.path ]
+
+ for (bus, instance), disk in sorted(disks.iteritems()):
+
+ if not disk.path:
+ typeattr = ""
+ hostdev = ""
+
+ # It's quite common for .vmx files to reference a
+ # non-existent ISO (which was cleaned up in vmx_parser).
+ # Just skip them.
+ if disk.type == vmconfig.DISK_TYPE_ISO:
+ continue
+ else:
+ # Of course, this file path might be relative, so we won't be
+ # able to stat() it. In such a case, it's almost certainly a
+ # file anyway, so the fallback is fine.
+ typeattr = "type='file'"
+ hostdev = ("<driver name='file' />\n"
+ "<source file='%s' />\n" % disk.path)
+
+ try:
+ if stat.S_ISBLK(os.stat(disk.path)[0]):
+ typeattr = "type='block'"
+ hostdev = ("<driver name='phy' />\n"
+ "<source dev='%s' />\n" % disk.path)
+ except:
+ pass
+
+ device = "disk"
+ readonly = ""
+
+ if (disk.type == vmconfig.DISK_TYPE_CDROM or
+ disk.type == vmconfig.DISK_TYPE_ISO):
+ device = "cdrom"
+ readonly = "<readonly />"
+
+ bus = "ide"
+
+ disk_prefix = "xvd"
+ if vm.type == vmconfig.VM_TYPE_HVM:
+ if bus == "ide":
+ disk_prefix = "hd"
+ else:
+ disk_prefix = "sd"
# FIXME: needs updating for later Xen enhancements; need to
# implement capabilities checking for max disks etc.
- drive_nr = ascii_letters[int(devid[1]) % 26]
-
- disks.append(disk_template % {
- "path" : disk.path,
+ drive_nr = ascii_letters[int(instance) % 26]
+
+ instance += 1
+
+ out.append(disk_template % {
+ "typeattr" : typeattr,
+ "device" : device,
+ "hostdev" : hostdev,
"prefix" : disk_prefix,
- "dev" : drive_nr
+ "dev" : drive_nr,
+ "readonly" : readonly,
})
-
- return disks
+
+ return out
def export_os_params(vm):
"""
diff --git a/virtconv/parsers/vmx.py b/virtconv/parsers/vmx.py
--- a/virtconv/parsers/vmx.py
+++ b/virtconv/parsers/vmx.py
@@ -32,14 +32,18 @@ def parse_disk_entry(vm, fullkey, value)
if re.match(r"^(scsi|ide)[0-9]+[^:]", fullkey):
return
- # FIXME: we don't check bus number, we should
- _, bus, _, inst, key = re.split(r"^(scsi|ide)([0-9]+):([0-9]+)\.",
+ _, bus, bus_nr, inst, key = re.split(r"^(scsi|ide)([0-9]+):([0-9]+)\.",
fullkey)
lvalue = value.lower()
if key == "present" and lvalue == "false":
return
+
+ # Does anyone else think it's scary that we're still doing things
+ # like this?
+ if bus == "ide":
+ inst = int(inst) + int(bus_nr) * 2
devid = (bus, inst)
if not vm.disks.get(devid):
More information about the et-mgmt-tools
mailing list