zoukankan      html  css  js  c++  java
  • 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

     

    以查看虚拟机情况的流程为例,分析过程:

    1. 客户端使用命令:curl - H 'X-Auth-Token:open-sesame ' 127.0.0.1:8080/instances,请求虚拟机信息
    2. server.py中的WSGI服务器一直监听在127.0.0.1的8080端口,收到客户端的请求。请求的具体内容就是上图的"req"打印内容。
    3. WSGI服务通过配置的configure.ini文件,分析出/instancesURL处理的类是COntroller类。
    4. router.py中的app_factory被调用,分析URL和添加对应关系之后,调用Controller类。
    5. Controller类的__call__方法根据 GET方法 + /instance路径分析出对应的处理函数是index。
    6. 调用index函数,返回结果,判断返回值,将信息返回给客户端。

    添加虚拟机:

    POST http://127.0.0.1:8080/instances

    data : name=demo_one

  • 相关阅读:
    R语言做文本挖掘 Part4文本分类
    在VS2005中使用原来的IIS调试Web程序(像VS2003一样)
    “提高一下dotnet程序的效率一”中关于exception的问题
    asp.net Cookies 转码的问题 中文丢失
    静态构造函数
    js在firefox中的问题
    模板引擎的一种实现
    .NET面试题,看看你的水平[转]
    转载 软件架构师应该具备的素质(Enterprise Solution Architects and Leadership)
    用正则表达式提取url中的Querystring参数
  • 原文地址:https://www.cnblogs.com/goldsunshine/p/7763395.html
Copyright © 2011-2022 走看看