Here's a patch that allows to install Red Hat based systems, for example Oracle
Linux.  Tested with OEL.

The hypervisor by default offers a device named 'sda'.  If the SCSI module is
already loaded, the disk device can't be created due to naming conflict, and
the disk is not available.  A workaround is to modify the initrd by removing
the scsi driver from it.  This helps, but doesn't allow to install the OS.

Red Hat's installer, anaconda, runs parted, which tries to execute a check
against /dev/sda and fails.  This makes anaconda think that the disk is faulty,
and not available.  The best way to work around this, is to declare 'xvda' as
the xen disk device.

This patch allows to pass -H xen-pvm:blockdev_prefix="xvd" and successfully run
the Red Hat installer.

Maciej

---
 lib/constants.py         |    4 ++++
 lib/hypervisor/hv_xen.py |   32 +++++++++++++++++++++-----------
 man/gnt-instance.rst     |    7 +++++++
 3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/lib/constants.py b/lib/constants.py
index 63807ad..1222bf9 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -580,6 +580,7 @@ HV_VHOST_NET = "vhost_net"
 HV_KVM_USE_CHROOT = "use_chroot"
 HV_CPU_MASK = "cpu_mask"
 HV_MEM_PATH = "mem_path"
+HV_BLOCKDEV_PREFIX = "blockdev_prefix"
 
 HVS_PARAMETER_TYPES = {
   HV_BOOT_ORDER: VTYPE_STRING,
@@ -617,6 +618,7 @@ HVS_PARAMETER_TYPES = {
   HV_KVM_USE_CHROOT: VTYPE_BOOL,
   HV_CPU_MASK: VTYPE_STRING,
   HV_MEM_PATH: VTYPE_STRING,
+  HV_BLOCKDEV_PREFIX: VTYPE_STRING,
   }
 
 HVS_PARAMETERS = frozenset(HVS_PARAMETER_TYPES.keys())
@@ -953,6 +955,7 @@ HVC_DEFAULTS = {
     HV_KERNEL_ARGS: 'ro',
     HV_MIGRATION_PORT: 8002,
     HV_MIGRATION_MODE: HT_MIGRATION_LIVE,
+    HV_BLOCKDEV_PREFIX: "sd",
     },
   HT_XEN_HVM: {
     HV_BOOT_ORDER: "cd",
@@ -968,6 +971,7 @@ HVC_DEFAULTS = {
     HV_MIGRATION_PORT: 8002,
     HV_MIGRATION_MODE: HT_MIGRATION_NONLIVE,
     HV_USE_LOCALTIME: False,
+    HV_BLOCKDEV_PREFIX: "hd",
     },
   HT_KVM: {
     HV_KERNEL_PATH: "/boot/vmlinuz-2.6-kvmU",
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index bdf38a4..8f1a58b 100644
--- a/lib/hypervisor/hv_xen.py
+++ b/lib/hypervisor/hv_xen.py
@@ -312,7 +312,7 @@ class XenHypervisor(hv_base.BaseHypervisor):
       return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
 
   @staticmethod
-  def _GetConfigFileDiskData(block_devices):
+  def _GetConfigFileDiskData(block_devices, blockdev_prefix):
     """Get disk directive for xen config file.
 
     This method builds the xen config disk directive according to the
@@ -321,6 +321,8 @@ class XenHypervisor(hv_base.BaseHypervisor):
     @param block_devices: list of tuples (cfdev, rldev):
         - cfdev: dict containing ganeti config disk part
         - rldev: ganeti.bdev.BlockDev object
+    @param blockdev_prefix: a string containing blockdevice prefix,
+                            e.g. "sd" for /dev/sda
 
     @return: string containing disk directive for xen instance config file
 
@@ -333,9 +335,7 @@ class XenHypervisor(hv_base.BaseHypervisor):
     if len(block_devices) > 24:
       # 'z' - 'a' = 24
       raise errors.HypervisorError("Too many disks")
-    # FIXME: instead of this hardcoding here, each of PVM/HVM should
-    # directly export their info (currently HVM will just sed this info)
-    namespace = ["sd" + chr(i + ord('a')) for i in range(24)]
+    namespace = [blockdev_prefix + chr(i + ord('a')) for i in range(24)]
     for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
       if cfdev.mode == constants.DISK_RDWR:
         mode = "w"
@@ -459,6 +459,8 @@ class XenPvmHypervisor(XenHypervisor):
     constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
     constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
     constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
+    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
+    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
     }
 
   @classmethod
@@ -509,7 +511,8 @@ class XenPvmHypervisor(XenHypervisor):
         nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
       vif_data.append("'%s'" % nic_str)
 
-    disk_data = cls._GetConfigFileDiskData(block_devices)
+    disk_data = cls._GetConfigFileDiskData(block_devices,
+                                           hvp[constants.HV_BLOCKDEV_PREFIX])
 
     config.write("vif = [%s]\n" % ",".join(vif_data))
     config.write("disk = [%s]\n" % ",".join(disk_data))
@@ -639,13 +642,20 @@ class XenHvmHypervisor(XenHypervisor):
       vif_data.append("'%s'" % nic_str)
 
     config.write("vif = [%s]\n" % ",".join(vif_data))
-    disk_data = cls._GetConfigFileDiskData(block_devices)
+
+    blockdev_prefix = hvp[constants.HV_BLOCKDEV_PREFIX]
+    # A special case for HT_DISK_IOEMU; if the blockdev prefix hasn't been
+    # specified, use "ioemu:hd".
+    default_blockdev = (
+        constants.HVC_DEFAULTS[HT_XEN_HVM[constants.HV_BLOCKDEV_PREFIX]])
     disk_type = hvp[constants.HV_DISK_TYPE]
-    if disk_type in (None, constants.HT_DISK_IOEMU):
-      replacement = ",ioemu:hd"
-    else:
-      replacement = ",hd"
-    disk_data = [line.replace(",sd", replacement) for line in disk_data]
+    disk_is_ioemu = disk_type in (None, constants.HT_DISK_IOEMU)
+    prefix_is_default = blockdev_prefix == default_blockdev
+    if (prefix_is_default and disk_is_ioemu):
+      blockdev_prefix = "ioemu:hd"
+
+    disk_data = cls._GetConfigFileDiskData(block_devices, blockdev_prefix)
+
     iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
     if iso_path:
       iso = "'file:%s,hdc:cdrom,r'" % iso_path
diff --git a/man/gnt-instance.rst b/man/gnt-instance.rst
index 08b7e00..ae5ce46 100644
--- a/man/gnt-instance.rst
+++ b/man/gnt-instance.rst
@@ -185,6 +185,13 @@ boot\_order
     interfaces. This has been fixed in more recent versions and is
     confirmed to work at least with qemu-kvm 0.11.1.
 
+blockdev\_prefix
+    Valid for the Xen HVM and PVM hypervisors.
+
+    Relevant to nonpvops guest kernels, in which the disk device names are
+    given by the host.  Allows to specify 'xvd', which helps run Red Hat based
+    installers, driven by anaconda.
+
 cdrom\_image\_path
     Valid for the Xen HVM and KVM hypervisors.
 
-- 
1.7.3.1

Reply via email to