Adam Litke has uploaded a new change for review. Change subject: Live Merge: Restore watermark tracking ......................................................................
Live Merge: Restore watermark tracking Change-Id: I632f31e7795ec5d8c6f52a480116b14470c3163f Signed-off-by: Adam Litke <ali...@redhat.com> --- M vdsm/virt/vm.py 1 file changed, 108 insertions(+), 10 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/36924/1 diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py index f22610d..09080b9 100644 --- a/vdsm/virt/vm.py +++ b/vdsm/virt/vm.py @@ -1512,12 +1512,94 @@ with self._confLock: self.conf['timeOffset'] = newTimeOffset + def _getWriteWatermarks(self): + def pathToVolID(drive, path): + for vol in drive.volumeChain: + if os.path.realpath(vol['path']) == os.path.realpath(path): + return vol['volumeID'] + raise LookupError("Unable to find VolumeID for path '%s'", path) + + volAllocMap = {} + statsFlags = self._libvirtBackingChainStatsFlag() + conn = libvirtconnection.get() + blkStats = conn.domainListGetStats([self._dom._dom], + libvirt.VIR_DOMAIN_STATS_BLOCK, + statsFlags)[0][1] + for i in xrange(0, blkStats['block.count']): + name = blkStats['block.%i.name' % i] + try: + drive = self._findDriveByName(name) + except LookupError: + continue + if not drive.blockDev or drive.format != 'cow': + continue + + try: + path = blkStats['block.%i.path' % i] + alloc = blkStats['block.%i.allocation' % i] + except KeyError as e: + self.log.debug("Block stats are missing expected key '%s', " + "skipping volume", e.args[0]) + continue + volID = pathToVolID(drive, path) + volAllocMap[volID] = alloc + return volAllocMap + + def _getLiveMergeExtendCandidates(self): + # The common case is that there are no active jobs. + if not self.conf['_blockJobs'].values(): + return {} + + candidates = {} + watermarks = self._getWriteWatermarks() + for job in self.conf['_blockJobs'].values(): + try: + drive = self._findDriveByUUIDs(job['disk']) + except LookupError: + # After an active layer merge completes the vdsm metadata will + # be out of sync for a brief period. If we cannot find the old + # disk then it's safe to skip it. + continue + + if not drive.blockDev: + continue + + if job['strategy'] == 'commit': + volumeID = job['baseVolume'] + else: + self.log.debug("Unrecognized merge strategy '%s'", + job['strategy']) + continue + res = self.cif.irs.getVolumeInfo(drive.domainID, drive.poolID, + drive.imageID, volumeID) + if res['status']['code'] != 0: + self.log.error("Unable to get the info of volume %s (domain: " + "%s image: %s)", volumeID, drive.domainID, + drive.imageID) + continue + volInfo = res['info'] + + if volInfo['format'].lower() != 'cow': + continue + + if volumeID in watermarks: + self.log.debug("Adding live merge extension candidate: " + "volume=%s allocation=%i", volumeID, + watermarks[volumeID]) + candidates[drive.imageID] = { + 'alloc': watermarks[volumeID], + 'physical': int(volInfo['truesize']), + 'capacity': int(volInfo['apparentsize']), + 'volumeID': volumeID} + else: + self.log.warning("No watermark info available for %s", + volumeID) + return candidates + def _getExtendCandidates(self): ret = [] - # FIXME: mergeCandidates should be a dictionary of candidate volumes - # once libvirt starts reporting watermark information for all volumes. - mergeCandidates = {} + mergeCandidates = self._getLiveMergeExtendCandidates() for drive in self._devices[hwclass.DISK]: if not drive.blockDev or drive.format != 'cow': continue @@ -4771,6 +4853,14 @@ jobsRet[jobID] = entry return jobsRet + def _libvirtBackingChainStatsFlag(self): + # Since libvirt 1.2.13, the virConnectGetAllDomainStats API will return + # block statistics for all volumes in the chain when using a new flag. + try: + return libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_BACKING + except AttributeError: + return 0 + def merge(self, driveSpec, baseVolUUID, topVolUUID, bandwidth, jobUUID): if not caps.getLiveMergeSupport(): self.log.error("Live merge is not supported on this host") @@ -4815,6 +4905,8 @@ if res['info']['voltype'] == 'SHARED': self.log.error("merge: Refusing to merge into a shared volume") return errCode['mergeErr'] + baseSize = int(res['info']['apparentsize']) + baseCow = bool(res['info']['format'].lower() == 'cow') # Indicate that we expect libvirt to maintain the relative paths of # backing files. This is necessary to ensure that a volume chain is @@ -4865,13 +4957,19 @@ # blockCommit will cause data to be written into the base volume. # Perform an initial extension to ensure there is enough space to - # copy all the required data. Normally we'd use monitoring to extend - # the volume on-demand but internal watermark information is not being - # reported by libvirt so we must do the full extension up front. In - # the worst case, we'll need to extend 'base' to the same size as 'top' - # plus a bit more to accomodate additional writes to 'top' during the - # live merge operation. - self.extendDriveVolume(drive, baseVolUUID, topSize) + # copy all the required data. If libvirt supports monitoring of + # backing chain volumes, just extend by one chunk now and monitor + # during the rest of the operation. Otherwise, extend now to + # accomodate the worst case scenario: no intersection between the + # allocated blocks in the base volume and the top volume. + if drive.blockDev and baseCow: + if self._libvirtBackingChainStatsFlag(): + self.extendDrivesIfNeeded() + else: + extendSize = baseSize + topSize + self.log.debug("Preemptively extending volume %s with size %i" + "(job: %s)", baseVolUUID, extendSize, jobUUID) + self.extendDriveVolume(drive, baseVolUUID, extendCurSize) # Trigger the collection of stats before returning so that callers # of getVmStats after this returns will see the new job -- To view, visit http://gerrit.ovirt.org/36924 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I632f31e7795ec5d8c6f52a480116b14470c3163f Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Adam Litke <ali...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches