OpenStack之Nova分析——创建虚拟机(一)
2015-01-20 16:04
417 查看
上篇文章主要介绍了Nova API的启动流程,这篇文章我们来分析一下一个虚拟机的创建产生过程是怎样的。
由前一篇文章的分析,我们知道,处理HTTP请求的核心工作实际上都在底层的Controller对象中定义完成。Resource对象只是在Controller的基础上完成的封装,用来实现数据的序列化和反序列化。Controller类中,处理虚拟机创建请求的方法是create,该方法最终调用了Compute API类的create方法。来看代码,先来看Controller类,这个类位于nova/nova/api/openstack/compute/servers.py中。
这个类继承自wsgi.Controller,该类位于nova/nova/api/openstack/wsgi.py。首先为create方法指定了序列化对象、反序列化对象和默认的HTTP Code。接着我们进入create方法,来分析代码。
先来看看context = req.eviron['nova.context']究竟拿到了什么信息,这个上下文信息对象是由类nova.context.RequestContext实例化而来。我们来把获取到的context打印出来,这样方便大家理解。
后面我们来逐个分析其中的方法。
(1) is_valid_body方法
该方法检查客户端传入的消息体是否合法,这个方法位于Controller类的基类wsgi.Controller中。is_valid_body方法首先检查消息体中是否含有server字段,然后检查server字段的内容是否为字典。
接下来的一系列方法都是获取并验证客户端传入的虚拟机参数。其中,server_dict保存了虚拟机参数,包括虚拟机名、镜像uuid、需要的网络、固定ip、虚拟机规格等等。
(2) _validate_server_name方法
该方法检查虚拟机名的长度是否越界。
(3) _validate_access_ipv4&_validate_access_ipv6方法
该方法验证传入的固定ip格式是否合法。
(4) _favor_id_from_req_data方法
该方法对HTTP请求中包含的虚拟机规格id进行过滤解析。所谓规格id就是url包含的id或者uuid的值,如http://www.foo.com/bar/123?q=4,该方法则返回123。
(5) get_instance_type_get_by_flavor_id方法
该方法位于nova/nova/compute/instance_types.py中,该方法调用了nova/nova/db/api.py下的instance_type_get_by_flavor_id方法,其功能是根据虚拟机规格id,从数据库中查找对应信息后返回。在openstack中,与数据库的交互用的是sqlalchemy这个东东,我目前也不是很熟悉,先放一放吧,后面我再专门分析。
再接下来调用了Nova Compute的API处理虚拟机的创建请求。Compute API的create方法会返回一个创建虚拟机的列表。重点分析一下这个方法。
(6) compute_api.create方法
其中_check_create_policies方法的作用是检查客户端是否有创建虚拟机的权限,该方法会通过查询policy.json文件来查看用户权限,其内部逻辑和Keystone服务的权限管理类似。由于这里只是谈虚拟机的创建过程,所以关于Keystone就不在展开详谈。
接下来就是我们的重头戏了——_create_instance方法。这个方法就是执行进一步的虚拟机的创建过程,后面的文章我会花大篇幅来详细分析。
注:这里我们为了便于理解,再次打印出传入这个方法的参数实例
由前一篇文章的分析,我们知道,处理HTTP请求的核心工作实际上都在底层的Controller对象中定义完成。Resource对象只是在Controller的基础上完成的封装,用来实现数据的序列化和反序列化。Controller类中,处理虚拟机创建请求的方法是create,该方法最终调用了Compute API类的create方法。来看代码,先来看Controller类,这个类位于nova/nova/api/openstack/compute/servers.py中。
class Controller(wsgi.Controller): _view_builder_class = views_servers.ViewBuilder ... @wsgi.response(202) @wsgi.serializers(xml=FullServerTemplate) @wsgi.deserializers(xml=CreateDeserializer) def create(self,req,body): #检查HTTP消息是否合法 if not self.is_valid_body(body, 'server'): raise exc.HTTPUnprocessableEntity() #获取客户端传入的虚拟机参数 context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) #获取和检查虚拟机名 if not 'name' in server_dict: msg = _("Server name is not defined") raise exc.HTTPBadRequest(explanation=msg) name = server_dict['name'] self._validate_server_name(name) name = name.strip() #获取虚拟机磁盘镜像uuid image_uuid = self._image_from_req_data(body) ... #获取客户端需求的网络 requested_networks = None if (self.ext_mgr.is_loaded('os-networks') or self._is_quantum_v2()): requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) #获取和验证客户端指定的虚拟机IP (access_ip_v4, ) = server_dict.get('accessIPv4'), if access_ip_v4 is not None: self._validate_access_ipv4(access_ip_v4) (access_ip_v6, ) = server_dict.get('accessIPv6'), if access_ip_v6 is not None: self._validate_access_ipv6(access_ip_v6) #获取虚拟机规格id try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: ... #获取虚拟机规格信息 try: _get_inst_type = instance_types.get_instance_type_by_flavor_id inst_type = _get_inst_type(flavor_id, read_deleted="no") #调用compute API创建虚拟机 (instances, resv_id) = self.compute_api.create(context, ...) except exception.QuotaError as error: ... #将虚拟机信息转化为字典 server = self._view_builder.create(req,instances[0]) #将虚拟机信息封装成ResponseObject对象 robj = wsgi.ResponseObject(server) #添加访问当前虚拟机资源的url return self._add_location(robj)
这个类继承自wsgi.Controller,该类位于nova/nova/api/openstack/wsgi.py。首先为create方法指定了序列化对象、反序列化对象和默认的HTTP Code。接着我们进入create方法,来分析代码。
先来看看context = req.eviron['nova.context']究竟拿到了什么信息,这个上下文信息对象是由类nova.context.RequestContext实例化而来。我们来把获取到的context打印出来,这样方便大家理解。
user_id = afc380206e2549ad930396d9050d20cf project_id = 0e492e86f22e4d19bd523f1e7ca64566 roles = [u'admin', u'KeystoneAdmin', u'KeystoneServiceAdmin'] read_deleted = no remote_address = 172.21.6.145 timestamp = 2013-06-23 16:36:37.399405 request_id = req-f0255b14-833d-4fff-b973-23c35f70ddda auth_token = 7e7bb3cf84ab43269010bb55410064b3 service_catalog = [{u'endpoints': [{u'adminURL': u'http://172.21.5.161:8776/v1/0e492e86f22e4d19bd523f1e7ca64566', u'region': u'RegionOne', u'id': u'753a1ad55e91469794e2eb7ac4c3df92', u'internalURL': u'http://172.21.5.161:8776/v1/0e492e86f22e4d19bd523f1e7ca64566', u'publicURL': u'http://172.21.6.145:8776/v1/0e492e86f22e4d19bd523f1e7ca64566'}], u'endpoints_links': [], u'type': u'volume', u'name': u'cinder'}] instance_lock_checked = False quota_class = None user_name = admin project_name = admin is_admin = True
后面我们来逐个分析其中的方法。
(1) is_valid_body方法
该方法检查客户端传入的消息体是否合法,这个方法位于Controller类的基类wsgi.Controller中。is_valid_body方法首先检查消息体中是否含有server字段,然后检查server字段的内容是否为字典。
接下来的一系列方法都是获取并验证客户端传入的虚拟机参数。其中,server_dict保存了虚拟机参数,包括虚拟机名、镜像uuid、需要的网络、固定ip、虚拟机规格等等。
(2) _validate_server_name方法
该方法检查虚拟机名的长度是否越界。
(3) _validate_access_ipv4&_validate_access_ipv6方法
该方法验证传入的固定ip格式是否合法。
(4) _favor_id_from_req_data方法
该方法对HTTP请求中包含的虚拟机规格id进行过滤解析。所谓规格id就是url包含的id或者uuid的值,如http://www.foo.com/bar/123?q=4,该方法则返回123。
(5) get_instance_type_get_by_flavor_id方法
该方法位于nova/nova/compute/instance_types.py中,该方法调用了nova/nova/db/api.py下的instance_type_get_by_flavor_id方法,其功能是根据虚拟机规格id,从数据库中查找对应信息后返回。在openstack中,与数据库的交互用的是sqlalchemy这个东东,我目前也不是很熟悉,先放一放吧,后面我再专门分析。
再接下来调用了Nova Compute的API处理虚拟机的创建请求。Compute API的create方法会返回一个创建虚拟机的列表。重点分析一下这个方法。
(6) compute_api.create方法
class API(base.Base): def create(self,context,instance_type, ...): #检查客户端是否具有创建虚拟机的权限 self._check_create_policies(context, availability_zone, requested_networks, block_device_mapping) #进一步处理创建虚拟机的请求 return self._create_instance(context,intance_type, ...)
其中_check_create_policies方法的作用是检查客户端是否有创建虚拟机的权限,该方法会通过查询policy.json文件来查看用户权限,其内部逻辑和Keystone服务的权限管理类似。由于这里只是谈虚拟机的创建过程,所以关于Keystone就不在展开详谈。
接下来就是我们的重头戏了——_create_instance方法。这个方法就是执行进一步的虚拟机的创建过程,后面的文章我会花大篇幅来详细分析。
注:这里我们为了便于理解,再次打印出传入这个方法的参数实例
context = <nova.context.RequestContext object at 0x447d050> instance_type = {'memory_mb': 2048L, 'root_gb': 20L, 'deleted_at': None, 'name': u'm1.small', 'deleted': 0L, 'created_at': None, 'ephemeral_gb': 0L, 'updated_at': None, 'disabled': False, 'vcpus': 1L, 'extra_specs': {}, 'swap': 0L, 'rxtx_factor': 1.0, 'is_public': True, 'flavorid': u'2', 'vcpu_weight': None, 'id': 5L} image_href = 20612b24-c980-4900-b270-8e6b66e5f72f kernel_id = None ramdisk_id = None min_count = 1 max_count = 1 display_name = test3 display_description = test3 key_name = oskey key_data = None security_group = ['default'] availability_zone = None user_data = None metadata = {} injected_files = [] admin_password = Piu4aSSNmSNk block_device_mapping = [] access_ip_v4 = None access_ip_v6 = None requested_networks = None config_drive = None auto_disk_config = None scheduler_hints = {}
相关文章推荐
- OpenStack之Nova分析——创建虚拟机(八)
- OpenStack之Nova分析——创建虚拟机(五)
- OpenStack之Nova分析——创建虚拟机(四)
- openstack Nova分析之 创建虚拟机流程(4)
- OpenStack之Nova分析——创建虚拟机(二)
- OpenStack之Nova分析——创建虚拟机(三)
- OpenStack之Nova分析——创建虚拟机(七)——创建虚拟机镜像文件
- OpenStack之Nova分析——创建虚拟机(六)
- 【openstack】Nova创建虚拟机流程2 -scheduler
- 原创:openstack创建虚拟机流程图(完成到scheduler向nova-compute发送rpc请求)
- Openstack针对nova,cinder,glance使用ceph的虚拟机创建机制优化
- Nova创建虚拟机的底层代码分析
- 【openstack】Nova创建虚拟机流程1
- Openstack之Nova创建虚机流程分析
- openstack之虚拟机创建流程分析
- openstack:nova中“从镜像启动”创建虚拟机的流程
- OpenStack Nova深入学习 -- 创建instance的过程之源码分析
- Openstack针对nova,cinder,glance使用ceph的虚拟机创建机制优化 .
- 【openstack】Nova创建虚拟机流程3-compute