本帖最后由 xioaxu790 于 2014-6-11 10:34 编辑
问题导读:
1、Openstack中扩展API有哪些方式?
2、写一个新的模块来声明控制器实现扩展?
Openstack 中规定,扩展openstack的api有两种方式
1、创建新的WSGI 资源
2、扩展原有得WSGI资源得控制器(我得理解是,接受到API请求后,具体得响应逻辑)
这两种方式中,都要求写一个新的模块来声明控制器类去处理请求和实现扩展。
在一个API模块中,可以有一个或多个得资源和扩展控制器。
根据osapi_compute_extension 得配置, ExtensionManager 由nova/api/openstack/compute/contrib/ 下的__init__.py 文件加载标准的或者新的扩展。
所以扩展的api统一写在nova/api/openstack/compute/contrib/ 目录下
如本例子中得 nova/api/openstack/compute/contrib/documents.py
扩展API流程
实现控制器,完成对资源的基本操作,如增删改查和其他一些用户自定义的RESTful资源操作;
实现一个extensions.ExtensionDescriptor的子类, 并实现get_resources 或者(/以及)get_controller_extensions,来建立新的资源或扩展资源控制器(即改写原有的业务逻辑)。具体实现哪个方法这取决于是否要修改原有的RESTFul业务逻辑, 或者说两个功能都需要;
将控制器和扩展的资源类,写如新创建的的资源中; 规范是资源类是模块(问家名)首字母大写,这样做的目的是使nova.api.openstack.extensions.load_standard_extensions这个类能够是别该新资源,并予以加载;
当添加新的资源(extensions.ResourceExtension的子类)的时候,如果想要去除掉 {tenent_id} 链接,则需要编写自定义的路由访问规则(本例子中没有涉及)
documents.py 实现
- # vim: tabstop=4 shiftwidth=4 softtabstop=4
-
- # Author: JiangYiTao
- # Email: willierjyt@gmail.com
-
- import webob
- from webob import exc
-
- from nova import db
- from nova import exception
- from nova.api.openstack import extensions
- authorize = extensions.extension_authorizer('compute', 'documents')
-
- # 请求控制器, 即处理对资源的请求,予以响应
- class DocumentsController():
- """the Documents API Controller declearation"""
-
- def index(self, req):
- import pdb; pdb.set_trace()
- documents = {}
- context = req.environ['nova.context']
- authorize(context)
-
- documents["key"] = "helloworld"
- return documents
-
- def create(self, req):
- documents = {}
- context = req.environ['nova.context']
- authorize(context)
-
- documents["key"] = "helloworld"
- return documents
-
- def show(self, req, id):
- documents = {}
- context = req.environ['nova.context']
- authorize(context)
-
- try:
- document = db.document_get(context, id)
- except :
- raise webob.exc.HTTPNotFound(explanation="Document not found")
-
- documents["document"] = document
- return documents
-
- def update(self, req):
- documents = {}
- context = req.environ['nova.context']
- authorize(context)
-
- documents["key"] = "helloworld"
- return documents
- def delete(self, req, id):
- return webob.Response(status_int=202)
- # 根据命名规范, 模块(python源文件)中的类名是模块名的首字母大写
- class Documents(extensions.ExtensionDescriptor):
- """Documents ExtensionDescriptor implementation"""
- name = "documents"
- alias = "os-documents"
- namespace = "www.www.com"
- updated = "2013-05-19T00:00:00+00:00"
-
- def get_resources(self):
- """register the new Documents Restful resource"""
-
- resources = [extensions.ResourceExtension('os-documents',
- DocumentsController())
- ]
-
复制代码
扩展api时所修改的文件
- nova/db/api.py
- nova/db/sqlalchemy/api.py
- nova/db/sqlalchemy/models.py
复制代码
nova/db/api.py 文件内容
#数据操作API提供的方法,由Nova API 根据请求进行相应的操作, 由上面的请求控制器进行调用
- def document_get(context, document_id):
- """Get a document or raise if it does not exist."""
- return IMPL.document_get(context, document_id)
复制代码
nova/db/sqlalchemy/api.py 文件内容
- # 完成通过由SQLAlchemy操作数据库
- @require_admin_context
- def document_get(context, document_id): 4 session = get_session()
- with session.begin():
- query = model_query(context, models.Document, session=session, read_deleted="yes").filter_by(id=document_id)
- result = query.first()
- if not result or not query:
- raise Exception()
- return result
复制代码
SQLAlchemy 中定义的资源
nova/db/sqlalchemy/models.py(具体使用见上一 篇日志)
- class Document(BASE, NovaBase):
- """Represents a document of customized extension."""
-
- __tablename__ = 'documents'
- id = Column(Integer, primary_key=True)
- title = Column(String(255))
复制代码
至此,添加添加新的nova API功能完成
重起api服务
调用
- curl -v -X GET -H 'X-Auth-Token: 8e5971b3ce0a4f039b895681e7c29361' http://127.0.0.1:8774/v2/9b5903dd2d3443d8bb75ddffac27239a/extensions/os-documents | python -mjson.tool命令,
复制代码
可以看到返回,扩展添加成功
复制代码
数据库添加表documents, 结构如下
- mysql> desc documents;
- +------------+--------------+------+-----+---------+----------------+
- | Field | Type | Null | Key | Default | Extra |
- +------------+--------------+------+-----+---------+----------------+
- | id | int(11) | NO | PRI | NULL | auto_increment |
- | title | varchar(255) | NO | | NULL | |
- | created_at | datetime | YES | | NULL | |
- | updated_at | datetime | YES | | NULL | |
- | deleted_at | datetime | YES | | NULL | |
- | deleted | int(11) | YES | | NULL | |
- +------------+--------------+------+-----+---------+----------------+
- 6 rows in set (0.05 sec)
复制代码
- mysql> select * from documents;
- +----+----------------+------------+------------+------------+---------+
- | id | title | created_at | updated_at | deleted_at | deleted |
- +----+----------------+------------+------------+------------+---------+
- | 1 | abcdefgiifeife | NULL | NULL | NULL | NULL |
- | 2 | 1qaz2wsx | NULL | NULL | NULL | NULL |
- +----+----------------+------------+------------+------------+---------+
- 2 rows in set (0.03 sec)
复制代码
调用命令
- curl -X GET -H 'X-Auth-Token: 8e5971b3ce0a4f039b895681e7c29361' http://127.0.0.1:8774/v2/9b5903dd2d3443d8bb75ddffac27239a/os-documents/1 | python -mjson.tool
- 返回结果
- {
- "document": {
- "created_at": null,
- "deleted": null,
- "deleted_at": null,
- "id": 1,
- "title": "abcdefgiifeife",
- "updated_at": null
- }
复制代码
至此新添加的资源,API 扩展成功, 可以在此基础上进行进一步的修改,完成需求
|