Add forwarder function to pecan framework 71/33571/5
authorHong Hui Xiao <honghui_xiao@yeah.net>
Thu, 1 Mar 2018 08:25:40 +0000 (16:25 +0800)
committerHong Hui Xiao <honghui_xiao@yeah.net>
Mon, 12 Mar 2018 08:58:32 +0000 (16:58 +0800)
Add forward(or proxy) functionality, so that multicloud component
is able to forward request to another component.

TEST DONE:
GET POST DELETE (/networks)

Registry/Unregistry/Identity

Change-Id: I73f71c62a91301c0864f1a00fd95f016f69a89d4
Issue-ID: MULTICLOUD-150
Signed-off-by: Hong Hui Xiao <honghui_xiao@yeah.net>
multivimbroker/multivimbroker/api_v2/api_router/v0_controller.py

index 10922e5..83b4260 100644 (file)
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
+import logging
 import pecan
 
 from multivimbroker.swagger import utils
+from multivimbroker.pub import exceptions
+from multivimbroker.pub.utils import restcall
+from multivimbroker.pub.utils import syscomm
+
+
+logger = logging.getLogger(__name__)
+
+# TODO: Move to a constant file.
+REGISTRY_URI = "registry"
+UNREGISTRY_URI = ""
+IDENTITY_URI = "identity/v3"
+IDENTITY_AUTH_URI = "identity/v3/auth/tokens"
 
 
 class V0_Controller(object):
@@ -20,3 +33,57 @@ class V0_Controller(object):
     @pecan.expose('json', route="swagger.json")
     def swagger_json(self):
         return utils.get_swagger_json_data()
+
+    def _filter_illegal_uri(self, uri, method):
+        """
+        Filter unsupported actions, so they can be stopped at begginning.
+        """
+
+        if uri == REGISTRY_URI and method != "POST":
+            pecan.abort(405)
+
+        if uri == UNREGISTRY_URI and method != "DELETE":
+            pecan.abort(405)
+
+        if (uri in (IDENTITY_URI, IDENTITY_AUTH_URI) and
+                method not in ("POST", "GET")):
+            pecan.abort(405)
+
+    @pecan.expose()
+    def _route(self, remainder, request):
+        uri = "/".join(remainder[1:])
+        method = request.method
+        self._filter_illegal_uri(uri, method)
+
+        return self.forwarder, remainder
+
+    @pecan.expose('json')
+    def forwarder(self, *remainder, **kwargs):
+        """ Forward any requests that don't have a specific match """
+
+        # TODO(xiaohhui): Add validator for vim_id.
+        vim_id = remainder[0]
+        request = pecan.request
+        try:
+            vim_url = syscomm.getMultivimDriver(vim_id,
+                                                full_path=request.path)
+
+            # NOTE: Not sure headers should be set here. According to original
+            # code, headers are discarded.
+            retcode, content, status_code, resp = restcall.req_by_msb(
+                vim_url, request.method, content=request.body)
+        except exceptions.NotFound as e:
+            pecan.abort(404, detail=str(e))
+        except Exception as e:
+            pecan.abort(500, detail=str(e))
+
+        if retcode:
+            # Execptions are handled within req_by_msb
+            logger.error("Status code is %s, detail is %s.",
+                         status_code, content)
+        response = pecan.Response(body=content, status=status_code)
+
+        for k in syscomm.getHeadersKeys(resp):
+            response.headers[k] = resp[k]
+
+        return response