nova 热迁移卷 的关键代码 rebase说明

来源:互联网 发布:用js写满天闪烁的星星 编辑:程序博客网 时间:2024/05/07 16:32

cinder的migrate功能,如果遇到热迁移(卷已经挂载在虚机)的情况:cinder在目标后端host上创建好卷,然后交给nova;nova保证两个卷都挂着,然后调用nova.virt.libvirt.guest.BlockDevice的几个方法,实现硬盘数据从原卷到新卷的拷贝,然后修改虚机的xml配置文件(即virsh dumpxml instance-xxxxx 出来的xml文件,保存了虚拟机的配置信息)。

  1. abort_job():
    同步终止关于硬盘的所有读写操作。
  2. rebase(new_path, copy=True, reuse_ext=True):
    在路径new_path(即新硬盘)为磁盘创建一个备份,同时reuse_ext=True指定了在拷贝过程中还可以写硬盘,但是此时不是写在块设备中,而是写在nova本地的一个文件中。
  3. dev.is_job_complete()检查job是否完成。
  4. dev.abort_job(pivot=True):
    停止磁盘的读写,并且将过程2中的读写内容合并。
  5. self._host.write_instance_config(xml):

nova.virt.libvirt.driver.LibvirtDriver#_swap_volume

    def _swap_volume(self, guest, disk_path, conf, resize_to):        """Swap existing disk with a new block device."""        dev = guest.get_block_device(disk_path)        # Save a copy of the domain's persistent XML file        xml = guest.get_xml_desc(dump_inactive=True, dump_sensitive=True)        # Abort is an idempotent operation, so make sure any block        # jobs which may have failed are ended.        try:            dev.abort_job()        except Exception:            pass        try:            # NOTE (rmk): blockRebase cannot be executed on persistent            #             domains, so we need to temporarily undefine it.            #             If any part of this block fails, the domain is            #             re-defined regardless.            if guest.has_persistent_configuration():                support_uefi = self._has_uefi_support()                guest.delete_configuration(support_uefi)            try:                # Start copy with VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT flag to                # allow writing to existing external volume file. Use                # VIR_DOMAIN_BLOCK_REBASE_COPY_DEV if it's a block device to                # make sure XML is generated correctly (bug 1691195)                copy_dev = conf.source_type == 'block'                dev.rebase(conf.source_path, copy=True, reuse_ext=True,                           copy_dev=copy_dev)                while not dev.is_job_complete():                    time.sleep(0.5)                dev.abort_job(pivot=True)            except Exception as exc:                LOG.exception("Failure rebasing volume %(new_path)s on "                    "%(old_path)s.", {'new_path': conf.source_path,                                      'old_path': disk_path})                raise exception.VolumeRebaseFailed(reason=six.text_type(exc))            if resize_to:                dev.resize(resize_to * units.Gi / units.Ki)        finally:            self._host.write_instance_config(xml)

nova.virt.libvirt.guest.BlockDevice#rebase

    def rebase(self, base, shallow=False, reuse_ext=False,               copy=False, relative=False, copy_dev=False):        """Copy data from backing chain into a new disk        This copies data from backing file(s) into overlay(s), giving        control over several aspects like what part of a disk image        chain to be copied, whether to reuse an existing destination        file, etc.  And updates the backing file to the new disk        :param shallow: Limit copy to top of the source backing chain        :param reuse_ext: Reuse an existing external file that was                          pre-created        :param copy: Start a copy job        :param relative: Keep backing chain referenced using relative names        :param copy_dev: Treat the destination as type="block"        """        flags = shallow and libvirt.VIR_DOMAIN_BLOCK_REBASE_SHALLOW or 0        flags |= reuse_ext and libvirt.VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT or 0        flags |= copy and libvirt.VIR_DOMAIN_BLOCK_REBASE_COPY or 0        flags |= copy_dev and libvirt.VIR_DOMAIN_BLOCK_REBASE_COPY_DEV or 0        flags |= relative and libvirt.VIR_DOMAIN_BLOCK_REBASE_RELATIVE or 0        return self._guest._domain.blockRebase(            self._disk, base, self.REBASE_DEFAULT_BANDWIDTH, flags=flags)
原创粉丝点击