Horizon前台界面用于接受用户的输入或动作(action),然后将这些参数构造成RESTful API(https://developer.openstack.org/api-ref/compute/#create-server),并通过novaclient发出。Nova-API负责接受该RESTFul API请求,通过RPC调用将消息发送到RabbitMQ,Nova-Compute订阅了该消息,接受消息后随机调用Libvirt API,指挥KVM-QEMU去真正创建虚拟机。

对虚拟机的增删改查(前台)操作,发出的url请求都会被以下模块正则匹配到:

urlpatterns = patterns(
VIEW_MOD,
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^filter/(?P<vm_state>[^/]+)/$', views.IndexView.as_view(), name='filter'),
url(r'^create$', views.CreateInstanceView.as_view(), name='create'),
url(INSTANCES % 'update', views.UpdateView.as_view(), name='update'),
url(INSTANCES % 'rebuild', views.RebuildView.as_view(), name='rebuild'),

拿创建虚拟机的操作为例,有一系列的步骤(workflow)需要用户选择和操作,目的是拼接足够多的(创建虚拟机所必须的)参数:

class CreateInstanceView(workflows.WorkflowView):
workflow_class = project_workflows.CreateInstance
ajax_template_name = constants.INSTANCE_CREATE_TEMPLATE
success_url = reverse_lazy(constants.INSTANCES_INDEX_URL)

默认的workflow为:

class CreateInstance(workflows.Workflow):
slug = "create_instance"
name = _("Create Instance")
finalize_button_name = _("Create")
success_message = _('Launched %(count)s named "%(name)s".')
failure_message = _('Unable to launch %(count)s named "%(name)s".')
success_url = constants.INSTANCES_INDEX_URL
wizard = True
default_steps = (
SelectImages,
CustomFlavors,
SelectHost,
SelectNetworks,
SetInstanceDetails

)
@sensitive_variables('context')
def handle(self, request, context):
custom_script = context.get('script_data', '')
vcpus = int(context.get('vcpus', 0))
ram = int(context.get('ram', 0)) * 1024
disk = int(float(context.get('disk', 0)))
count = int(context.get('count', 0))
pool = context.get('pool', None)
try:
rets = api.nova.server_create(request,
context['name'],
image_id,
flavor_id,
None,
normalize_newlines(custom_script),
context['groups'],
meta=meta,
fips=fips)

workflow走完之后,就执行handle方法了,Horizon中有一个api python包,里面有nova,keystone,glance等的api,这些api都是对novaclient、keystoneclient、glanceclient等的封装。

@write_log("Create Server")
def server_create(request, name, image, flavor, key_name, user_data,
security_groups, block_device_mapping=None,
block_device_mapping_v2=None, nics=None,
availability_zone=None, instance_count=1, admin_pass=None,
disk_config=None, config_drive=None, meta=None,
host=None, fips=None): return Server(novaclient(request).servers.create(
name, image, flavor, userdata=user_data,
security_groups=security_groups,
key_name=key_name, block_device_mapping=block_device_mapping,
block_device_mapping_v2=block_device_mapping_v2,
nics=nics, availability_zone=availability_zone,
min_count=instance_count, admin_pass=admin_pass,
disk_config=disk_config, config_drive=config_drive,
meta=meta, fips=fips), request)

novaclient的create方法获得需要的参数后,构造Restful api,并发送到Nova服务中,由nova-api负责接收。

在Nova组件中,nova/api/openstack/compute/servers.py(nova-api)的Controller负责接受请求并进行处理。

class Controller(wsgi.Controller):
def create(self, req, body):
try:
_get_inst_type = flavors.get_flavor_by_flavor_id
inst_type = _get_inst_type(flavor_id, ctxt=context,
read_deleted="no") (instances, resv_id) = self.compute_api.create(context,
inst_type,
image_uuid,
display_name=name,
display_description=name,
key_name=key_name,
metadata=server_dict.get('metadata', {}),
config_drive=config_drive,
block_device_mapping=block_device_mapping,
auto_disk_config=auto_disk_config,
scheduler_hints=scheduler_hints,
legacy_bdm=legacy_bdm,
check_server_group_quota=check_server_group_quota,
floating_ips=floating_ips) return self._add_location(robj) def _delete(self, context, req, instance_uuid):
instance = self._get_server(context, req, instance_uuid)
if CONF.reclaim_instance_interval:
try:
self.compute_api.soft_delete(context, instance)
except exception.InstanceInvalidState:
self.compute_api.delete(context, instance)
else:
self.compute_api.delete(context, instance)

之后,会调用Nova Compute的api模块的相应方法:

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,
reservation_id=None, scheduler_hints=None,
legacy_bdm=True, shutdown_terminate=False,
check_server_group_quota=False,
floating_ips=None): self.compute_task_api.build_instances(context,
instances=instances, image=boot_meta,
filter_properties=filter_properties,
admin_password=admin_password,
injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=block_device_mapping,
legacy_bdm=False,
floating_ips=floating_ips) return (instances, reservation_id)

然后,会调用Nova-Conductor API中的ComputeTaskAPI相应方法:

def build_instances(self, context, instances, image, filter_properties,
admin_password, injected_files, requested_networks,
security_groups, block_device_mapping, legacy_bdm=True,
floating_ips=None):
self.conductor_compute_rpcapi.build_instances(context,
instances=instances, image=image,
filter_properties=filter_properties,
admin_password=admin_password, injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=block_device_mapping,
legacy_bdm=legacy_bdm,
floating_ips=floating_ips)

之后,又会调用Nova-Conductor模块RPCAPI中的相应方法:

def build_instances(self, context, instances, image, filter_properties,
admin_password, injected_files, requested_networks,
security_groups, block_device_mapping, legacy_bdm=True,
floating_ips=None):
image_p = jsonutils.to_primitive(image)
kw = {'instances': instances, 'image': image_p,
'filter_properties': filter_properties,
'admin_password': admin_password,
'injected_files': injected_files,
'requested_networks': requested_networks,
'security_groups': security_groups,
'floating_ips': floating_ips} version = '1.9'
if not self.client.can_send_version('1.9'):
version = '1.8'
kw['requested_networks'] = kw['requested_networks'].as_tuples()
if not self.client.can_send_version('1.7'):
version = '1.5'
kw.update({'block_device_mapping': block_device_mapping,
'legacy_bdm': legacy_bdm}) cctxt = self.client.prepare(version=version)
cctxt.cast(context, 'build_instances', **kw)

该方法会获取messaging模块中的RPCClient,然后通过cast的方式将消息发送到RabbitMQ中。

  • RPC.call:发送请求到消息队列,等待返回最终结果。例如nova-compute调用nova-network服务分配网络,需要获得结果。
  • RPC.cast:发送请求到消息队列,不需要等待最终返回的结果。例如nova-conductor服务调用nova-compute的build_and_run_instance。

最终,nova-compute订阅了RabbitMQ的消息,接受到创建虚拟机的消息。创建虚拟机的操作,由/nova/compute/manager.py ComputeManager中的_do_build_and_run_instance方法完成。

def _do_build_and_run_instance(self, context, instance, image,
request_spec, filter_properties, admin_password, injected_files,
requested_networks, security_groups, block_device_mapping,
node=None, limits=None,
floating_ip=None):
try:
self._build_and_run_instance(context, instance, image,
decoded_files, admin_password, requested_networks,
security_groups, block_device_mapping, node, limits,
filter_properties,
floating_ip=floating_ip)
def _build_and_run_instance(self, context, instance, image, injected_files,
admin_password, requested_networks, security_groups,
block_device_mapping, node, limits, filter_properties,
floating_ip=None):
try:
self.driver.spawn(context, instance, image,
injected_files, admin_password,
network_info=network_info,
block_device_info=block_device_info)

最后,调用Libvirt(Driver)的api接口,完成创建虚拟机的操作。/nova/virt/libvirt/driver spawn方法为创建本地镜像,获取虚机xml文件,创建domain:

def spawn(self, context, instance, image_meta, injected_files,
admin_password, network_info=None, block_device_info=None):
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance,
block_device_info,
image_meta) self._create_image(context, instance,
disk_info['mapping'],
network_info=network_info,
block_device_info=block_device_info,
files=injected_files,
admin_pass=admin_password)
xml = self._get_guest_xml(context, instance, network_info,
disk_info, image_meta,
block_device_info=block_device_info,
write_to_disk=True)
self._create_domain_and_network(context, xml, instance, network_info,
block_device_info, disk_info=disk_info)
LOG.debug("Instance is running", instance=instance)

Openstack创建虚拟机 Restful api和RPC调用的更多相关文章

  1. openstack创建虚拟机的步骤

    图片来自互联网. 虚拟机启动过程如下: 1.界面或命令行通过RESTful API向keystone获取认证信息.2.keystone通过用户请求认证信息,并生成auth-token返回给对应的认证请 ...

  2. 云计算---openstack创建虚拟机过程

     虚拟机创建过程: (1)界面或命令行通过RESTful API向keystone获取认证信息.(2)keystone通过用户请求认证信息,并生成auth-token返回给对应的认证请求.(3)界面或 ...

  3. Hadoop学习记录(3)|HDFS API 操作|RPC调用

    HDFS的API操作 URL方式访问 package hdfs; import java.io.IOException; import java.io.InputStream; import java ...

  4. 快速创建Flask Restful API项目

    前言 Python必学的两大web框架之一Flask,俗称微框架.它只需要一个文件,几行代码就可以完成一个简单的http请求服务. 但是我们需要用flask来提供中型甚至大型web restful a ...

  5. 使用 Express 和 waterline 创建简单 Restful API

    这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000004996659  突然想起来我这个博客冷落了好多年了,也该更新一下, ...

  6. 如何解决OpenStack创建虚拟机或删除虚拟机时一直处于deleting或者creating状态的问题(转载)

    原文地址:http://www.cnblogs.com/robertoji/p/4968280.html 在OpenStack使用时,有时候会遇到创建虚拟机或者删除虚拟机无法成功创建或者删除的时候,一 ...

  7. openstack 创建虚拟机失败

    虚拟机创建失败    用户创建一台虚拟机,虚拟机使用4个网络平面,所以虚拟机选择了4个不同平面的网络,创建虚拟机一直在孵化的过程中,最后创建虚拟机失败. 失败后返回的报错日志 Build of ins ...

  8. 快速创建yii2 RESTful api的小记

    1.复制backend的应用到同级目录,改名叫api 2.然后就是配置项修改,common和api目录下的 common下: bootstrap.php最后添加一行配置 api/config/main ...

  9. openstack创建虚拟机之后使用ssh登陆的解决办法

    创建一个虚机之后:若果想要在horizon的控制台上登录操作,第一步.需要先使用ssh从controller上修改密码 从controller上登录: ssh ubuntu@虚机ip sudo su ...

随机推荐

  1. [分布式系统学习]阅读笔记 Distributed systems for fun and profit 之三 时间和顺序

    这是阅读 http://book.mixu.net/distsys/time.html 的笔记,是该系列的第三章. 为什么时间和顺序很重要呢?为什么我们关系事件A发生在事件B之前? 因为分布式系统要解 ...

  2. 不同修饰符使用细节(java)

    常用来修饰类.方法.变量的修饰符如下 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权限修饰符,默认访 ...

  3. 使用find命令按条件查找多个文件并且拷贝至指定目录

    命令格式如下 find / \( -name "*.war" -o -name "*.jar" \) | xargs -i cp {} ${wardir} 当需 ...

  4. OpenCV学习笔记之课后习题练习3-3

    3.3 创建一个100*100的拥有三个通道的二维字节类型矩阵,将其元素全部置0.通过cvPtr2D函数将指针指向中间通道(绿色),以(20,5)和(40,20)为顶点间画一个绿色的长方形. cvPt ...

  5. 各种小巧的Hello World

    在Reddit看到这篇文章:Hello from a libc-free world! ,觉得挺有趣,然后又想起以前看过的各种相关资料,在此做一个整理.注意所有实验环境都为Linux. 版本一: 实际 ...

  6. 图论最短路——dijkstra

    下午直接开始dijkstra的堆优化,很简单的这里把书上的原理说一下吧,小心和prim最小生成树的堆优化迷,Dijkstra算法基于贪心思想,它只适用于所有边都是非负数的图.当变长z都是非负数的时候, ...

  7. 新同事,git又报错Please move or remove them before you merge

    http://blog.csdn.net/hufengvip/article/details/17231133 下面一行搞定 git clean -d -fx ""

  8. 什么是 Delta 文件

    什么是 Delta 文件 Delta 文件应用很广泛,特别是在数据库领域 What Is a Delta File? During most computer operations, copying, ...

  9. 64位win10+cuda8.0+vs2013+cuDNN V5下Caffe的编译安装教程并配置matlab2014a 接口

    一.需要安装的软件 1)vs2013,我是在http://www.52pojie.cn/thread-492326-1-1.html这个网址安装的.我之前用的是vs2012,按照网上的配置教程会爆各种 ...

  10. 十天精通CSS3(1)

    什么是CSS3? CSS3是CSS2的升级版本,3只是版本号,它在CSS2.1的基础上增加了很多强大的新功能. 目前主流浏览器chrome.safari.firefox.opera.甚至360都已经支 ...