Allow multiple bootloader loopback devices Starting several domains concurrently can fail due to using a single bootloader loopback device. This patch creates a list of bootloader loopback devices so more than one instance of bootloader can be run concurrently. Index: xen-4.1.0-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-4.1.0-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-4.1.0-testing/tools/python/xen/xend/XendDomainInfo.py @@ -74,7 +74,7 @@ from xen.xend.XendPSCSI import XendPSCSI from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA MIGRATE_TIMEOUT = 30.0 -BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp' +BOOTLOADER_LOOPBACK_DEVICES = ['/dev/xvd' + chr(x) for x in range(ord('z'), ord('d'), -1)] xc = xen.lowlevel.xc.xc() xoptions = XendOptions.instance() @@ -3299,33 +3299,38 @@ class XendDomainInfo: # This is a file, not a device. pygrub can cope with a # file if it's raw, but if it's QCOW or other such formats # used through blktap, then we need to mount it first. - - log.info("Mounting %s on %s." % - (fn, BOOTLOADER_LOOPBACK_DEVICE)) - - vbd = { - 'mode': 'RW', - 'device': BOOTLOADER_LOOPBACK_DEVICE, - } - - from xen.xend import XendDomain - dom0 = XendDomain.instance().privilegedDomain() - mounted_vbd_uuid = dom0.create_vbd(vbd, disk); - vbd_uuid = dom0.create_vbd(vbd, disk) - dom0._waitForDeviceFrontUUID(vbd_uuid) - fn = BOOTLOADER_LOOPBACK_DEVICE - + # Try all possible loopback_devices + for loopback_device in BOOTLOADER_LOOPBACK_DEVICES: + log.info("Mounting %s on %s." % (fn, loopback_device)) + vbd = { 'mode' : 'RW', 'device' : loopback_device, } + try: + from xen.xend import XendDomain + dom0 = XendDomain.instance().privilegedDomain() + vbd_uuid = dom0.create_vbd(vbd, disk) + dom0._waitForDeviceFrontUUID(vbd_uuid) + fn = loopback_device + break + except VmError, e: + if str(e).find('already connected.') != -1: + continue + elif str(e).find('isn\'t accessible') != -1: + dom0.destroyDevice('vbd', loopback_device, force = True, rm_cfg = True) + continue + else: + raise + else: + raise try: blcfg = bootloader(blexec, fn, self, False, bootloader_args, kernel, ramdisk, args) finally: if mounted: log.info("Unmounting %s from %s." % - (fn, BOOTLOADER_LOOPBACK_DEVICE)) + (fn, loopback_device)) if devtype in ['tap', 'tap2']: - dom0.destroyDevice('tap', BOOTLOADER_LOOPBACK_DEVICE, rm_cfg = True) + dom0.destroyDevice('tap', loopback_device, rm_cfg = True) else: - dom0.destroyDevice('vbd', BOOTLOADER_LOOPBACK_DEVICE, rm_cfg = True) + dom0.destroyDevice('vbd', loopback_device, rm_cfg = True) if blcfg is None: msg = "Had a bootloader specified, but can't find disk" log.error(msg)