资讯专栏INFORMATION COLUMN

openstack创建虚拟机源码阅读

muddyway / 3345人阅读

摘要:标签源码阅读在中虚拟机的创建无疑是非常重要的了解虚拟机创建流程并阅读模块关于创建虚拟机的源码对开发有很很大帮助本篇文章将以版本为基础讲解创建虚拟机的源码由于模块代码复杂而且阅读源码所需知识较多所以侧重于流程逻辑源码阅读可能不够详尽指出模块结

标签: openstack nova 源码阅读


在openstack中,虚拟机的创建无疑是非常重要的,了解虚拟机创建流程并阅读nova模块关于创建虚拟机的源码对opensatck开发有很很大帮助,本篇文章将以openstack queens版本为基础.讲解创建虚拟机的源码.由于nova模块代码复杂,而且阅读源码所需知识较多,所以侧重于流程逻辑,源码阅读可能不够详尽指出.

nova模块结构

DB: 用于存储nova服务相关数据的SQL数据库,通常为MySQL

API:接收HTTP请求的组件,处理请求并通过oslo.messaging队列或HTTP与其他组件通信

Scheduler: 决定虚拟机在哪个主机运行

Network: 管理IP转发,桥接和vlans

Compute: 管理虚拟机和虚拟机管理器直接的通信

Conductor: 处理需要协同的请求(创建/重建),作为数据库代理,或者处理对象转换

创建虚拟机流程

为了简便,这里省略了认证过程,实际上一个请求发送过来,还要经过认证和鉴权等过程,确保该用户有权限创建虚拟机.
在openstack的wiki中给出创建一个虚拟的workflow,图有点大,但对于每个组件的工作内容写的非常详细

我们可以把创建流程分成几个部分

处理请求

用户发送一个创建虚拟机的请求,Nova-Api接收到请求后,Nova-Api负责激活扩展插件,检查虚拟机名称,接收注入文件,提取新虚拟机的网络设置,检查配置和镜像等工作.
然后Nova-Api将处理好的参数集以JSON文件通过HTTP请求发送给Nova的Compute-Api.然后向用户发送带有虚拟机预留ID的相应(这时的相应码202,提示虚拟机创建成功,但实际上虚拟机还未真正创建成功)
Compute-Api在接收到请求后将会检查创建政策,进一步检查虚拟机,网络,镜像和配额,然后正式建立虚拟机的配置.
接着在数据库中生成虚拟机的相应记录,而后通过消息队列发送请求让scheduler选择一个host来创建虚拟机.

虚拟机调度和资源准备

scheduler接收到消息后根据消息中filters对所有host进行过滤,最后选出某个host,然后跟新数据库,并通过消息队列向被选定的host发送创建虚拟机消息
被选定的host接收到队列的消息后在数据库中更新虚拟机和任务的状态,然后通过nova network-api为虚拟机创建或获取网络.
接着通过nova volume-api为虚拟机创建新的卷,决定虚拟机的块设备映射,并将卷挂载到虚拟机上
此时虚拟机的调度和资源准备都以完成.

在hypervisor上运行虚拟机

被选定的host获取镜像,建立块设备映射,最后生成libvirt.xml最后执行hypervisor的spawn()方法,至此,虚拟机已经在host上运行了.最后一步是跟新虚拟机和任务的状态.

源码阅读

下面将根据虚拟机创建时调用的模块顺序阅读代码

Nova-Api

Nova-Api将处理不同类型的请求写成了各种controler类,而处理创建虚拟机的类被称为ServerControler

# nova/api/openstack/compute/servers.py
class ServersController(wsgi.Controller):
    
    # 为了简明,省略了很多用于检查的装饰器
    @wsgi.response(202)
    def create(self, req, body):
         """Creates a new server for a given user."""
        context = req.environ["nova.context"]
        server_dict = body["server"]
        password = self._get_server_admin_password(server_dict)
        name = common.normalize_name(server_dict["name"])
        description = name
        # create方法干的是些从请求中提取并检查参数的脏活
        # 省略...
        try:
            # 依然是构建参数的代码...
            
            # 调用compute_api创建虚拟机
            (instances, resv_id) = self.compute_api.create(context,
                            inst_type,
                            image_uuid,
                            display_name=name,
                            display_description=description,
                            availability_zone=availability_zone,
                            forced_host=host, forced_node=node,
                            metadata=server_dict.get("metadata", {}),
                            admin_password=password,
                            requested_networks=requested_networks,
                            check_server_group_quota=True,
                            supports_multiattach=supports_multiattach,
                            **create_kwargs)
        # 错误处理...
compute-api
# nova/compute/api.py
class API(base.Base):
    def create(self, context, instance_type,
               image_href, kernel_id=None, ramdisk_id=None,
               min_count=None, max_count=None,
               display_name=None, display_description=None,
               key_name=None, key_data=None, security_groups=None,
               availability_zone=None, forced_host=None, forced_node=None,
               user_data=None, metadata=None, injected_files=None,
               admin_password=None, block_device_mapping=None,
               access_ip_v4=None, access_ip_v6=None, requested_networks=None,
               config_drive=None, auto_disk_config=None, scheduler_hints=None,
               legacy_bdm=True, shutdown_terminate=False,
               check_server_group_quota=False, tags=None,
               supports_multiattach=False):
        """准备实例创建工作,然后将实例信息发送至scheduler,
        由scheduler计算host上创建和在DB创建记录。
        """
        # preparation
        
        # 为了简介,所有参数简略为args和kwargs
        self_create_instance(*args, **kwargs)
        
    def _create_instance(self, context, instance_type,
               image_href, kernel_id, ramdisk_id,
               min_count, max_count,
               display_name, display_description,
               key_name, key_data, security_groups,
               availability_zone, user_data, metadata, injected_files,
               admin_password, access_ip_v4, access_ip_v6,
               requested_networks, config_drive,
               block_device_mapping, auto_disk_config, filter_properties,
               reservation_id=None, legacy_bdm=True, shutdown_terminate=False,
               check_server_group_quota=False, tags=None,
               supports_multiattach=False):
        """核查所有参数"""
        # verifying
        pass
        
        # 获取镜像信息
        if image_href:
            # if image_href is provied, get image via glance api
            image_id, boot_meta = self._get_image(context, image_href)
        else:
            # if image_href is not proved, get image metadata from bdm
            image_id = None
            boot_meta = self._get_bdm_image_metadata(
                context, block_device_mapping, legacy_bdm)
        
        # 继续检查参数
        
        # 由于block device mapping有两种版本,为了兼容,需要检查并在必要时转换
         block_device_mapping = self._check_and_transform_bdm(context,
            base_options, instance_type, boot_meta, min_count, max_count,
            block_device_mapping, legacy_bdm)
        
        # go on checking
        
        # 为了支持cell特性,参见cell wiki
        # https://docs.openstack.org/nova/ocata/cells.html
        if CONF.cells.enable:
            # 创建instance模型对象
            # 检查quota
            
            # 调用rpc api将消息发送到队列
            self.compute_task_api.build_instance(*args, **kwargs)
        
        else:
            compute_task_api.schedule_and_build_instances(*args, **kwargs)
        
        
        return instances, reservation_id
调度和消息传递代码

nova组件之间可以通过rpc api以消息队列通信,而最后的真正执行的任务的类都在manager.py文件中定义.这里我们方便理解省略调度代码

# nova/conductor/api.py
class ComputeTaskAPI(object):
    def schedule_and_build_instance(self, *args, **kwargs):
        # very simple method
        # call rpc api only
        self.conductor_compute_rpc_api.schedule_and_build_instance(*args, **kwargs)

# nova/conductor/rpcapi.py
class ComputeTaskAPI(object):
    def schedule_and_build_instance(self, *args, **kwargs):
        # 构建参数和api版本检查
        # 最后将其发送到消息队列
        cctxt.cast(context, "schedule_and_build_instance", **kwargs)
manager代码
# nova/compute/manager.py
class ComputeManager(object):
    @wrap_exception()
    @reverts_task_state
    @wrap_instance_fault
    def build_and_run_instance(self, *args, **kwargs):
        # 给资源加锁,避免竞争
        @utils.synchronized(instance.uuid)
        def _locked_do_build_and_run_instance(*args, **kwargs):
            with self._build_semaphore:
                try:
                    result = self._do_build_and_run_instance(*args, **kwargs)
                # handle exceptions
                pass
        # 由于创建虚拟机的工作可能会持续很长时间,为了避免进程阻塞
        # 将这个任务分发给某个worker
        utils.spawn_n(_locked_do_build_and_run_instance,
        context, instance, ...)

    def _do_build_and_run_instance(self, *args, **kwargs):
        # 更新虚拟机和任务状态
        # 解码注入文件
        try:
            with timeutils.StopWatch() as timer:
                self._build_and_run_instance(*args)
        # handle exceptions
    def _build_and_run_instance(self, *args, **kwargs):
        # 获取 image ref
        try:
            scheduler_hints = self._get_scheduler_hints(filter_properties, request_spec)
            rt = self._get_resource_tracker()
            with rt.instance_claime(context, instance, node, limits):
                # 获取群组策略和镜像metadata

                # 通过调用_build_resources创建network和volume
                with self._build_resources(*args) as resources:
                    # handle vm and task state
                    # spawn instance on hypervisor
                    with timeuitls.StopWatch() as time:
                        # 通过driver创建xml,然后真正运行虚拟机
                        self.driver.spawn(*args, **kwargs)
        # handle exceptions

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41893.html

相关文章

  • OpenStack虚拟云桌面在携程呼叫中心的应用

    摘要:一为什么要使用虚拟云桌面背景携程呼叫中心,即服务联络中心,是携程的核心部门之一,现有几万员工。他们全年小时为全球携程用户提供服务。为此,携程正式引入了虚拟云桌面。携程云桌面现状携程云桌面现已部署上海南通如皋合肥信阳穆棱六个呼叫中心。 编者:本文为刘科在第六期【携程技术微分享】中的分享内容。在携程技术中心(微信号ctriptech)微信后台回复【云桌面】,可加入微信交流群,和关注云桌面的...

    EsgynChina 评论0 收藏0
  • OpenStack虚拟云桌面在携程呼叫中心的应用

    摘要:一为什么要使用虚拟云桌面背景携程呼叫中心,即服务联络中心,是携程的核心部门之一,现有几万员工。他们全年小时为全球携程用户提供服务。为此,携程正式引入了虚拟云桌面。携程云桌面现状携程云桌面现已部署上海南通如皋合肥信阳穆棱六个呼叫中心。 编者:本文为刘科在第六期【携程技术微分享】中的分享内容。在携程技术中心(微信号ctriptech)微信后台回复【云桌面】,可加入微信交流群,和关注云桌面的...

    biaoxiaoduan 评论0 收藏0
  • Kubernetes和OpenStack的多云端网络

    摘要:上周,在举行的上,发布,整合和。多亏存储应用程序会话到数据库通常来说是下载安装或者是,我们不需要特定的负载均衡器,运行完全没有问题。用负载均衡器描述的展示了浮动和私有集群。特别感谢来自的的支持和在测试过程中作出的贡献。 上周,在Austin举行的OpenStack Summit上,CoreOS发布Stackanetes,整合Kubernetes和OpenStack。 一个月前,Core...

    Hwg 评论0 收藏0
  • 深度解析 OpenStack metadata 服务架构

    摘要:下图展示了虚拟机可以获取到的信息神奇的这个地址来源于,亚马逊在设计公有云的时候为了让能够访问,就将这个特殊的作为服务器的地址。服务启动了服务,负责处理虚拟机发送来的请求。服务也运行在网络节点。中的路由和服务器都在各自独立的命名空间中。前言下图是OpenStack虚拟机在启动过程中发出的一个请求,我们在里面可以看到cloud-init和169.254.169.254。那么它们分别是做什么用的呢...

    Michael_Lin 评论0 收藏0
  • 云计算战争:OpenStack vs VMware—定位分析、功能对比、发展趋势

    摘要:和的云计算功能特点对比正式这个战争或者说趋势的一个生动写照。总而言之,目前调度器将只会对部署虚拟机环节有影响。目前有一个孵化项目其作用是为提供虚拟机级别高可用支持。容错在中没有针对于容错的功能,并且截至目前也没有计划去完成这些功能。 OpenStack中国社区编者按:在云计算生态系统中,有两种类型的用户需要使用云计算资源:传统型(Traditional IT applications)和在互...

    shiyang6017 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<