openstack如何扩展API之一:新添加API

(文章来自作者维护的社区微信公众号【虚拟化云计算】)
目前有两个微信群《kvm虚拟化》和《openstack》,扫描二维码点击“云-交流”,进群交流提问
(本文以nova-api为例子,完整的添加一个新的nova-api,并写一个测试程序进行测试)
一。创建API资源模块
    为新的Restful资源写一个controller实现标准操作(如index、create、delete…),以及其它定制的动作。
定义extensions.V21APIExtensionBase 的一个子类,此子类实现get_resources和get_controller_extensions方法,建立一个新的资源或控制器扩展。添加一个文件:
nova/api/openstack/compute/extended_comcat api/openstack/compute/extended_common.py
"""The instance interface extension."""
 
import webob
from webob import exc
 
from nova.api.openstack.compute.schemas import extended_common
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api import validation
from nova import exception
from nova import db
from nova.i18n import _
from nova.policies import extended_common as extended_common_policies
 
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
 
ALIAS = 'os-extended-common'
 
class ExtendedCommonController(wsgi.Controller):
 
    def __init__(self):
        super(ExtendedCommonController, self).__init__()
 
    @extensions.expected_errors(404)
    @validation.schema(extended_common.create)
    def create(self, req, body):
        context = req.environ['nova.context']
        context.can(extended_common_policies.BASE_POLICY_NAME)
        context.can(extended_common_policies.POLICY_ROOT % 'create')
        LOG.info(body)
 
    @extensions.expected_errors(())
    def gettest(self, req):
        context = req.environ['nova.context']
        return dict(controller={'myhost': 'compute1'} )
 
class ExtendedCommon(extensions.V21APIExtensionBase):
    """extended common support."""
 
    name = "ExtendedCommon"
    alias = ALIAS
    version = 1
 
    def get_resources(self):
        member_actions = {'action': 'POST'}
        collection_actions = {'gettest': 'GET'}
        resources = [
            extensions.ResourceExtension(
                ALIAS,
                ExtendedCommonController(),
                collection_actions=collection_actions,
                member_actions=member_actions)]
        return resources
 
    def get_controller_extensions(self):
        return []
这里我们建立了一个新的文件:extended_common.py;在里面建立了类ExtendedCommon。其ALIAS='os-extended-common'。这些后面会使用到。

 

二。规定API调用到的数据结构
nova/api/openstack/compute/schemas/extended_common.py
from nova.api.validation import parameter_types
 
create = {
    'type': 'object',
    'properties': {
        'MyTest': {
            'type': 'object',
            'properties': {
                'myhost': parameter_types.hostname,
            },
            'additionalProperties': False,
        },
    },
    'additionalProperties': False,
}
 
三。注册API
nova/policies/__init__.py
from nova.policies import extended_common
......
def list_rules():
    return itertools.chain(
        ......
        extended_common.list_rules(),
        ......
nova/policies/extended_common.py
from oslo_policy import policy
from nova.policies import base
 
BASE_POLICY_NAME = 'os_compute_api:os-extended-common'
POLICY_ROOT = 'os_compute_api:os-extended-common:%s'
 
extended_common_policies = [
    policy.RuleDefault(
        name=BASE_POLICY_NAME,
        check_str=base.RULE_ADMIN_API),
    policy.RuleDefault(
        name=POLICY_ROOT % 'create',
        check_str=base.RULE_ANY),
    policy.RuleDefault(
        name=POLICY_ROOT % 'discoverable',
        check_str=base.RULE_ANY),
    policy.RuleDefault(
        name=POLICY_ROOT % 'show',
        check_str=base.RULE_ANY),
]
 
def list_rules():
    return extended_common_policies
 
四。添加entry_points
nova.egg-info/entry_points.txt
extended_common = nova.api.openstack.compute.extended_common:ExtendedCommon
 
五。查看API是否被导出
# systemctl restart nova-api
# nova list-extensions
应该能看到os-extended-common。
 
六。测试
 
测试程序
import json
import urllib2
CONTROLLER_HOSTNAME='controller'
class Opthttp(object):
    def __init__(self, passwd):
        self.token = None
        self.tenant = None
        self.token, self.tenant = self.__get_token(passwd)
 
    def __get_token(self, passwd):
        url = 'http://%s:5000/v2.0/tokens' % CONTROLLER_HOSTNAME
        values = {"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin", "password": passwd}}}
        data = self.http_post(url, values)
        token = data['access']['token']['id']
        tenant = data['access']['token']['tenant']['id']
        return token, tenant
 
    def http_get(self, url):
        req = urllib2.Request(url)
        req.add_header('X-Auth-Token', self.token)
        response = urllib2.urlopen(req)
        data = response.read()
        data = json.loads(data)
        return data
 
    def _do_http_post(self, method, url, body):
        if body:
            jdata = json.dumps(body)
            req = urllib2.Request(url, jdata)
        else:
            req = urllib2.Request(url, None)
        req.add_header('Content-Type', 'application/json')
        req.add_header('Accept', 'application/json')
        if self.token:
            req.add_header('X-Auth-Token', self.token)
        req.get_method = lambda: method
        response = urllib2.urlopen(req)
        data = response.read()
        if data != '':
            data = json.loads(data)
        return data
 
    def http_post(self, url, body):
        return self._do_http_post('POST', url, body)
 
    def http_put(self, url, body):
        return self._do_http_post('PUT', url, body)
 
    def http_delete(self, url, body):
        return self._do_http_post('DELETE', url, body)
 
url = '%s/5ad08373b2814d16833959228c714329/os-extended-common' %('http://127.0.0.1:8774/v2.1')
body = {"MyTest": {'myhost': 'compute2'}}
ret = Opthttp('cloud').http_post(url, body)
 
url = '%s/5ad08373b2814d16833959228c714329/os-extended-common/gettest' %('http://127.0.0.1:8774/v2.1')
controller = Opthttp('cloud').http_get(url)
print controller

 

====================================================================
关注微信公众号【虚拟化云计算】,阅读更多虚拟化云计算知识,纯技术干货更新不停。
 
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值