From 2c897eb5d3d43b9bb0c9f30285d1c4f8d0e40c9f Mon Sep 17 00:00:00 2001 From: Sindhu Devale Date: Wed, 7 Dec 2016 19:56:54 +0000 Subject: [PATCH] Create Octavia api V2 directory Introduce V2 directory to begin work in exposing v2.0 API for Octavia. Change-Id: I420aa8ca607d428ac9cc5063db7f5c70cdf0922c --- octavia/api/root_controller.py | 17 ++++- octavia/api/v2/__init__.py | 0 octavia/api/v2/controllers/__init__.py | 41 +++++++++++ octavia/api/v2/controllers/base.py | 98 ++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 octavia/api/v2/__init__.py create mode 100644 octavia/api/v2/controllers/__init__.py create mode 100644 octavia/api/v2/controllers/base.py diff --git a/octavia/api/root_controller.py b/octavia/api/root_controller.py index 88f5b7dbc3..de22c5c664 100644 --- a/octavia/api/root_controller.py +++ b/octavia/api/root_controller.py @@ -12,16 +12,18 @@ # License for the specific language governing permissions and limitations # under the License. +import pecan from pecan import rest from wsme import types as wtypes from wsmeext import pecan as wsme_pecan -from octavia.api.v1 import controllers +from octavia.api.v1 import controllers as v1_controller +from octavia.api.v2 import controllers as v2_controller class RootController(rest.RestController): """The controller in which the pecan wsgi app should be created with.""" - v1 = controllers.V1Controller() + v1 = v1_controller.V1Controller() @wsme_pecan.wsexpose(wtypes.text) def get(self): @@ -29,4 +31,13 @@ class RootController(rest.RestController): # here return {'versions': [{'status': 'CURRENT', 'updated': '2014-12-11T00:00:00Z', - 'id': 'v1'}]} + 'id': 'v1'}, + {'status': 'EXPERIMENTAL', + 'updated': '2016-12-11T00:00:00Z', + 'id': 'v2.0'} + ]} + + +# This controller cannot be specified directly as a member of RootController +# as its path is not a valid python identifier +pecan.route(RootController, 'v2.0', v2_controller.V2Controller()) diff --git a/octavia/api/v2/__init__.py b/octavia/api/v2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/octavia/api/v2/controllers/__init__.py b/octavia/api/v2/controllers/__init__.py new file mode 100644 index 0000000000..b1253eca9c --- /dev/null +++ b/octavia/api/v2/controllers/__init__.py @@ -0,0 +1,41 @@ +# Copyright 2016 Intel +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import pecan + +from octavia.api.v1.controllers import load_balancer +from octavia.api.v2.controllers import base + + +class BaseV2Controller(base.BaseController): + loadbalancers = load_balancer.LoadBalancersController() + + @pecan.expose() + def get(self): + return "v2.0" + + +class LBaaSController(BaseV2Controller): + """Expose /lbaas/ endpoint for the v2.0 controller. + + Provides backwards compatibility with LBaaSV2 + + To be removed once LBaasV2 has been removed. + + """ + pass + + +class V2Controller(BaseV2Controller): + lbaas = LBaaSController() \ No newline at end of file diff --git a/octavia/api/v2/controllers/base.py b/octavia/api/v2/controllers/base.py new file mode 100644 index 0000000000..0668d2d2dc --- /dev/null +++ b/octavia/api/v2/controllers/base.py @@ -0,0 +1,98 @@ +# Copyright 2014 Rackspace +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +from oslo_config import cfg +from pecan import rest +from stevedore import driver as stevedore_driver + +from octavia.common import data_models +from octavia.common import exceptions +from octavia.db import repositories +from octavia.i18n import _LE + +CONF = cfg.CONF +LOG = logging.getLogger(__name__) + + +class BaseController(rest.RestController): + + def __init__(self): + super(BaseController, self).__init__() + self.repositories = repositories.Repositories() + self.handler = stevedore_driver.DriverManager( + namespace='octavia.api.handlers', + name=CONF.api_handler, + invoke_on_load=True + ).driver + + @staticmethod + def _convert_db_to_type(db_entity, to_type, children=False): + """Converts a data model into a Octavia WSME type + + :param db_entity: data model to convert + :param to_type: converts db_entity to this time + """ + if isinstance(to_type, list): + to_type = to_type[0] + + def _convert(db_obj): + return to_type.from_data_model(db_obj, children=children) + if isinstance(db_entity, list): + converted = [_convert(db_obj) for db_obj in db_entity] + else: + converted = _convert(db_entity) + return converted + + @staticmethod + def _get_db_obj(session, repo, data_model, id): + """Gets an object from the database and returns it.""" + db_obj = repo.get(session, id=id) + if not db_obj: + LOG.exception(_LE("{name} {id} not found").format( + name=data_model._name(), id=id)) + raise exceptions.NotFound( + resource=data_model._name(), id=id) + return db_obj + + def _get_db_lb(self, session, id): + """Get a load balancer from the database.""" + return self._get_db_obj(session, self.repositories.load_balancer, + data_models.LoadBalancer, id) + + def _get_db_listener(self, session, id): + """Get a listener from the database.""" + return self._get_db_obj(session, self.repositories.listener, + data_models.Listener, id) + + def _get_db_pool(self, session, id): + """Get a pool from the database.""" + return self._get_db_obj(session, self.repositories.pool, + data_models.Pool, id) + + def _get_db_member(self, session, id): + """Get a member from the database.""" + return self._get_db_obj(session, self.repositories.member, + data_models.Member, id) + + def _get_db_l7policy(self, session, id): + """Get a L7 Policy from the database.""" + return self._get_db_obj(session, self.repositories.l7policy, + data_models.L7Policy, id) + + def _get_db_l7rule(self, session, id): + """Get a L7 Rule from the database.""" + return self._get_db_obj(session, self.repositories.l7rule, + data_models.L7Rule, id)