openstack学习笔记一 虚拟机启动过程代码跟踪

本文主要通过对虚拟机创建过程的代码跟踪。观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程。

当从horizon界面发送一个创建虚拟机请求,horizon api 将会依据前端给定的数据信息。调用novaclient 生成一个创建虚拟机的http post 请求来创建vm服务。

>/usr/lib/python2.6/site-packages/horizon/api/nova.py(334)server_create()

> /usr/lib/python2.6/site-packages/novaclient/base.py(149)_create()

->        _resp, body = self.api.client.post(url, body=body)

说明:

此时self.api:<novaclient.v1_1.client.Clientobject >

self.api.client:<novaclient.client.HTTPClientobject>

>/usr/lib/python2.6/site-packages/novaclient/client.py(216)_cs_request()

在_rs_request 假设management_url为空。则须要调用keystone的

authenticate()(该方法位于>/usr/lib/python2.6/site-packages/keystone/service.py(252)authenticate()中)方法进行keystone认证。此处创建虚拟机,因为用户已经登陆系统,则management_url不为空,已经经过keystone认证过,故无需再次进行keystone认证。

Eg:发送认证请求的请求參数:

url

u'http://172.30.51.164:8774/v1.1/1c56ca83be0944009499481e90e184dd'

headers

{'X-Auth-Project-Id':u'1c56ca83be0944009499481e90e184dd', 'X-Auth-Key':u'648cc1397bee44eb951399c43155a402', 'X-Auth-User': u'opadmin'}

>/usr/lib/python2.6/site-packages/novaclient/client.py(209)_time_request()

參数:

Self:<novaclient.client.HTTPClient object>

url:u'http://172.30.51.164:8774/v1.1/1c56ca83be0944009499481e90e184dd/servers'

method:”POST”

kwargs:

{'body':{'server': {'name': u'vm_test', 'imageRef':'e540ef5b-baf0-417e-b6c2-3a0364af25d5', 'availability_zone': u'nova','flavorRef': '6', 'max_count': 1, 'min_count': 1, 'security_groups': [{'name':u'default'}]}}, 'headers': {'X-Auth-Project-Id':
u'1c56ca83be0944009499481e90e184dd','X-Auth-Token': u'd9ce4438b914442397f3fdeeb673b30a'}}

>/usr/lib/python2.6/site-packages/novaclient/client.py(184)request()

184  ->        resp, body = super(HTTPClient, self).request(*args, **kwargs)

參数:

Args:

self =<novaclient.client.HTTPClient object at 0x7f14d5c1b950>

args =(u'http://172.30.51.164:8774/v1.1/1c56ca83be0944009499481e90e184dd/servers','POST')

kwargs ={'body': '{"server": {"name": "vm_test","imageRef": "e540ef5b-baf0-417e-b6c2-3a0364af25d5","availability_zone": "nova", "flavorRef":"6", "max_count": 1, "min_count": 1,"security_groups": [{"name": "default"}]}}','headers': {'X-Auth-Project-Id':
u'1c56ca83be0944009499481e90e184dd','User-Agent': 'python-novaclient', 'Content-Type': 'application/json','Accept': 'application/json', 'X-Auth-Token':u'd9ce4438b914442397f3fdeeb673b30a'}}

即调用httplib中

>/usr/lib/python2.6/site-packages/httplib2/__init__.py(1600)request()--httplib

1605                        (response, content) =self._request(conn, authority, uri, request_uri, method, body, headers,redirections, cachekey)

參数说明:

Conn:<httplib2.HTTPConnectionWithTimeout instance>

Authority:u'172.30.51.164:8774'

Uri:u'http://172.30.51.164:8774/v1.1/1c56ca83be0944009499481e90e184dd/servers'

request_uri:u'/v1.1/1c56ca83be0944009499481e90e184dd/servers'

method:'POST'

body:

'{"server":{"name": "vm_test", "imageRef":"e540ef5b-baf0-417e-b6c2-3a0364af25d5","availability_zone": "nova", "flavorRef":"6", "max_count": 1, "min_count": 1,"security_groups": [{"name": "default"}]}}'

Headers:

{'x-auth-project-id':u'1c56ca83be0944009499481e90e184dd', 'accept-encoding': 'gzip, deflate','accept': 'application/json', 'x-auth-token':u'd9ce4438b914442397f3fdeeb673b30a', 'user-agent': 'python-novaclient','content-type': 'application/json'}

Redirections:5

Cachekey:None

请求发出后,openstack中的wsgi 服务将会接收并处理该请求:

虚拟机启动过程中任务状态:

任务状态变化:

Status     Task                         Power state        Steps

Build        scheduling                   None               3-12

Build        networking                 None              22-24

Build        block_device_mapping     None                 25-27

Build        spawing                 None               28

Active      none                        Running

当请求从前端发送后,wsgicontroller 接受请求后进入nova-api 处理过程:

/usr/lib/python2.6/site-packages/nova/api/openstack/compute/servers.py(714)create()

(instances, resv_id) =self.compute_api.create(context,......

>/usr/lib/python2.6/site-packages/nova/compute/api.py(651)create()

>/usr/lib/python2.6/site-packages/nova/compute/api.py(233)_create_instance()

>/usr/lib/python2.6/site-packages/nova/image/glance.py(235)show() 通过image_href获取get-image信息

>/usr/lib/python2.6/site-packages/nova/compute/api.py(406)_create_instance()  写nova.instances数据库,此时vm_status=buildingtask_vm=scheduling

>/usr/lib/python2.6/site-packages/nova/compute/api.py(433)_create_instance()

>/usr/lib/python2.6/site-packages/nova/compute/api.py(600)_schedule_run_instance()

>/usr/lib/python2.6/site-packages/nova/compute/api.py(627)_schedule_run_instance()向消息中间件中发送消息。rpc.cast 方法

>/usr/lib/python2.6/site-packages/nova/api/openstack/compute/servers.py(762)create()返回全部创建的虚拟机

>/usr/lib/python2.6/site-packages/nova/api/openstack/compute/views/servers.py(64)create()依据消息中间件中返回的虚拟机对象信息构造返回前端显示的虚拟机实例对象

_schedule_run_instance方法中,调用rpc向消息中间件中发送消息。

创建时实例数据參数值:

FLAGS.scheduler_topic:scheduler

FLAGS.compute_topic:computer

Request_spec:

{'num_instances':1, 'block_device_mapping': [], 'image': {'status': 'active', 'name':'cirros-0.3.0-x86_64', 'deleted': False, 'container_format': 'ovf','created_at': '2014-10-28 18:56:51', 'disk_format': 'raw', 'updated_at':'2014-10-28 18:56:51',
'properties': {'description': 'cirros-0.3.0-x86_64'},'min_ram': '512', 'checksum': '50bdc35edb03a38d91b1b071afb20a3c', 'min_disk':'1', 'is_public': True, 'deleted_at': None, 'id':'e540ef5b-baf0-417e-b6c2-3a0364af25d5', 'size': 9761280}, 'instance_type':{'root_gb':
1L, 'name': u'testflav', 'deleted': False, 'created_at':datetime.datetime(2014, 10, 28, 21, 23, 5), 'ephemeral_gb': 0L, 'updated_at':None, 'memory_mb': 512L, 'vcpus': 1L, 'flavorid': u'6', 'swap': 0L,'rxtx_factor': 1.0, 'extra_specs': {u'connections': u'1024',
u'bandwidth':u'2'}, 'deleted_at': None, 'vcpu_weight': None, 'id': 6L},'instance_properties': {'vm_state': 'building', 'ephemeral_gb': 0L,'access_ip_v6': None, 'access_ip_v4': None, 'kernel_id': '', 'key_name': None,'ramdisk_id': '', 'instance_type_id': 6L,
'user_data': '', 'vm_mode': None,'display_name': u'test_vm', 'config_drive_id': '', 'reservation_id': 'r-tq6swy2p','key_data': None, 'root_gb': 1L, 'user_id':u'5cd9af0bd8c94f0287eae6919b3a8160', 'uuid':u'52e9f1ad-9983-42ce-ab8a-ed7685d2fcb7', 'root_device_name':
None,'availability_zone': u'nova', 'launch_time': '2014-10-29T00:06:20Z','metadata': {}, 'display_description': u'test_vm', 'memory_mb': 512L,'launch_index': 0, 'vcpus': 1L, 'locked': False, 'image_ref':u'e540ef5b-baf0-417e-b6c2-3a0364af25d5', 'architecture':
None, 'power_state':0, 'auto_disk_config': None, 'progress': 0, 'os_type': None, 'project_id':u'1c56ca83be0944009499481e90e184dd', 'config_drive': ''}, 'security_group':[u'default']}

admin_password:'H2pGHU9xHpF5'

injected_files:[]

requested_networks:None

filter_properties: {'scheduler_hints': {}}

当compute api 发送run_instance消息到消息队列后。compute server将接收消息队列中的消息。并运行指定的方法。

>/usr/lib/python2.6/site-packages/nova/compute/manager.py(460)_run_instance()

>/usr/lib/python2.6/site-packages/nova/compute/manager.py(576)_start_building() 将正在创建的vm的vm_state改动为building状态,此时。task_state还处于scheduling

> /usr/lib/python2.6/site-packages/nova/compute/manager.py(585)_allocate_network()为vm分配网络。vm的vm_state改动为building状态。此时。task_state
进入networking状态

>/usr/lib/python2.6/site-packages/nova/network/api.py(164)allocate_for_instance()通过网络api 进入network相关组件为vm创建网络。

创建网络步骤例如以下:

參数说明:

FLAGS.network_topic :'network'

Args :

self =<nova.network.api.API object at 0x1dd0d90>

context= <nova.rpc.amqp.RpcContext object at 0x32bb850>

instance= <nova.db.sqlalchemy.models.Instance object at 0x374da50>

kwargs ={'instance_uuid': u'37efb12b-aed5-485c-bafc-7ebe9e923c05', 'vpn': False,'requested_networks': None, 'instance_id': 14L, 'host': u'guoyl','rxtx_factor': 1.0, 'project_id': u'1c56ca83be0944009499481e90e184dd'}

消息队列返回结果举例:

nw_info :

[{u'meta':{}, u'network': {u'bridge': u'br100', u'label': u'bss1173', u'meta':{u'tenant_id': None, u'multi_host': True, u'should_create_bridge': True,u'bridge_interface': u'eth0'}, u'id': u'15577a4d-5a16-42a4-88da-17e5773253ca',u'subnets': [{u'ips':
[{u'meta': {}, u'type': u'fixed', u'version': 4,u'address': u'10.0.0.2', u'floating_ips': []}], u'version': 4, u'meta':{u'dhcp_server': u'10.0.0.3'}, u'dns': [{u'meta': {}, u'type': u'dns',u'version': 4, u'address': u'8.8.4.4'}], u'routes': [], u'cidr': u'10.0.0.0/24',u'gateway':
{u'meta': {}, u'type': u'gateway', u'version': 4, u'address':u'10.0.0.1'}}, {u'ips': [], u'version': None, u'meta': {u'dhcp_server':u'10.0.0.3'}, u'dns': [], u'routes': [], u'cidr': None, u'gateway': {u'meta':{}, u'type': u'gateway', u'version': None, u'address':
None}}]}, u'address':u'fa:16:3e:36:1b:52', u'id': u'6faf6db7-d044-41bf-a12e-363efef98474'}]

>/usr/lib/python2.6/site-packages/nova/network/api.py(180)allocate_for_instance()

调用network api 去创建网络,并返回获取新创建的网络信息:

输入:[{u'meta': {}, u'network':{u'bridge': u'br100', u'label': u'bss1173', u'meta': {u'tenant_id': None,u'multi_host': True, u'should_create_bridge': True, u'bridge_interface':u'eth0'}, u'id': u'15577a4d-5a16-42a4-88da-17e5773253ca', u'subnets':
[{u'ips':[{u'meta': {}, u'type': u'fixed', u'version': 4, u'address': u'10.0.0.2',u'floating_ips': []}], u'version': 4, u'meta': {u'dhcp_server': u'10.0.0.3'},u'dns': [{u'meta': {}, u'type': u'dns', u'version': 4, u'address':u'8.8.4.4'}], u'routes': [], u'cidr':
u'10.0.0.0/24', u'gateway': {u'meta': {},u'type': u'gateway', u'version': 4, u'address': u'10.0.0.1'}}, {u'ips': [],u'version': None, u'meta': {u'dhcp_server': u'10.0.0.3'}, u'dns': [],u'routes': [], u'cidr': None, u'gateway': {u'meta': {}, u'type': u'gateway',u'version':
None, u'address': None}}]}, u'address': u'fa:16:3e:36:1b:52',u'id': u'6faf6db7-d044-41bf-a12e-363efef98474'}]

输出:

VIF({'network':Network({'bridge': u'br100', 'subnets': [Subnet({'ips': [FixedIP({'meta': {},'version': 4, 'type': u'fixed', 'floating_ips': [], 'address': u'10.0.0.2'})],'version': 4, 'meta': {u'dhcp_server': u'10.0.0.3'}, 'dns': [IP({'meta':
{},'version': 4, 'type': u'dns', 'address': u'8.8.4.4'})], 'routes': [], 'cidr':u'10.0.0.0/24', 'gateway': IP({'meta': {}, 'version': 4, 'type': u'gateway','address': u'10.0.0.1'})}), Subnet({'ips': [], 'version': None, 'meta':{u'dhcp_server': u'10.0.0.3'},
'dns': [], 'routes': [], 'cidr': None,'gateway': IP({'meta': {}, 'version': None, 'type': u'gateway', 'address':None})})], 'meta': {u'tenant_id': None, u'multi_host': True,u'should_create_bridge': True, u'bridge_interface': u'eth0'}, 'id':u'15577a4d-5a16-42a4-88da-17e5773253ca',
'label': u'bss1173'}), 'meta': {},'id': u'6faf6db7-d044-41bf-a12e-363efef98474', 'address': u'fa:16:3e:36:1b:52'})

网络创建完毕后,进入准备block_device过程;此时。vm的vm_state改动为building状态。task_state
进入task_states.BLOCK_DEVICE_MAPPING(block_device_mapping)状态。

>/usr/lib/python2.6/site-packages/nova/compute/manager.py(610)_prep_block_device()

输入:<nova.db.sqlalchemy.models.Instance>

输出:{'block_device_mapping':[], 'root_device_name': None, 'ephemerals': [], 'swap': None}

获取完块存储信息后,虚拟机进入spawning过程:此时,vm的vm_state改动为building状态。task_state
进入task_states.SPAWNING(spawning)状态。

> /usr/lib/python2.6/site-packages/nova/compute/manager.py(622)_spawn()步骤例如以下:

Spawn过程中,self.driver 对象为<nova.virt.libvirt.connection.LibvirtConnection object>

输入:

Instance:<nova.db.sqlalchemy.models.Instanceobject>

image_meta:

{'status':'active', 'name': 'cirros-0.3.0-x86_64', 'deleted': False, 'container_format':'ovf', 'created_at': datetime.datetime(2014, 10, 28, 18, 56, 51),'disk_format': 'raw', 'updated_at': datetime.datetime(2014, 10, 28, 18, 56,51), 'id': 'e540ef5b-baf0-417e-b6c2-3a0364af25d5',
'min_ram': '512','checksum': '50bdc35edb03a38d91b1b071afb20a3c', 'min_disk': '1', 'is_public':True, 'deleted_at': None, 'properties': {'description': 'cirros-0.3.0-x86_64'},'size': 9761280}

self._legacy_nw_info(network_info):

[({'bridge':u'br100', 'multi_host': True, 'bridge_interface': u'eth0', 'cidr_v6': None,'vlan': None, 'injected': False, 'cidr': u'10.0.0.0/24', 'id':u'15577a4d-5a16-42a4-88da-17e5773253ca'}, {'rxtx_cap': 0,'should_create_bridge': True, 'dns':
[u'8.8.4.4'], 'ip6s': [], 'label':u'bss1173', 'broadcast': '10.0.0.255', 'ips': [{'ip': u'10.0.0.2', 'netmask':'255.255.255.0', 'enabled': '1', 'gateway': u'10.0.0.1'}], 'mac':u'fa:16:3e:36:1b:52', 'vif_uuid': u'6faf6db7-d044-41bf-a12e-363efef98474','should_create_vlan':
False, 'gateway_v6': None, 'dhcp_server': u'10.0.0.3','gateway': u'10.0.0.1'})]

block_device_info:

{'block_device_mapping':[], 'root_device_name': None, 'ephemerals': [], 'swap': None}

Inject_files:[]

admin_pass:MeWoHq7i2Z8'

输出:instance

当虚拟机spawn完毕后,vm的vm_state改动为active状态。task_state
置空。为None状态且vm的电源状态为Running状态。

此时。虚拟机创建过程完毕。

调用spawn方法实际上就是调用

>/usr/lib/python2.6/site-packages/nova/virt/libvirt/connection.py(964)spawn()

运行步骤例如以下:

将信息写入到libvirt xml模板

依据network-info创建对应的网络

创建虚拟机启动所须要的镜像文件

调用libvirt 接口define一个虚拟机domain

调用libvirt接口 create vmdomain

轮询vm状态,当vm 为running状态时返回

Openstack  keystone 认证过程:

Openstack中的keystone是通过请求-响应的方式来完毕的。

请求认证的方式有两种,一种将用户password等信息放在request headers中(_v1_auth)。如token认证;另外一种将认证信息放在请求body 中(_v2_auth)。

请求时都需带auth_url 參数。

第一种方式:

request(url,'GET', headers=headers)

headers = {'X-Auth-User':
self.user,

'X-Auth-Key':
self.password,

'X-Auth-Project-Id': self.projectid}

另外一种方式:

request(token_url,"POST", body=body);当中token_url = url + "/tokens"

body = {"auth": {

"passwordCredentials": {

"username":
self
.user,

"password":
self.password}

}

"tenantName": projectid

}

当keystone服务内容组件结构例如以下。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZ3l1bmxpbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

当service接受认证请求后,或调用authenticate()方法来处理请求,经过一系列的认证处理后,返回_format_authenticate(token_ref, roles_ref, catalog_ref),返回json数据格式例如以下:

{'access': {'token': {'id': token_ref['id'],

'expires': expires,

 'tenant'
: {‘enable’:true,……}

},

'user': {'id': user_ref['id'],

'name': user_ref['name'],

'username': user_ref['name'],

'roles': roles_ref,

'roles_links':metadata_ref.get('roles_links',[])

},

serviceCatalog
: catalog_ref

}

}

Catalog_ref:

        [{'name': $SERVICE[name],

          'type': $SERVICE,

          'endpoints': [{

              'tenantId': $tenant_id,

              ...

              'region': $REGION,

              }],

          'endpoints_links': [],

         }]

 

 

openstack学习笔记一 虚拟机启动过程代码跟踪的更多相关文章

  1. openstack虚拟机启动过程

    核心项目3个 1.控制台 服务名:Dashboard 项目名:Horizon 功能:web方式管理云平台,建云主机,分配网络,配安全组,加云盘 2.计算 服务名:计算 项目名:Nova 功能:负责响应 ...

  2. Android学习笔记——Activity的启动和创建

    http://www.cnblogs.com/bastard/archive/2012/04/07/2436262.html Android Activity学习笔记——Activity的启动和创建 ...

  3. 【学习笔记】OI玄学道—代码坑点

    [学习笔记]\(OI\) 玄学道-代码坑点 [目录] [逻辑运算符的短路运算] [\(cmath\)里的贝塞尔函数] 一:[逻辑运算符的短路运算] [运算规则] && 和 || 属于逻 ...

  4. JPG学习笔记3(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  5. Java虚拟机启动过程解析

    一.序言 当我们在编写Java应用的时候,很少会注意Java程序是如何被运行的,如何被操作系统管理和调度的.带着好奇心,探索一下Java虚拟机启动过程. 1.素材准备 从Java源代码.Java字节码 ...

  6. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

  7. JVM学习笔记:虚拟机的类加载机制

    JVM类加载机制分两部分来总结: (1)类加载过程 (2)类加载器 一.JVM类加载过程 类的加载过程:加载 →连接(验证 → 准备 → 解析)→ 初始化. 类的生命周期:加载 →连接(验证 → 准备 ...

  8. Zephyr学习(三)启动过程

    一.写在前面 最近对zephyr这个系统很感兴趣,因此业余有时间的时候都在研究它的源码,而光看代码不去动手这不是我的风格,于是乎在网上淘了一块STM32F103C8T6的核心板和一块NRF52832的 ...

  9. Android Activity学习笔记——Activity的启动和创建

    http://www.cnblogs.com/bastard/archive/2012/04/07/2436262.html 最近学习Android相关知识,感觉仅仅了解Activity几个生命周期函 ...

随机推荐

  1. MFC超链接静态类的使用

    源代码:http://download.csdn.net/detail/nuptboyzhb/4197151 CHyperLink类,是由CStatic类派生出来,重载了CStatic类的如下函数: ...

  2. 性能测试之LoardRunner 手动关联二

    概述: 1.如果寻找左右边界值 2.关联函数详解 以下是详细介绍 1.如果寻找左右边界值 <以login 为例> Step1.录制两份相同的业务流程的的脚本,输入的数据要相同 Step2. ...

  3. UVALive 2519 Radar Installation 雷达扫描 区间选点问题

    题意:在坐标轴中给出n个岛屿的坐标,以及雷达的扫描距离,要求在y=0线上放尽量少的雷达能够覆盖全部岛屿. 很明显的区间选点问题. 代码: /* * Author: illuz <iilluzen ...

  4. Js版游戏打砖块开发过程详细

    最近对js的小游戏开发来了兴趣,前段时间由于回答度娘知道的提问写了个贪吃蛇,虽然难度不大并不复杂,感觉还挺有意思.感觉小时候玩过的什么俄罗斯方块,坦克大战什么的都可以试着用js实现下,这天来了兴致又想 ...

  5. Opencv实现图像的灰度处理,二值化,阀值选择

    前几天接触了图像的处理,发现用OPencv处理确实比較方便.毕竟是非常多东西都封装好的.可是要研究里面的东西,还是比較麻烦的,首先,你得知道图片处理的一些知识,比方腐蚀,膨胀,仿射,透射等,还有非常多 ...

  6. c++中编译器的作用

    编译器的部分工作是寻找程序代码中的错误.编译器不能查出程序的意义是否正确. 但它能够查出程序形式上的错误.以下是编译器能查出的最普遍的一些错误: (1)语法错误.程序猿犯了c++语言中的语法错误. ( ...

  7. 《转》OpenStack Live Migration

    This post is based assumption that KVM as hypervisor, and Openstack is running in Grizzly on top of ...

  8. MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系

    MongoDB的集合(collection)可以看做关系型数据库的表,文档对象(document)可以看做关系型数据库的一条记录.但两者并不完全对等.表的结构是固定的,MongoDB集合并没有这个约束 ...

  9. c++ try throw catch

    c++ try throw catch 这三者联合使用 , try { statement list; } catch( typeA arg ) { statement list; } catch( ...

  10. 引导加载程序:GRUB

    计算机在启动的时候,首先由BIOS中的程序执行自检,自检通过后,就根据CMOS的配置找到第一个可启动磁盘的MBR中的Boot Loader程序(一般在启动盘的第一个物理扇区,占446字节),并把控制权 ...