nova I版本虚机热迁移流程源码分析

本文详细分析了OpenStack I版本中Nova的虚机热迁移流程,从admin_actions.py的入口开始,经过compute_api、compute_task_api、conductor_api,直至在conductor中执行migrate_server和_live_migrate。接着,讨论了compute_manager如何在源和目标主机上执行pre_live_migrate和live_migrate,并着重介绍了libvirt驱动的实现细节。
摘要由CSDN通过智能技术生成

      nova有两种虚机迁移方式,一种是冷迁移,另个一种是热迁移,这段时间项目上碰到一些热迁移的问题,正好错这个机会梳理一下nova虚机热迁移的源码,版本是基于openstack I版本的.

      首先从url入口开始nova/openstack/compute/contrib/admin_actions.py中

    @wsgi.action('os-migrateLive')
    def _migrate_live(self, req, id, body):
        """Permit admins to (live) migrate a server to a new host."""
        context = req.environ["nova.context"]
        authorize(context, 'migrateLive')

        try:
            block_migration = body["os-migrateLive"]["block_migration"]
            disk_over_commit = body["os-migrateLive"]["disk_over_commit"]
            host = body["os-migrateLive"]["host"]
        except (TypeError, KeyError):
            msg = _("host, block_migration and disk_over_commit must "
                    "be specified for live migration.")
            raise exc.HTTPBadRequest(explanation=msg)

        try:
            block_migration = strutils.bool_from_string(block_migration,
                                                        strict=True)
            disk_over_commit = strutils.bool_from_string(disk_over_commit,
                                                         strict=True)
        except ValueError as err:
            raise exc.HTTPBadRequest(explanation=str(err))

        try:
            instance = self.compute_api.get(context, id, want_objects=True)
            # 这里主要处理热迁移
            self.compute_api.live_migrate(context, instance, block_migration,
                                          disk_over_commit, host)
        except (exception.ComputeServiceUnavailable,
                exception.InvalidHypervisorType,
                exception.UnableToMigrateToSelf,
                exception.DestinationHypervisorTooOld,
                exception.NoValidHost,
                exception.InvalidLocalStorage,
                exception.InvalidSharedStorage,
                exception.MigrationPreCheckError) as ex:
            raise exc.HTTPBadRequest(explanation=ex.format_message())
        except exception.InstanceNotFound as e:
            raise exc.HTTPNotFound(explanation=e.format_message())
        except exception.InstanceInvalidState as state_error:
            common.raise_http_conflict_for_instance_invalid_state(state_error,
                    'os-migrateLive')
        except Exception:
            if host is None:
                msg = _("Live migration of instance %s to another host "
                        "failed") % id
            else:
                msg = _("Live migration of instance %(id)s to host %(host)s "
                        "failed") % {'id': id, 'host': host}
            LOG.exception(msg)
            # Return messages from scheduler
            raise exc.HTTPBadRequest(explanation=msg)

        return webob.Response(status_int=202)

 执行到self.compute_api.live_migrate(context, instance, block_migration, disk_over_commit, host)接下来转到nova/compute/api.py中

    @check_instance_cell
    @check_instance_state(vm_state=[vm_states.ACTIVE])
    def live_migrate(self, context, instance, block_migration,
                     disk_over_commit, host_name):
        """Migrate a server lively to a new host."""
        LOG.debug(_("Going to try to live migrate instance to %s"),
                  host_name or "another host", instance=instance)
        
        # 将instance的状态转为 migrating
        instance.task_state = task_states.MIGRATING
        instance.save(expected_task_state=[None])

        # 转到conductorapi进行处理
        self.compute_task_api.live_migrate_instance(context, instance,
                host_name, block_migration=block_migration,
                disk_over_commit=disk_over_commit)

compute/api 又调用了compute_task_api,看一下compute_task_api具体初始化过程

    @property
    def compute_task_api(self):
        if self._compute_task_api is None:
            # TODO(alaski): Remove calls into here from conductor manager so
            # that this isn't necessary. #1180540
            from nova import conductor
            # 返回conductor的ComputeTaskAPI实例
            self._compute_task_api = conductor.ComputeTaskAPI()
        return self._compute_task_api

 compute/api主要是将instance实例标记为migrating,接下来转到nova/conductor/api.py ComputeTaskAPI

    def live_migrate_instance(self, context, instance, host_name,
                              block_migration, disk_over_commit):
        scheduler_hint = {'host': host_name}
        self.conductor_compute_rpcapi.migrate_server(
            context, instance, scheduler_hint, True, False, None,
            block_migration, disk_over_commit, None)
将主机名存入字典scheduler_hint中,然后调用nova/conductor/rpcapi.py方法migrate_server
    def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
                  flavor, block_migration, disk_over_commit,
                  reservations=None):
        # 检测一下支持rpc版本号
        if self.client.can_send_version('1.6'):
            version = '1.6'
        else:
            instance = jsonutils.to_primitive(
                    objects_base.obj_to_primitive(instance))
            version = '1.4'
        flavor_p = jsonutils.to_primitive(flavor)
        cctxt = self.client.prepare(version=version)
        # 发送rpc消息到nova-conductor
        return cctxt.call(context, 'migrate_server',
                          instance=instance, scheduler_hint=scheduler_hint,
                          live=live, rebuild=rebuild, flavor=flavor_p,
                          block_migration=block_migration,
                          disk_over_commit=disk_over_commit,
                          reservations=reservations)

完成动作主要检测一下兼容的api版本号,发送消息给nova-conductor进行处理

看一下nova-conductor处理函数

    @messaging.expected_exceptions(exception.NoValidHost,
                                   exception.ComputeServiceUnavailable,
                                   exception.InvalidHypervisorType,
                                   exception.UnableToMigrateToSelf,
                                   exception.DestinationHypervisorTooOld,
                                   exception.InvalidLocalStorage,
                                   exception.InvalidSharedStorage,
                                   exception.MigrationPreCheckError)
    def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
            flavor, block_migration, disk_over_commit, reservations=None):
        if instance and not isinstance(instance, instance_obj.Instance):
            # NOTE(danms): Until v2 of the RPC API, we need to tolerate
            # old-world instance objects here
            attrs = [&#
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值