コード例 #1
0
ファイル: kvm.py プロジェクト: seqizz/igvm
def migrate_background(
    domain,
    source,
    destination,
    migrate_params,
    migrate_flags,
):
    # As it seems it is possible to call multiple functions in parallel
    # from different threads.
    try:
        domain.migrateToURI3(
            MIGRATE_CONFIG.get((source.dataset_obj['os'],
                                destination.dataset_obj['os']))['uri'].format(
                                    destination=destination.fqdn),
            migrate_params,
            migrate_flags,
        )
    except libvirtError as e:
        if virGetLastError()[0] == VIR_ERR_OPERATION_ABORTED:
            raise MigrationAborted('Migration aborted by user')
        raise MigrationError(e)
コード例 #2
0
ファイル: kvm.py プロジェクト: seqizz/igvm
def migrate_live(source, destination, vm, domain):
    """Live-migrates a VM via libvirt."""

    # Reduce CPU pinning to minimum number of available cores on both
    # hypervisors to avoid "invalid cpuset" errors.
    props = DomainProperties.from_running(source, vm, domain)
    _live_repin_cpus(
        domain,
        props,
        min(source.dataset_obj['num_cpu'], destination.dataset_obj['num_cpu']),
    )

    migrate_flags = (
        VIR_MIGRATE_LIVE |  # Do it live
        VIR_MIGRATE_PERSIST_DEST |  # Define the VM on the new host
        VIR_MIGRATE_CHANGE_PROTECTION |  # Protect source VM
        VIR_MIGRATE_NON_SHARED_DISK |  # Copy non-shared storage
        VIR_MIGRATE_AUTO_CONVERGE |  # Slow down VM if can't migrate memory
        VIR_MIGRATE_ABORT_ON_ERROR  # Don't tolerate soft errors
    )

    migrate_params = {}

    # Append OS-specific migration commands.  They might not exist for some
    # combinations but this should have already been checked by the caller.
    migrate_flags |= MIGRATE_CONFIG.get(
        (source.dataset_obj['os'], destination.dataset_obj['os']))['flags']

    log.info('Starting online migration of vm {} from {} to {}'.format(
        vm,
        source,
        destination,
    ))

    future = parallel(
        migrate_background,
        args=[[
            domain,
            source,
            destination,
            migrate_params,
            migrate_flags,
        ]],
        workers=1,
        return_results=False,
    )[0]

    try:
        while future.running():
            try:
                js = domain.jobStats()
            except libvirtError:
                # When migration is finished, jobStats will fail
                break
            if 'memory_total' in js and 'disk_total' in js:
                log.info(
                    ('Migration progress: '
                     'disk {:.0f}% {:.0f}/{:.0f}MiB, '
                     'memory {:.0f}% {:.0f}/{:.0f}MiB, ').format(
                         js['disk_processed'] / (js['disk_total'] + 1) * 100,
                         js['disk_processed'] / 1024 / 1024,
                         js['disk_total'] / 1024 / 1024,
                         js['memory_processed'] / (js['memory_total'] + 1) *
                         100,
                         js['memory_processed'] / 1024 / 1024,
                         js['memory_total'] / 1024 / 1024,
                     ))
            else:
                log.info('Waiting for migration stats to show up')
            time.sleep(1)
    except KeyboardInterrupt:
        domain.abortJob()
        log.info('Awaiting migration to abort')
        future.result()
        # Nothing to log, the function above raised an exception
    else:
        log.info('Awaiting migration to finish')
        future.result()  # Exception from slave thread will re-raise here
        log.info('Migration finished')

        # And pin again, in case we migrated to a host with more physical cores
        domain = destination._get_domain(vm)
        _live_repin_cpus(domain, props, destination.dataset_obj['num_cpu'])