Change in vdsm[master]: pool: live storage migration implementation

fsimonce at redhat.com fsimonce at redhat.com
Fri Oct 19 10:43:05 UTC 2012


Federico Simoncelli has posted comments on this change.

Change subject: pool: live storage migration implementation
......................................................................


Patch Set 13: (31 inline comments)

....................................................
File vdsm/libvirtvm.py
Line 126:             if vmDrive.device == 'disk' and vmDrive.isVdsmImage():
Line 127:                 volSize = self._vm.cif.irs.getVolumeSize(vmDrive.domainID,
Line 128:                         vmDrive.poolID, vmDrive.imageID, vmDrive.volumeID)
Line 129: 
Line 130:                 if volSize['status']['code'] == 0:
Done
Line 131:                     continue
Line 132: 
Line 133:                 vmDrive.truesize = int(volSize['truesize'])
Line 134:                 vmDrive.apparentsize = int(volSize['apparentsize'])


Line 1741: 
Line 1742:     def snapshot(self, snapDrives):
Line 1743:         """Live snapshot command"""
Line 1744: 
Line 1745:         def _diskSnapshot(vmDev, newPath):
Done
Line 1746:             """Libvirt snapshot XML"""
Line 1747: 
Line 1748:             disk = xml.dom.minidom.Element('disk')
Line 1749:             disk.setAttribute('name', vmDev)


Line 1990: 
Line 1991:         self.saveState()
Line 1992: 
Line 1993:     def _setDiskReplica(self, srcDrive, dstDisk):
Line 1994:         srcDrive.diskReplicate = dstDisk
Done
Line 1995: 
Line 1996:         for device in self.conf["devices"]:
Line 1997:             if (device['type'] == vm.DISK_DEVICES
Line 1998:                     and device.get("name") == srcDrive.name):


Line 1995: 
Line 1996:         for device in self.conf["devices"]:
Line 1997:             if (device['type'] == vm.DISK_DEVICES
Line 1998:                     and device.get("name") == srcDrive.name):
Line 1999:                 device['diskReplicate'] = dstDisk
Done
Line 2000: 
Line 2001:         self.saveState()
Line 2002: 
Line 2003:     def _hasDiskReplica(self, srcDrive):


Line 1999:                 device['diskReplicate'] = dstDisk
Line 2000: 
Line 2001:         self.saveState()
Line 2002: 
Line 2003:     def _hasDiskReplica(self, srcDrive):
Done
Line 2004:         return hasattr(srcDrive, 'diskReplicate')
Line 2005: 
Line 2006:     def _delDiskReplica(self, srcDrive):
Line 2007:         del srcDrive.diskReplicate


Line 2013: 
Line 2014:         self.saveState()
Line 2015: 
Line 2016:     def diskReplicateStart(self, srcDisk, dstDisk):
Line 2017:         # Finding the source disk name and the destination path
Done
Line 2018:         try:
Line 2019:             srcDrive = self._findDriveByUUIDs(srcDisk)
Line 2020:         except LookupError:
Line 2021:             return errCode['imageErr']


Line 2019:             srcDrive = self._findDriveByUUIDs(srcDisk)
Line 2020:         except LookupError:
Line 2021:             return errCode['imageErr']
Line 2022: 
Line 2023:         # Another replication is ongoing
Done
Line 2024:         if self._hasDiskReplica(srcDrive):
Line 2025:             return errCode['replicaErr']
Line 2026: 
Line 2027:         # Updating the destination disk device and name


Line 2023:         # Another replication is ongoing
Line 2024:         if self._hasDiskReplica(srcDrive):
Line 2025:             return errCode['replicaErr']
Line 2026: 
Line 2027:         # Updating the destination disk device and name
Done
Line 2028:         dstDisk.update({'device': srcDrive.device, 'name': srcDrive.name})
Line 2029: 
Line 2030:         self._setDiskReplica(srcDrive, dstDisk)
Line 2031:         dstDrive = dstDisk.copy()


Line 2024:         if self._hasDiskReplica(srcDrive):
Line 2025:             return errCode['replicaErr']
Line 2026: 
Line 2027:         # Updating the destination disk device and name
Line 2028:         dstDisk.update({'device': srcDrive.device, 'name': srcDrive.name})
The 'device' key is strictly required by prepareVolumePath.
Line 2029: 
Line 2030:         self._setDiskReplica(srcDrive, dstDisk)
Line 2031:         dstDrive = dstDisk.copy()
Line 2032: 


Line 2027:         # Updating the destination disk device and name
Line 2028:         dstDisk.update({'device': srcDrive.device, 'name': srcDrive.name})
Line 2029: 
Line 2030:         self._setDiskReplica(srcDrive, dstDisk)
Line 2031:         dstDrive = dstDisk.copy()
Done
Line 2032: 
Line 2033:         try:
Line 2034:             dstDrive['path'] = self.cif.prepareVolumePath(dstDrive)
Line 2035:             self._dom.blockRebase(srcDrive.name, dstDrive['path'], 0, (


Line 2038:                 libvirt.VIR_DOMAIN_BLOCK_REBASE_SHALLOW
Line 2039:             ))
Line 2040:         except:
Line 2041:             self.log.error("Unable to start the replication for %s to %s",
Line 2042:                            srcDisk.name, dstDrive['path'], exc_info=True)
srcDrive.name
Line 2043: 
Line 2044:             self._delDiskReplica(srcDrive)
Line 2045:             return errCode['replicaErr']
Line 2046: 


Line 2044:             self._delDiskReplica(srcDrive)
Line 2045:             return errCode['replicaErr']
Line 2046: 
Line 2047:         # Request an initial extension if the disk is on a block device
Line 2048:         if srcDrive.blockDev:
Done
Line 2049:             try:
Line 2050:                 self.extendDriveVolume(srcDrive)
Line 2051:             except:
Line 2052:                 self.log.error("Initial extension request failed for %s",


Line 2053:                                srcDrive.name, exc_info=True)
Line 2054: 
Line 2055:         return {'status': doneCode}
Line 2056: 
Line 2057:     def diskReplicateStop(self, srcDisk, dstDisk):
Done
Line 2058:         # Finding the source disk name and the destination path
Line 2059:         try:
Line 2060:             srcDrive = self._findDriveByUUIDs(srcDisk)
Line 2061:         except LookupError:


Line 2067: 
Line 2068:         # Looking for the replication blockJob info (checking its presence)
Line 2069:         blkJobInfo = self._dom.blockJobInfo(srcDrive.name, 0)
Line 2070: 
Line 2071:         if not isinstance(blkJobInfo, dict):
Done
Line 2072:             self.log.error("Replication job not found for disk %s (%s)",
Line 2073:                            srcDrive.name, srcDisk)
Line 2074: 
Line 2075:             # Making sure that we don't have any stale information


Line 2075:             # Making sure that we don't have any stale information
Line 2076:             self._delDiskReplica(srcDrive)
Line 2077:             return errCode['replicaErr']
Line 2078: 
Line 2079:         # Checking if we reached the mirroring mode
Done
Line 2080:         if blkJobInfo['cur'] != blkJobInfo['end']:
Line 2081:             return errCode['unavail']
Line 2082: 
Line 2083:         dstDrive = dstDisk.copy()


Line 2077:             return errCode['replicaErr']
Line 2078: 
Line 2079:         # Checking if we reached the mirroring mode
Line 2080:         if blkJobInfo['cur'] != blkJobInfo['end']:
Line 2081:             return errCode['unavail']
I didn't find anything better, unavail is "Resource unavailable".
Line 2082: 
Line 2083:         dstDrive = dstDisk.copy()
Line 2084: 
Line 2085:         # Updating the destination disk device and name


Line 2079:         # Checking if we reached the mirroring mode
Line 2080:         if blkJobInfo['cur'] != blkJobInfo['end']:
Line 2081:             return errCode['unavail']
Line 2082: 
Line 2083:         dstDrive = dstDisk.copy()
Done
Line 2084: 
Line 2085:         # Updating the destination disk device and name
Line 2086:         dstDrive.update({'device': srcDrive.device, 'name': srcDrive.name})
Line 2087:         dstDrive['path'] = self.cif.prepareVolumePath(dstDrive)


Line 2082: 
Line 2083:         dstDrive = dstDisk.copy()
Line 2084: 
Line 2085:         # Updating the destination disk device and name
Line 2086:         dstDrive.update({'device': srcDrive.device, 'name': srcDrive.name})
Here the name is not redundant, it's the key used by _updateDrive, and 'device' is used by prepareVolumePath.
Line 2087:         dstDrive['path'] = self.cif.prepareVolumePath(dstDrive)
Line 2088: 
Line 2089:         if srcDisk != dstDisk:
Line 2090:             self.log.error("Stopping the disk replication switching to the "


Line 2087:         dstDrive['path'] = self.cif.prepareVolumePath(dstDrive)
Line 2088: 
Line 2089:         if srcDisk != dstDisk:
Line 2090:             self.log.error("Stopping the disk replication switching to the "
Line 2091:                            "destination drive: %s", dstDisk)
log.info
Line 2092:             blockJobFlags = libvirt.VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT
Line 2093:         else:
Line 2094:             self.log.error("Stopping the disk replication remaining on the "
Line 2095:                            "source drive: %s", dstDisk)


Line 2091:                            "destination drive: %s", dstDisk)
Line 2092:             blockJobFlags = libvirt.VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT
Line 2093:         else:
Line 2094:             self.log.error("Stopping the disk replication remaining on the "
Line 2095:                            "source drive: %s", dstDisk)
log.info
Line 2096:             blockJobFlags = 0
Line 2097: 
Line 2098:         self._volumesPrepared = False
Line 2099: 


Line 2094:             self.log.error("Stopping the disk replication remaining on the "
Line 2095:                            "source drive: %s", dstDisk)
Line 2096:             blockJobFlags = 0
Line 2097: 
Line 2098:         self._volumesPrepared = False
Done
Line 2099: 
Line 2100:         # Stopping the replication
Line 2101:         try:
Line 2102:             self._dom.blockJobAbort(srcDrive.name, blockJobFlags)


Line 2108:             self.cif.teardownVolumePath(srcDrive.diskReplicate)
Line 2109: 
Line 2110:             return errCode['changeDisk']
Line 2111:         finally:
Line 2112:             self._volumesPrepared = True
Done
Line 2113: 
Line 2114:         # Tearing down the old drive only if we switched to the new one
Line 2115:         try:
Line 2116:             if blockJobFlags:


Line 2112:             self._volumesPrepared = True
Line 2113: 
Line 2114:         # Tearing down the old drive only if we switched to the new one
Line 2115:         try:
Line 2116:             if blockJobFlags:
Done
Line 2117:                 self.cif.teardownVolumePath(srcDrive)
Line 2118:             else:
Line 2119:                 self.cif.teardownVolumePath(srcDrive.diskReplicate)
Line 2120:         except:


Line 2122:             self.log.error("Unable to teardown the replication source ",
Line 2123:                            "disk", exc_info=True)
Line 2124: 
Line 2125:         # Updating the drive structure
Line 2126:         self._updateDrive(dstDrive)
Done
Line 2127:         self._delDiskReplica(srcDrive)
Line 2128: 
Line 2129:         return {'status': doneCode}
Line 2130: 


....................................................
File vdsm/storage/hsm.py
Line 1345:                     misc.parseBool(force)
Line 1346:         )
Line 1347: 
Line 1348:     @public
Line 1349:     def syncImage(self, spUUID, sdUUID, imgUUID, dstSdUUID, operations):
Done
Line 1350:         """
Line 1351:         Synchronize images between storage domains within same storage pool
Line 1352:         """
Line 1353:         pool = self.getPool(spUUID)


Line 1347: 
Line 1348:     @public
Line 1349:     def syncImage(self, spUUID, sdUUID, imgUUID, dstSdUUID, operations):
Line 1350:         """
Line 1351:         Synchronize images between storage domains within same storage pool
Done
Line 1352:         """
Line 1353:         pool = self.getPool(spUUID)
Line 1354: 
Line 1355:         srcDom = self.validateSdUUID(sdUUID)


Line 1353:         pool = self.getPool(spUUID)
Line 1354: 
Line 1355:         srcDom = self.validateSdUUID(sdUUID)
Line 1356:         dstDom = self.validateSdUUID(dstSdUUID)
Line 1357:         self.validateImageMove(srcDom, dstDom, imgUUID)
Done
Line 1358: 
Line 1359:         for dom in sorted((sdUUID, dstSdUUID)):
Line 1360:             vars.task.getSharedLock(STORAGE, dom)
Line 1361: 


....................................................
File vdsm/storage/sp.py
Line 1750:         srcImgResNs = sd.getNamespace(sdUUID, IMAGE_NAMESPACE)
Line 1751:         dstImgResNs = sd.getNamespace(dstSdUUID, IMAGE_NAMESPACE)
Line 1752: 
Line 1753:         # Preparing the ordered resource list to be acquired
Line 1754:         resList = (rmanager.acquireResource(*x) for x in sorted((
Yes indeed it acquires the resources, but it does that in the correct order. This is also what happens at line 1787. The nested( *resList) is basically used only to release the resources (__enter__ is a simple "return self", __exit__ is instead a real release of the resource). Ugly, but there's no time to fix infra issues.
Line 1755:             (srcImgResNs, imgUUID, rm.LockType.shared),
Line 1756:             (dstImgResNs, imgUUID, rm.LockType.exclusive),
Line 1757:         )))
Line 1758: 


....................................................
File vdsm/vm.py
Line 721:         self.conf['timeOffset'] = timeOffset
Line 722: 
Line 723:     def extendDriveVolume(self, vmDrive, newSize=None):
Line 724:         if not vmDrive.blockDev:
Line 725:             self.log.error("The device %s is not a block device", vmDrive.name)
Done
Line 726:             return
Line 727: 
Line 728:         if newSize is None:
Line 729:             newSize = (config.getint('irs', 'volume_utilization_chunk_mb')


Line 735:                        'imageID': vmDrive.diskReplicate['imageID'],
Line 736:                        'volumeID': vmDrive.diskReplicate['volumeID'],
Line 737:                        'name': vmDrive.name, 'newSize': newSize}
Line 738:             self.log.debug("Requesting extension for the replica volume: %s",
Line 739:                            volInfo)
I can't, __extendDriveVolume takes a drive object, here we're building an extend request from a PDIV (diskReplicate).
Line 740:             self.cif.irs.sendExtendMsg(vmDrive.poolID, volInfo,
Line 741:                                        newSize, self.__afterReplicaExtend)
Line 742:         else:
Line 743:             self.__extendDriveVolume(vmDrive, newSize)


Line 758:             self._guestCpuLock.release()
Line 759: 
Line 760:     def __afterReplicaExtend(self, volInfo):
Line 761:         self.log.debug("Refreshing replica volume: %s", volInfo)
Line 762:         self.__refreshDriveVolume(volInfo)
Done
Line 763: 
Line 764:         vmDrive = self._findDriveByName(volInfo['name'])
Line 765: 
Line 766:         self.log.debug("Requesting extension for the original drive: %s",


--
To view, visit http://gerrit.ovirt.org/5252
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: comment
Gerrit-Change-Id: I91e641cb1d25feb8a406aa7ad07415587a7ac290
Gerrit-PatchSet: 13
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Federico Simoncelli <fsimonce at redhat.com>
Gerrit-Reviewer: Ayal Baron <abaron at redhat.com>
Gerrit-Reviewer: Federico Simoncelli <fsimonce at redhat.com>
Gerrit-Reviewer: Maor Lipchuk <mlipchuk at redhat.com>
Gerrit-Reviewer: Royce Lv <lvroyce at linux.vnet.ibm.com>
Gerrit-Reviewer: Saggi Mizrahi <smizrahi at redhat.com>
Gerrit-Reviewer: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
Gerrit-Reviewer: Shu Ming <shuming at linux.vnet.ibm.com>
Gerrit-Reviewer: oVirt Jenkins CI Server


More information about the vdsm-patches mailing list