openstack 版本:Newton

注:博文图片采用了很多大牛博客图片,仅作为总结学习,非商用。
该图全面的说明了nova创建虚机的过程,从逻辑的角度清晰的描述了前端请求创建虚拟机之后发生的一系列反应。

上图是以逻辑的关系说明虚机创建的流程,并没有涉及到真正的代码,下面这张图则是从代码的角度来看虚机的创建过程。两张逻辑图相辅相成,能够快速对nova创建虚机流程有一个认识。

上一篇博文已经将nova创建虚机的流程分析到restful调用具体的函数。如下图所示,本篇将从该函数开始分析,展开nova服务的代码文件。

上图的create函数是nova api的入口函数,所有nova api的调用都是从该函数开始的。

从该函数开始到nova调用底层驱动创建虚拟机,要经过的调用流程如下:

 nova.api.openstack.compute.servers.py::Controller:create
->nova.compute.api.py::API:create
->nova.compute.api.py::API:_create_instance
->nova.comductor.ComputeTaskAPI.py::build_instances
->nova.conductor.rpcapi.py::ComputeTaskAPI:build_instances
->nova.conductor.manager.py::ComputeTaskAPI.py:build_instances
->nova.compute.rpcapi.ComputeManager.py::build_and_run_instance
->nova.compute.manager.py::ComputeManager:_do_build_and_run_instance
->nova.compute.manager.py::ComputeManager:_build_and_run_instance
->driver

nova.api.openstack.compute.servers.py:: Controller:create  指该create函数的所在路径是nova文件夹下的/nova/api/openstack/compute/servers.py中的create方法

同理:nova.compute.api.py::API:create 指该create方法在/nova/compute/api.py中的create方法。

所以这个调用的顺序就是如下图所示:

那么接下来就详细分析create()函数方法。

想要搞明白create函数做了什么,就要弄清楚函数传入的参数是什么。create传入了三个参数,分别是self,req,body。

其中self是类方法的标识,如果java类中函数的 "this" 字段。那么req、body分别是什么呢?使用python中print打印到文件的方法,输出了req与body的内容。

req

POST /v2.1/servers HTTP/1.0
Accept: application/json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 323
Content-Type: application/json
Host: 192.168.252.134:8774
User-Agent: python-novaclient
X-Auth-Project-Id: 836c0b02b549489eac82733267830e60
X-Auth-Token: 31475f46361e41d49c3aa519531192c2
X-Domain-Id: None
X-Domain-Name: None
X-Identity-Status: Confirmed
X-Is-Admin-Project: False
X-Project-Domain-Id: default
X-Project-Domain-Name: Default
X-Project-Id: 836c0b02b549489eac82733267830e60
X-Project-Name: demo
X-Role: Member,anotherrole
X-Roles: Member,anotherrole
X-Service-Catalog: [{"endpoints": [{"adminURL": "http://192.168.252.134:8774/v2.1", "region": "RegionOne", "internalURL": "http://192.168.252.134:8774/v2.1", "publicURL": "http://192.168.252.134:8774/v2.1"}], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60"}], "type": "compute_legacy", "name": "nova_legacy"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60"}], "type": "volumev2", "name": "cinderv2"}, {"endpoints": [{"adminURL": "http://192.168.252.134:9696/", "region": "RegionOne", "internalURL": "http://192.168.252.134:9696/", "publicURL": "http://192.168.252.134:9696/"}], "type": "network", "name": "neutron"}, {"endpoints": [{"adminURL": "http://192.168.252.134/identity_v2_admin", "region": "RegionOne", "internalURL": "http://192.168.252.134/identity", "publicURL": "http://192.168.252.134/identity"}], "type": "identity", "name": "keystone"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60"}], "type": "volume", "name": "cinder"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8080", "region": "RegionOne", "internalURL": "http://192.168.252.134:8080/v1/AUTH_836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8080/v1/AUTH_836c0b02b549489eac82733267830e60"}], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60"}], "type": "volumev3", "name": "cinderv3"}, {"endpoints": [{"adminURL": "http://192.168.252.134:9292", "region": "RegionOne", "internalURL": "http://192.168.252.134:9292", "publicURL": "http://192.168.252.134:9292"}], "type": "image", "name": "glance"}]
X-Tenant: demo
X-Tenant-Id: 836c0b02b549489eac82733267830e60
X-Tenant-Name: demo
X-User: demo
X-User-Domain-Id: default
X-User-Domain-Name: Default
X-User-Id: ac86920aec8c443f9fad33283599a17c
X-User-Name: demo {"server": {"name": "demo", "imageRef": "ec8f8b10-beb4-4802-9158-7b3ca8357d16", "availability_zone": "nova", "flavorRef": "1", "OS-DCF:diskConfig": "AUTO", "max_count": 1, "min_count": 1, "networks": [{"uuid": "cf8411d0-85b4-4534-9b7c-aed9dbecaafe"}], "security_groups": [{"name": "2a2f7994-a555-45be-9909-3bb06b1f4811"}]}}

req是http报文的全部内容,包括报文头,报文内容。其中很熟悉的字段:X-Auth-Token是已经获得的token,还有获得Token时返回的服务列表Catalog。会不会有人好奇为什么发送的不是账号和密码?而是Token?在登陆上openstack dashboard时账号和密码都被验证,后面的操作全都是基于Token来操作的。

报文内容中包含一个server字典,这是我们填写的创建虚机的数据。可以看到下面的代码中有在创建虚机时必填的参数,name,镜像,flavor,network等。

{"server":
{
"name": "demo",
"imageRef": "ec8f8b10-beb4-4802-9158-7b3ca8357d16",
"availability_zone": "nova",
"flavorRef": "1",
"OS-DCF:diskConfig": "AUTO",
"max_count": 1,
"min_count": 1,
"networks": [{"uuid": "cf8411d0-85b4-4534-9b7c-aed9dbecaafe"}],
"security_groups": [{"name": "2a2f7994-a555-45be-9909-3bb06b1f4811"}]
}
}

再来看body中的内容是什么

{
    u'server':
     {
         u'name': u'demo',
         u'imageRef': u'ec8f8b10-beb4-4802-9158-7b3ca8357d16',
         u'availability_zone': u'nova',
         u'flavorRef': u'1',
         u'OS-DCF:diskConfig': u'AUTO',
         u'max_count': 1,
         u'min_count': 1,
         u'networks': [{u'uuid': u'cf8411d0-85b4-4534-9b7c-aed9dbecaafe'}],
         u'security_groups': [{u'name': u'2a2f7994-a555-45be-9909-3bb06b1f4811'}]
     }
}

可以看到body中的内容是req内容的一部分,是post方法的内容。

搞清楚了传入的数据,下面就是函数处理过程。

这里是该函数最重要的调用。调用了compute/api.py中的create方法去创建虚机。

总结来说,该函数主要做的工作:

/nova/api/openstack/compute/server.py::create()  
1 获取客户端传入的虚拟机参数
2 获取虚拟机名并检查是否合理
3 检查API版本
4 构造用户id,项目id,可用域字典
5 获取可用域
6 块设备映射
7 获取虚机的磁盘镜像uuid
8 获取客户端需求的网络
9 获取续集规格ID
10 调用compute_api.create()
11 将虚拟机信息转化为字典
12 添加访问当前虚拟机资源的url

主要任务是从传递过的req中获取各种创建虚拟机所需要的参数信息,做简单必要验证,然后将获取的一系列参数(image_uuid,name,insts_type等)

作为nova/compute/api.py中的API类的create()方法参数,最后将返回的信息处理。那么下一节的内容就是要探究调用函数/nova/compute/api.py中的create()函数

完成了什么样的工作。

nova创建虚拟机源码分析系列之六 api入口create方法的更多相关文章

  1. nova创建虚拟机源码分析系列之五 nova源码分发实现

    前面讲了很多nova restful的功能,无非是为本篇博文分析做铺垫.本节说明nova创建虚拟机的请求发送到openstack之后,nova是如何处理该条URL的请求,分析到处理的类. nova对于 ...

  2. nova创建虚拟机源码分析系列之三 PasteDeploy

    上一篇博文介绍WSGI在nova创建虚拟机过程的作用是解析URL,是以一个最简单的例子去给读者有一个印象.在openstack中URL复杂程度也大大超过上一个例子.所以openstack使用了Past ...

  3. nova创建虚拟机源码分析系列之一 restful api

    开始学习openstack源码,源码文件多,分支不少.按照学习的方法走通一条线是最好的,而网上推荐的最多的就是nova创建虚机的过程.从这一条线入手,能够贯穿openstack核心服务.写博文仅做学习 ...

  4. nova创建虚拟机源码分析系列之七 传入参数转换成内部id

    上一篇博文将nova创建虚机的流程推进到了/compute/api.py中的create()函数,接下来就继续分析. 在分析之前简单介绍nova组件源码的架构.以conductor组件为例: 每个组件 ...

  5. nova创建虚拟机源码分析系列之八 compute创建虚机

    /conductor/api.py _build_instance()  /conductor/rpcapi.py  _build_instance() 1 构造一些数据类型2 修改一些api版本信息 ...

  6. nova创建虚拟机源码分析系列之四 nova代码模拟

    在前面的三篇博文中,介绍了restful和SWGI的实现.结合restful和WSGI配置就能够简单的实现nova服务模型的最简单的操作. 如下的内容是借鉴网上博文,因为写的很巧妙,将nova管理虚拟 ...

  7. nova创建虚拟机源码系列分析之二 wsgi模型

    openstack nova启动时首先通过命令行或者dashborad填写创建信息,然后通过restful api的方式调用openstack服务去创建虚拟机.数据信息从客户端到达openstack服 ...

  8. Spark 源码分析系列

    如下,是 spark 源码分析系列的一些文章汇总,持续更新中...... Spark RPC spark 源码分析之五--Spark RPC剖析之创建NettyRpcEnv spark 源码分析之六- ...

  9. MyCat源码分析系列之——SQL下发

    更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...

随机推荐

  1. JDFS:一款分布式文件管理系统,第四篇(流式云存储续篇)

    一 前言 本篇博客是JDFS系列博客的第四篇,从最初简单的上传.下载,到后来加入分布式功能,背后经历了大量的调试,尤其当实验的虚拟计算结点数目增加后,一些潜在的隐藏很深的bug就陆续爆发.在此之前笔者 ...

  2. 动易CMS-搜索结果页显示自定义字段

    最终的页面: 步骤: 1.搜索标签代码 <input id="keyword" type="text" class="text" on ...

  3. 【Kafka】操作命令

    生产者 ./kafka-console-producer.sh --broker-list --topic norm 消费者 ./kafka-console-consumer.sh --zookeep ...

  4. 【转】TCP/IP协议中TCP和UDP的区别

    TCP协议与UDP协议的区别    首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...

  5. 洗礼灵魂,修炼python(7)--元组,集合,不可变集合

    前面已经把列表的基本用法讲解完 接着讲python的几大核心之--元组(tuple) 1.什么是元组? 类似列表,但为不可变对象,之前提到列表是可变对象,所谓可变对象就是支持原处修改,并且在修改前后对 ...

  6. 运行Chromium浏览器缺少google api密钥无法登录谷歌账号的解决办法

    管理员身份运行CMD,然后依次输入以下三行内容: setx GOOGLE_API_KEY "AIzaSyAUoSnO_8k-3D4-fOp-CFopA_NQAkoVCLw"setx ...

  7. MySQL优化原理

    前言 说起MySQL的查询优化,相信大家收藏了一堆:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的工作原理 ...

  8. Sql Server——查询(二)

    上次写了查询里的一些简单的查询方法,如果说上次的是初级查询,那这次的就是高级查询了. 今天主要是聚合函数.分组查询.连接查询.联合查询.在我看来前三个挺简单的,稍微难理解点的也就最后一个,为什么呢?因 ...

  9. 我的第一篇blog—— 一起来赛马呀

      作为一名大三的学生现在开始学习acm,或许太晚.感叹时光蹉跎....我的blog将以讲解的形式的发布,以专题的形式的形式介绍一些基本的知识和经典的题目.虽然感觉自己所剩时间无多,但也希望起到前人种 ...

  10. 聊聊Java语言中的单例

    package com.xinke.mybatis.test; public class TestSingleton { private static TestSingleton ts = null; ...