虚拟机迁移使资源配置更加灵活,尤其是在线迁移,提供了虚拟机的可用性和可靠性。Openstack liberty中提供了两种类型的迁移实现:静态迁移(cold migration)和动态迁移(live migration)。在接下来的几篇文章中,我将详细分析两种迁移的实现过程,先来看静态迁移。
限于篇幅,静态迁移的源码分析将包含两篇文章:
- 第一篇:主要介绍迁移过程中
nova-api
及nova-conductor
所在的工作 - 第二篇:重点介绍
nova-compute
的处理过程
下面请看第一篇的内容:
发起迁移
用户可以手动通过nova CLI
命令行发起云主机迁移动作:
#nova --debug migrate 52e4d485-6ccf-47f3-a754-b62649e7b256
上述命令将id=52e4d485-6ccf-47f3-a754-b62649e7b256
的云主机迁移到另外一个最优的nova-compute
节点上,--debug
选项用来显示执行日志:
......
curl -g -i -X POST http://controller:8774/v2/eab72784b36040a186a6b88dac9ac0b2/servers/5a7d302f-f388-4ffb-af37-f1e6964b3a51/action -H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}8e294a111a5deaa45f6cb0f3c58a600d2b1b0493" -d '{"migrate": null}
......
上述截取的日志表明:novaclient
通过http方式将迁移请求发送给nova-api
并执行migrate
动作(action),由nova-api
启动时建立的路由映射,很容易的知道,该动作的入口函数为
nova/api/openstack/compute/migrate_server.py/MigrateServerController._migrate
,下文具体分析。
源码分析
nova-api
部分
如上分析,迁移入口如下:
#nova/api/openstack/compute/migrate_server.py/MigrateServerController._migrate, 省略装饰器定义
def _migrate(self, req, id, body):
"""Permit admins to migrate a server to a new host.
req 是Request对象,包含该次请求信息
id 是待迁移的云主机id 如:52e4d485-6ccf-47f3-a754-b62649e7b256
body 是该次请求的参数信息 {"migrate": null}
"""
#从Request对象提取请求上下文
context = req.environ['nova.context']
"""执行权限认证,默认会通过读取host节点/etc/nova/policy.json文件
中的权限规则完成认证,如果没有定义相关的规则,则表明认证失败抛抛异
这里对应的认证规则是:
"os_compute_api:os_migrate_server:migrate": rule:admin_api"
"""
authorize(context, action='migrate')
#从nova数据库中获取id指向的云主机信息,返回一个InstanceV2对象
instance = common.get_instance(self.compute_api, context, id)
"""省略异常处理代码
如果云主机不存在,找不到合适的目标主机,云主机处于锁定状态,
资源不足,云主机状态不对(只能是运行或者停止态)则抛异常
与‘调整云主机大小’(resize)操作一样,也是调用
`/nova/compute/api.py/API.resize`
执行迁移操作,resize是通过判断
是否指定了flavor_id参数来判断是执行‘调整云主机大小’还是‘迁移’操作,
请看下文的具体分析
"""
self.compute_api.resize(req.environ['nova.context'], instance)
---------------------------------------------------------------
#接上文:/nova/compute/api.py/API.resize, 省略装饰器定义
def resize(self, context, instance, flavor_id=None,
clean_shutdown=True,
**extra_instance_updates):
"""Resize (ie, migrate) a running instance.
If flavor_id is None, the process is considered a
migration, keeping the original flavor_id. If flavor_id is
not None, the instance should be migrated to a new host and
resized to the new flavor_id.
上面的注释是说:如果flavor_id = None, 则用原有的flavor(配置)执行
迁移操作。如果不为None,则应将云主机迁移到新的主机并应用flavor_id指
定的配置
conext 请求上下文
instance InstanceV2实例对象,包含云主机的详细配置信息
flavor_id 配置模板id,这里为None,因为是迁移操作
clean_shutdown = True, 静态迁移时开启关机重试,如果未能正常关闭云
主机会抛异常
"""
#检查系统磁盘的‘自动配置磁盘’功能是否打开,否则抛异常
#迁移完成后,云主机需要能够自动配置系统磁盘
self._check_auto_disk_config(instance, **extra_instance_updates)
#获取云主机配置模板信息
current_instance_type = instance.get_flavor()
# If flavor_id is not provided, only migrate the instance.
#flavor_id = None, 执行迁移操作;打印日志并将当前配置作为迁移后云主
#机的配置
if not flavor_id:
LOG.debug("flavor_id is None. Assuming migration.",
instance=instance)
new_instance_type = current_instance_type
else:
#从nova.ins