nova创建虚拟机源码分析系列之四 nova代码模拟
在前面的三篇博文中,介绍了restful和SWGI的实现。结合restful和WSGI配置就能够简单的实现nova服务模型的最简单的操作。
如下的内容是借鉴网上博文,因为写的很巧妙,将nova管理虚拟机的过程刻画十分清楚,所以想自己实现一遍,加深印象。
在上一篇博文中写的URL的对应处理函数,结果是十分简单的return 一个网页。
在openstack当中肯定不会这么简单的处理,毕竟前面的工作只是将路修好,真正的功能还未实现呢!
所以对于nova操作的模拟,要实现的是对虚拟机的增,删,改,查等功能。而这些功能不是在一个return中就能实现的。
nova功能模拟操作的RESTFUl:
URL | 方法 | 描述 |
/instances | GET | 列出集合所有的虚拟机记录 |
/instances | POST | 添加一条虚拟机记录 |
/instances/instance_id | GET | 获取一条虚拟机记录的信息 |
/instances/instance_id | PUT |
更新一条虚拟机的记录 |
/instances/instancd_id | DELETE | 删除一条虚拟机九路 |
在博文中定义的文件如下:
配置WSGI服务器:
1 配置 configure.ini
[pipeline:main]
pipeline = auth instance
[app:instance]
paste.app_factory = routers:app_factory
[filter:auth]
paste.filter_factory = auth:filter_factory
首先解析配置文件,pipeline是管道,管道流是由“过滤器认证模块”auth 和 app 应用程序 instance组成。
app 应用程序的位置是routers文件的app_factory方法
filter 过滤器实现的认证模块,位置是auth文件的filter_factory方法。
下面的文件分别实现了router.py和auth.py
2 服务器端
server.py
from wsgiref.simple_server import make_server
from paste import httpserver
from paste.deploy import loadapp
import os if __name__ == '__main__':
configfile = 'configure.ini'
appname = 'main'
wsgi_app = loadapp('config:%s' % os.path.abspath(configfile), appname) server = make_server('localhost', 8000, wsgi_app)
server.serve_forever()
3 filter auth实现程序
auth.py
from webob.dec import *
from webob import Request,Response
from webob import exc class Auth(object):
def __init__(self, app):
self.app = app @wsgify
def __call__(self, req):
print 'Auth class'
resp = self.process_request(req)
if resp:
return resp
return self.app(req) @wsgify
def process_request(self, req):
if req.headers.get('X-Auth-Token') != 'open-sesame':
return exc.HTTPForbidden()
@wsgify.middleware
def filter_factory(app, global_config, **local_config):
return Auth(app)
过滤器的实现,其实现方法是filter_factory,参数有一个app,然后调用Auth方法。Auth方法是类的__call__方法,其实现是:
def __call__(self, req):
print 'Auth class' 打印了一个字符串
认证具体实现的地方,调用了一个函数。
具体实现就是取出请求报文头中的'X-Auth-Token',判断是不是'open-sesame'
resp = self.process_request(req)
if resp:
return resp
如果判断通过了,则调用传入的app,具体到本例中就是instance
return self.app(req)
4 app instance实现程序
routers.py
from webob.dec import *
from webob import Request,Response
import webob.exc from routes import Mapper,middleware
import controllers class Router(object):
def __init__(self):
self.mapper = Mapper()
self.add_routes()
self.router = middleware.RoutesMiddleware(self._dispatch, self.mapper) @wsgify
def __call__(self, req):
return self.router def add_routes(self):
controller = controllers.Controller() self.mapper.connect('/instances', controller = controller,action = 'create', conditions = {'method' : ['POST']})
self.mapper.connect('/instances', controller = controller,action = 'index', conditions = {'method' : ['GET']})
self.mapper.connect('/instances/{instance_id}', controller = controller,action = 'show', conditions = {'method' : ['GET']})
self.mapper.connect('/instances/{instance_id}', controller = controller,action = 'update', conditions = {'method' : ['PUT']})
self.mapper.connect('/instances/{instance_id}', controller = controller,action = 'delete', conditions = {'method':['DELETE']}) @staticmethod
@wsgify
def _dispatch(req):
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound() app = match['controller']
return app def app_factory(global_config, **local_config):
return Router()
router.py是instance的实现文件。app_factory为处理方法,其调用了Router(),Router()是类Router的__call__()方法。
__call__方法直接返回了对象router,router在初始化的时候实现了函数
middleware.RoutesMiddleware(self._dispatch, self.mapper)
该函数有两个参数,一个是mapper,一个是_dispatch。传入参数
mapper的作用是在该函数中负责解析URL,根据URL查找到对应的处理函数的类。
_dispath函数就是负责接收mapper解析出来的类,然后调用该类。
可以看到_dispatch从接收到的数据中匹配出app app = match['controller'] ,然后返回了该app,而这个app就是实现nova具体功能的类。对应的类在下面的文件controller中实现。
mapper成员出了作为函数的传入参数之后,还做了一件事情,就是注册了URL的请求和对应方法。简单来说就是注册URL和对应处理函数。
例如:create方法:
controller = controllers.Controller()
self.mapper.connect('/instances', controller = controller,action = 'create', conditions = {'method' : ['POST']})
第一行是说变量controller对应的是文件controller.py 中的Controller类。
第二行进行绑定,URL路径是/instances,请求类型是POST,对应的处理方法是 类 Controller中的'create'函数。
5 实际处理函数
controllers.py
import uuid
from webob import Request,Response
import simplejson
from webob.dec import wsgify class Controller(object):
def __init__(self):
self.instances = {}
for i in range(3):
inst_id = str(uuid.uuid4())
self.instances[inst_id] = {'id' : inst_id, 'name' : 'inst-' + str(i)} #print self.instances
@wsgify
def create(self, req):
print req.params
name = req.params['name']
if name:
inst_id = str(uuid.uuid4()) inst = {'id' : inst_id, 'name' : name}
self.instances[inst_id] = inst
return {'instance' : inst} @wsgify
def show(self, req, instance_id):
inst = self.instances.get(instance_id)
return {'instance ' : inst} @wsgify
def index(self, req):
return {'instances': self.instances.values()} @wsgify
def delete(self, req, instance_id):
if self.instances.get(instance_id):
self.instances.pop(instance_id)
@wsgify
def update(self, req, instance_id):
inst = self.instances.get(instance_id)
name = req.params['name']
if inst and name:
inst['name'] = name
return {'instance': inst} @wsgify
def __call__(self, req):
arg_dict = req.environ['wsgiorg.routing_args'][1]
action = arg_dict.pop('action')
del arg_dict['controller'] method = getattr(self, action)
result = method(req, **arg_dict) if result is None:
return Response(body='',status='204 Not Found',headerlist=[('Content-Type','application/json')])
else:
if not isinstance(result, str):
result = simplejson.dumps(result)
return result
终于到了功能具体实现的地方了。当router.py中的_dispatch方法返回了一个app之后,就是调用了该app。这个app就是类名字,同时也是类中的__call__方法。
__call__方法中实现的功能如下:
@wsgify
def __call__(self, req):
arg_dict = req.environ['wsgiorg.routing_args'][1] #获取URL解析结果
action = arg_dict.pop('action') #获取处理的方法
del arg_dict['controller'] #删除 controller项,剩下的都是参数列表 method = getattr(self, action) #搜索controller类中定义的方法
result = method(req, **arg_dict) #调用方法,处理HTTP请求
if result is None: #无返回值
return Response(body='',status='204 Not Found',headerlist=[('Content-Type','application/json')])
else:#有返回值
if not isinstance(result, str):
result = simplejson.dumps(result) #将返回值转化为字符串
return result
运行WSGI服务器:
使用请求:
GET http://127.0.0.1:8080/instances
以查看虚拟机情况的流程为例,分析过程:
- 客户端使用命令:curl - H 'X-Auth-Token:open-sesame ' 127.0.0.1:8080/instances,请求虚拟机信息
- server.py中的WSGI服务器一直监听在127.0.0.1的8080端口,收到客户端的请求。请求的具体内容就是上图的"req"打印内容。
- WSGI服务通过配置的configure.ini文件,分析出/instancesURL处理的类是COntroller类。
- router.py中的app_factory被调用,分析URL和添加对应关系之后,调用Controller类。
- Controller类的__call__方法根据 GET方法 + /instance路径分析出对应的处理函数是index。
- 调用index函数,返回结果,判断返回值,将信息返回给客户端。
添加虚拟机:
POST http://127.0.0.1:8080/instances
data : name=demo_one
nova创建虚拟机源码分析系列之四 nova代码模拟的更多相关文章
- nova创建虚拟机源码分析系列之五 nova源码分发实现
前面讲了很多nova restful的功能,无非是为本篇博文分析做铺垫.本节说明nova创建虚拟机的请求发送到openstack之后,nova是如何处理该条URL的请求,分析到处理的类. nova对于 ...
- nova创建虚拟机源码分析系列之三 PasteDeploy
上一篇博文介绍WSGI在nova创建虚拟机过程的作用是解析URL,是以一个最简单的例子去给读者有一个印象.在openstack中URL复杂程度也大大超过上一个例子.所以openstack使用了Past ...
- nova创建虚拟机源码分析系列之一 restful api
开始学习openstack源码,源码文件多,分支不少.按照学习的方法走通一条线是最好的,而网上推荐的最多的就是nova创建虚机的过程.从这一条线入手,能够贯穿openstack核心服务.写博文仅做学习 ...
- nova创建虚拟机源码分析系列之七 传入参数转换成内部id
上一篇博文将nova创建虚机的流程推进到了/compute/api.py中的create()函数,接下来就继续分析. 在分析之前简单介绍nova组件源码的架构.以conductor组件为例: 每个组件 ...
- nova创建虚拟机源码分析系列之六 api入口create方法
openstack 版本:Newton 注:博文图片采用了很多大牛博客图片,仅作为总结学习,非商用.该图全面的说明了nova创建虚机的过程,从逻辑的角度清晰的描述了前端请求创建虚拟机之后发生的一系列反 ...
- nova创建虚拟机源码分析系列之八 compute创建虚机
/conductor/api.py _build_instance() /conductor/rpcapi.py _build_instance() 1 构造一些数据类型2 修改一些api版本信息 ...
- nova创建虚拟机源码系列分析之二 wsgi模型
openstack nova启动时首先通过命令行或者dashborad填写创建信息,然后通过restful api的方式调用openstack服务去创建虚拟机.数据信息从客户端到达openstack服 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
随机推荐
- e2e测试之Nightmare
一.e2e测试简介 e2e或者端到端(end-to-end)或者UI测试是一种测试方法,它用来测试一个应用从头到尾的流程是否和设计时候所想的一样.简而言之,它从一个用户的角度出发,认为整个系统都是一个 ...
- Hadoop实战训练————MapReduce实现PageRank算法
经过一段时间的学习,对于Hadoop有了一些了解,于是决定用MapReduce实现PageRank算法,以下简称PR 先简单介绍一下PR算法(摘自百度百科:https://baike.baidu.co ...
- azure备份虚拟机
备份 azure虚拟机 提前创建了一个linux虚拟机,位置是chinaeast. 如果我们需要备份的虚拟机分别在中国东部和北部,那么需要在两个位置都创建备份库. 创建库 登录经典门户,新建-> ...
- Python基础学习-'module' object has no attribute 'urlopen'解决方法
import numpy as npimport urlliburl = "http://archive.ics.uci.edu/ml/machine-learning-databases/ ...
- mysql安装后服务启动不了(总结)
mysql安装后服务启动不了 1.1 前言 最近真的是倒霉到家,装个mysql都能把所有的问题给问候了一遍······不过这也是一个宝贵的经验,得好好总结下,毕竟也不知道以后会不会再次遇到.如果有网友 ...
- 实践作业2:黑盒测试实践——编写自动化脚本并拍摄测试过程视频 Day 6
下午下课之后小组成员一起交流了一下实验过程遇到的一些问题,并汇总了下各个项目完成情况 该实验目前(写博客是时间)基本完成,具体情况如下 (1)分析系统需求 .(done) (2)设计测试用例.(don ...
- python中字母与ascii码的相互转换
在做python编程时,碰到了需要将字母转换成ascii码的,原本以为用Int()就可以直接将字符串转换成整形了,可是int()带了一个默认参数,base=10,这里表示的是十进制,若出现字母,则会报 ...
- vue.js事件,属性,以及交互
这是我学习vue的第二天,今天主要学习了如何利用vue阻止事件冒泡,阻止事件的默认行为,键盘事件以及如何添加class.style这些属性,以及如何利用vue来进行数据交互,利用百度的一个API来写一 ...
- 浏览器抓包(post)
谁能想到我写的第一个wp竟然是个web题??? 以Geek2017_Buy me a Tesla 为例 来看看题目 emmmm有理想还是很好的,火狐打开(事实证明FF对web题是最友好的) 能点的地方 ...
- 框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解)
框架原理第一讲,熟悉常用的设计方式.(以MFC框架讲解) 一丶什么是框架,以及框架的作用 什么是框架? 框架,简而言之就是把东西封装好了,使用框架开发可以快速开发程序,例如MFC程序的双击写代码. 为 ...