Esempio n. 1
0
    def merge(self, driveSpec, base, top, bandwidth, job_id):
        bandwidth = int(bandwidth)
        if job_id is None:
            job_id = str(uuid.uuid4())

        try:
            drive = self._vm.findDriveByUUIDs(driveSpec)
        except LookupError:
            raise exception.ImageFileNotFound("Cannot find drive",
                                              driveSpec=driveSpec,
                                              job=job_id)

        job = self._create_job(job_id, drive, base, top, bandwidth)

        try:
            base_info = self._vm.getVolumeInfo(drive.domainID, drive.poolID,
                                               drive.imageID, job.base)
            top_info = self._vm.getVolumeInfo(drive.domainID, drive.poolID,
                                              drive.imageID, job.top)
        except errors.StorageUnavailableError as e:
            raise exception.MergeFailed(str(e),
                                        top=top,
                                        base=job.base,
                                        job=job_id)

        if base_info['voltype'] == 'SHARED':
            raise exception.MergeFailed("Base volume is shared",
                                        base_info=base_info,
                                        job=job_id)

        self._validate_base_size(drive, base_info, top_info)

        if self._base_needs_refresh(drive, base_info):
            self._refresh_base(drive, base_info)

        with self._lock:
            try:
                self._track_job(job, drive)
            except JobExistsError as e:
                raise exception.MergeFailed(str(e), job=job.id)

            if self._base_needs_extend(drive, job, base_info):
                job.extend = {
                    "attempt": 1,
                    "base_size": int(base_info["apparentsize"]),
                    "top_size": int(top_info["apparentsize"]),
                    "capacity": int(top_info["capacity"]),
                }
                self._start_extend(drive, job)
            else:
                self._start_commit(drive, job)

        # Trigger the collection of stats before returning so that callers
        # of getVmStats after this returns will see the new job
        self._vm.updateVmJobs()
Esempio n. 2
0
    def _start_commit(self, drive, job):
        """
        Start libvirt blockCommit block job.

        Must be called under self._lock.
        """
        # Persist the job before starting the commit, to ensure that vdsm will
        # know about the commit if it was killed after the block job was
        # started.
        job.state = Job.COMMIT
        self._persist_jobs()

        # Check that libvirt exposes full volume chain information
        actual_chain = self._vm.query_drive_volume_chain(drive)
        if actual_chain is None:
            self._untrack_job(job.id)
            raise exception.MergeFailed("Cannot get drive actual volume chain",
                                        drive=drive.name,
                                        alias=drive.alias,
                                        job=job.id)

        try:
            base_target = drive.volume_target(job.base, actual_chain)
            top_target = drive.volume_target(job.top, actual_chain)
        except VolumeNotFound as e:
            self._untrack_job(job.id)
            raise exception.MergeFailed(str(e),
                                        top=job.top,
                                        base=job.base,
                                        chain=actual_chain,
                                        job=job.id)

        # Indicate that we expect libvirt to maintain the relative paths of
        # backing files. This is necessary to ensure that a volume chain is
        # visible from any host even if the mountpoint is different.
        flags = libvirt.VIR_DOMAIN_BLOCK_COMMIT_RELATIVE

        if job.top == drive.volumeID:
            # Pass a flag to libvirt to indicate that we expect a two phase
            # block job. In the first phase, data is copied to base. Once
            # completed, an event is raised to indicate that the job has
            # transitioned to the second phase. We must then tell libvirt to
            # pivot to the new active layer (base).
            flags |= libvirt.VIR_DOMAIN_BLOCK_COMMIT_ACTIVE

        orig_chain = [entry.uuid for entry in actual_chain]
        chain_str = logutils.volume_chain_to_str(orig_chain)
        log.info(
            "Starting merge with job_id=%r, original chain=%s, "
            "disk=%r, base=%r, top=%r, bandwidth=%d, flags=%d", job.id,
            chain_str, drive.name, base_target, top_target, job.bandwidth,
            flags)

        try:
            # pylint: disable=no-member
            self._dom.blockCommit(drive.name,
                                  base_target,
                                  top_target,
                                  job.bandwidth,
                                  flags=flags)
        except libvirt.libvirtError as e:
            self._untrack_job(job.id)
            raise exception.MergeFailed(str(e), job=job.id)
Esempio n. 3
0
 # codes 20-35 are reserved for add/delNetwork
 # code 39 was used for:
 # wrongHost - migration destination has an invalid hostname
 'unavail': exception.ResourceUnavailable().response(),
 'changeDisk': exception.ChangeDiskFailed().response(),
 'destroyErr': exception.VMDestroyFailed().response(),
 'fenceAgent': exception.UnsupportedFenceAgent().response(),
 'noimpl': exception.MethodNotImplemented().response(),
 'hotplugDisk': exception.HotplugDiskFailed().response(),
 'hotunplugDisk': exception.HotunplugDiskFailed().response(),
 'migCancelErr': exception.MigrationCancelationFailed().response(),
 'snapshotErr': exception.SnapshotFailed().response(),
 'hotplugNic': exception.HotplugNicFailed().response(),
 'hotunplugNic': exception.HotunplugNicFailed().response(),
 'migInProgress': exception.MigrationInProgress().response(),
 'mergeErr': exception.MergeFailed().response(),
 'balloonErr': exception.BalloonError().response(),
 'momErr': exception.MOMPolicyUpdateFailed().response(),
 'replicaErr': exception.ReplicaError().response(),
 'updateDevice': exception.UpdateDeviceFailed().response(),
 'hwInfoErr': exception.CannotRetrieveHWInfo().response(),
 'resizeErr': exception.BadDiskResizeParameter().response(),
 'transientErr': exception.TransientError().response(),
 'setNumberOfCpusErr': exception.SetNumberOfCpusFailed().response(),
 'haErr': exception.SetHAPolicyFailed().response(),
 'cpuTuneErr': exception.CpuTuneError().response(),
 'updateVmPolicyErr': exception.UpdateVMPolicyFailed().response(),
 'updateIoTuneErr': exception.UpdateIOTuneError().response(),
 'V2VConnection': exception.V2VConnectionError().response(),
 'NoSuchJob': exception.NoSuchJob().response(),
 'V2VNoSuchOvf': exception.V2VNoSuchOVF().response(),