OpenStack Nova深入学习 -- 创建instance的过程之源码分析
来源:互联网 发布:数据库系统的基础是 编辑:程序博客网 时间:2024/04/27 22:39
Nova的核心组件有nova API, nova Conductor,nova Scheduler和nova compute。如下图所示:
1). nova API -- 主要是接收HTTP请求(通常来自nova client),将其转换成命令,并通过oslo message和nova Conductor或者nova Compute交互。为了完成虚机的处理(比如创建、修改,删除等)操作,nova API还需要通过HTTP协议向Keystone, Neutron, Glance发出请求。
2). nova Conductor -- 主要作为一个数据库代理存在,避免nova Compute直接操作数据库。
3). nova Compute -- 主要是操纵compute node上的hypervisor对instance进行创建和管理。
4). nova Scheduler -- 主要是用来判断新创建的instance应该被放在哪一个compute node上,它的配置在/etc/nova/nova.conf里完成,缺省配置如下:
scheduler_available_filters=nova.scheduler.filters.all_filtersscheduler_default_filters=RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter
scheduler_driver=nova.scheduler.filter_scheduler.FilterScheduler
其中,scheduler_driver决定了nova用什么样的scheduler,scheduler_default_filters决定了在一个compute node被选中作为instance的宿主前,都需要过哪些检查关口,如下是这些检查关口的说明:
-- RetryFilter:找出还没有被尝试filter过的compute node
-- AvailabilityZoneFilter:必须在规定的availability zone里选compute node
-- RamFilter:compute node必须有足够的内存支持instance的创建
-- ComputeFilter:必须有compute node存在
-- ComputeCapabilitiesFilter:compute node必须满足instance创建需要的extra specs
-- ImagePropertiesFilter:compute node必须满足镜像里定义的属性,比如architecture是否是qcow2,是否支持KVM hyperviosr等。
-- ServerGroupAntiAffinityFilter:如果创建多个instance,需要让这些instance分布在不同的compute node上
-- ServerGroupAffinityFilter:如果创建多个instance,需要让这些instance分布在相同的compute node上
下面,通过nova的源码看一下一个新的instance被创建需要经过哪些过程,代码来自Liberty版本:
创建instance的入口代码在nova/api/openstack/compute/servers.py,方法是create(),如下:
def create(self, req, body): (instances, resv_id) = self.compute_api.create(context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get('metadata', {}), admin_password=password, requested_networks=requested_networks, check_server_group_quota=True, **create_kwargs)
compute_api对象来自compute.API类,如下。而compute.API来自nova/compute/__init__.py。
self.compute_api = compute.API(skip_policy_check=True)
查看nova/compute/__init__.py,看到API()返回的就是nova.compute.api.API,如下。所以compute_api就是nova.compute.api.API。
CELL_TYPE_TO_CLS_NAME = {'api': 'nova.compute.cells_api.ComputeCellsAPI', 'compute': 'nova.compute.api.API', None: 'nova.compute.api.API', }def _get_compute_api_class_name(): """Returns the name of compute API class.""" cell_type = nova.cells.opts.get_cell_type() return CELL_TYPE_TO_CLS_NAME[cell_type]def API(*args, **kwargs): class_name = _get_compute_api_class_name() return importutils.import_object(class_name, *args, **kwargs)
查看nova/compute/api.py,看到create()方法调用了_create_instance(),如下:
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,… return self._create_instance( context, instance_type, image_href, kernel_id, ramdisk_id, min_count, max_count,…
_create_instance()也在nova/compute/api.py中定义,它又调用了compute_task_api对象的build_instances()方法,如下:
def _create_instance(self, context, instance_type, image_href, kernel_id, ramdisk_id, min_count, max_count,… self.compute_task_api.build_instances(context, instances=instances, image=boot_meta, filter_properties=filter_properties,…
compute_task_api对象也在nova/compute/api.py中定义,来自conductor.ComputeTaskAPI对象,如下:
def compute_task_api(self): if self._compute_task_api is None: # TODO(alaski): Remove calls into here from conductor manager so # that this isn't necessary. #1180540 from nova import conductor self._compute_task_api = conductor.ComputeTaskAPI() return self._compute_task_api
ComputeTaskAPI对象在nova/conductor/__init__.py中定义,来自nova.conductor.api.ComputeTaskAPI,如下:
from nova.conductor import api as conductor_apidef ComputeTaskAPI(*args, **kwargs): use_local = kwargs.pop('use_local', False) if oslo_config.cfg.CONF.conductor.use_local or use_local: api = conductor_api.LocalComputeTaskAPI else: api = conductor_api.ComputeTaskAPI return api(*args, **kwargs)
查看nova/conductor/api.py,build_instances()方法调用了conductor_compute_rpcapi对象的build_instances()方法。conductor_compute_rpcapi对象来自nova/conductor/rpcapi.py中定义的ComputeTaskAPI类。
class ComputeTaskAPI(object):… def __init__(self): self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI()… def build_instances(self, context, instances, image, filter_properties, admin_password, injected_files, requested_networks, security_groups, block_device_mapping, legacy_bdm=True): self.conductor_compute_rpcapi.build_instances(context, instances=instances, image=image,……
nova/conductor/rpcapi.py是专门处理nova组件之间的RPC调用的。因为这里定义的topic是conductor,根据http://www.cnblogs.com/littlebugfish/p/4090311.html中的描述的消息队列原理,这里将转到nova-conductor进程中进行处理。
def build_instances(self, context, instances, image, filter_properties, admin_password, injected_files, requested_networks,… cctxt = self.client.prepare(version=version) cctxt.cast(context, 'build_instances', **kw)
查看nova/conductor/manager.py,看到build_instances()方法会调用scheduler_client.select_destinations()和compute_rpcapi.build_and_run_instance()。前者会调用schedular的RPC API选择在哪些主机上创建instance,后者会通过RPC请求nova-compute服务去构建和运行instance。
class ComputeTaskManager(base.Base):… def build_instances(self, context, instances, image, filter_properties, admin_password, injected_files, requested_networks,…… try:… hosts = self.scheduler_client.select_destinations(context, request_spec, filter_properties)… for (instance, host) in itertools.izip(instances, hosts):… self.compute_rpcapi.build_and_run_instance(context, instance=instance, host=host['host'], image=image, request_spec=request_spec,…
查看nova/compute/manager.py,整个的调用过程如下:
build_and_run_instance() --> _do_build_and_run_instance() --> _build_and_run_instance() --> driver.spawn()
driver对象是在nova/virt/driver.py里定义,调用load_compute_driver()方法获得并加载compute driver。compute driver的定义是在/etc/nova/nova.conf里由compute_driver的值确定。
def __init__(self, compute_driver=None, *args, **kwargs): self.driver = driver.load_compute_driver(self.virtapi, compute_driver)def load_compute_driver(virtapi, compute_driver=None): if not compute_driver: compute_driver = CONF.compute_driver if not compute_driver: LOG.error(_LE("Compute driver option required, but not specified")) sys.exit(1) LOG.info(_LI("Loading compute driver '%s'"), compute_driver) try: driver = importutils.import_object_ns('nova.virt', compute_driver, virtapi) return utils.check_isinstance(driver, ComputeDriver)
- OpenStack Nova深入学习 -- 创建instance的过程之源码分析
- Openstack Nova 源码分析 — 使用 VCDriver 创建 VMware Instance
- openstack nova 源码分析2之nova-api,nova-compute
- 【OpenStack源码分析之五】Nova API 的插件管理
- openstack nova 源码分析
- OpenStack Nova 源码分析
- 小菜openstack nova 源码学习之 evacuate
- 小菜openstack nova 源码学习之 force_down
- Openstack Nova(四)----Instance 创建(Overview)
- Openstack Nova(八)----Instance 创建(流水线)
- OpenStack源码分析之Nova-Compute服务启动过程(icehouse)
- Openstack Nova(七)----Instance 创建(nova WSGI)
- Openstack Nova 源码分析 — RPC 远程调用过程
- nova创建虚机流程源码分析 openstack
- 【OpenStack源码分析之三】Nova-Compute启动流程分析
- openstack nova schedule 源码学习
- OpenStack Nova源码分析之-基础环境配置
- OpenStack之Nova分析——创建虚拟机(一)
- Object类的常见方法
- Weka分类---J48
- 137Single Number II
- 顺序栈的建立、迷宫问题
- 【JAVA】java字节码导读
- OpenStack Nova深入学习 -- 创建instance的过程之源码分析
- BZOJ1803: Spoj1487 Query on a tree III
- STM8s使用中遇到的死机问题的排除
- jsp连接数据库实现用户登录功能
- 【ShawnZhang】带你看数据结构——第十四课:通讯录
- 《UNIX网络编程》 第三章 套接字编程简介
- IDEA编写Spark程序及手动Artifacts并运行
- JAVA开源软件开发必备技能-发布构建到maven中央仓库的方法和详细步骤
- 生成树计数