From 19ff343fe30e038f11f353a1101a58331415f8d2 Mon Sep 17 00:00:00 2001 From: liangke Date: Tue, 14 Aug 2018 10:52:50 +0800 Subject: Add redis cache to store share data It's fine to run single redis server on local host. Cache cluster should be planed in some situation if we need. Change-Id: I176445e6918b980368953c8626995c80a4e45c46 Issue-ID: MULTICLOUD-300 Signed-off-by: liangke --- vio/docker/Dockerfile | 3 ++- vio/docker/instance-run.sh | 2 ++ vio/requirements.txt | 2 +- vio/vio/pub/utils/syscomm.py | 14 +++++++------- vio/vio/settings.py | 16 ++++++++++++++++ vio/vio/swagger/views/proxyplugin/httpclient.py | 10 ++++++++-- vio/vio/swagger/views/proxyplugin/identity/views.py | 18 ++++++++++-------- vio/vio/tests/test_proxy_identity_view.py | 11 ++++++++--- 8 files changed, 54 insertions(+), 22 deletions(-) diff --git a/vio/docker/Dockerfile b/vio/docker/Dockerfile index cf66f18..2e3f30d 100644 --- a/vio/docker/Dockerfile +++ b/vio/docker/Dockerfile @@ -15,7 +15,8 @@ EXPOSE 9004 RUN apt-get update && \ apt-get install -y unzip && \ apt-get install -y curl && \ - apt-get install -y wget + apt-get install -y wget && \ + apt-get install -y redis-server RUN cd /opt/ && \ diff --git a/vio/docker/instance-run.sh b/vio/docker/instance-run.sh index e5c6ec8..6ae160b 100755 --- a/vio/docker/instance-run.sh +++ b/vio/docker/instance-run.sh @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +service redis-server start + cd ./vio ./run.sh diff --git a/vio/requirements.txt b/vio/requirements.txt index 1647bfc..0cb1b52 100644 --- a/vio/requirements.txt +++ b/vio/requirements.txt @@ -7,7 +7,7 @@ redis==2.10.5 # for access redis cache redisco==0.1.4 -django-redis-cache==0.13.1 +django-redis==4.4.1 # for call rest api httplib2==0.9.2 diff --git a/vio/vio/pub/utils/syscomm.py b/vio/vio/pub/utils/syscomm.py index 60934bd..9058913 100644 --- a/vio/vio/pub/utils/syscomm.py +++ b/vio/vio/pub/utils/syscomm.py @@ -13,9 +13,10 @@ import inspect import json from collections import defaultdict +from django.core.cache import cache +from vio.settings import CACHE_TIMEOUT from rest_framework import status - keystoneV2Json = \ { "auth": { @@ -53,15 +54,14 @@ class Catalogs(object): self.ct = defaultdict(dict) def storeEndpoint(self, vimid, endpoints): - if vimid in self.ct: - self.ct[vimid].update(endpoints) - else: - self.ct.setdefault(vimid, endpoints) + cache.set(vimid, endpoints, CACHE_TIMEOUT) def getEndpointBy(self, vimid, serverType, interface='public'): - vim = self.ct.get(vimid) - return vim.get(serverType).get(interface, "") if vim else "" + if vimid in cache: + vim = cache.get(vimid) + return vim.get(serverType).get(interface, "") + return None def verifyKeystoneV2(param): diff --git a/vio/vio/settings.py b/vio/vio/settings.py index 98fb510..898452e 100644 --- a/vio/vio/settings.py +++ b/vio/vio/settings.py @@ -85,6 +85,22 @@ LOGGING_CONFIG = None LOGGING_FILE = os.path.join(BASE_DIR, 'vio/pub/config/log.yml') config.yamlConfig(filepath=LOGGING_FILE, watchDog=True) +# cache +REDIS_HOST = os.getenv("REDIS_HOST", "127.0.0.1") +REDIS_PORT = os.getenv("REDIS_PORT", "6379") +# note: Should keep same timout with keystone token +# expired time +CACHE_TIMEOUT = 3600*2 +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://" + REDIS_HOST + ":" + REDIS_PORT + "/1", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + } + } +} + if 'test' in sys.argv: from vio.pub.config import config diff --git a/vio/vio/swagger/views/proxyplugin/httpclient.py b/vio/vio/swagger/views/proxyplugin/httpclient.py index def8eb2..0f76bad 100644 --- a/vio/vio/swagger/views/proxyplugin/httpclient.py +++ b/vio/vio/swagger/views/proxyplugin/httpclient.py @@ -73,16 +73,18 @@ class BaseClient(APIView): headers = {} preUrl = catalog.getEndpointBy( vimid, serverType=self.serverType, interface="public") + token = request.META.get('HTTP_X_AUTH_TOKEN', "") tail = "/" + tail if tail else "" tenantid = "/" + tenantid if tenantid else "" - endPointURL = preUrl + tenantid + tail + endPointURL = preUrl + tenantid + tail if preUrl else "" + headers["X-Auth-Token"] = token headers["X-Subject-Token"] = token headers['Content-Type'] = request.META.get( "CONTENT_TYPE", "application/json") - if method == "GET": + if method == "GET" and preUrl is not None: # append parameters in url path query = "" for k, v in request.GET.items(): @@ -105,6 +107,10 @@ class BaseClient(APIView): try: try: + # Authenticated failed If it cann't get + # endpoint from cache + if url == "": + return Response(data="Unauthenticated", status=401) logger.info("%(method)s Request to %(url)s ", {'url': url, 'method': method}) resp = self.session.request( diff --git a/vio/vio/swagger/views/proxyplugin/identity/views.py b/vio/vio/swagger/views/proxyplugin/identity/views.py index ad3a8a7..c6db117 100644 --- a/vio/vio/swagger/views/proxyplugin/identity/views.py +++ b/vio/vio/swagger/views/proxyplugin/identity/views.py @@ -222,15 +222,17 @@ class TokenView(BaseClient): res[2] = MSB_ADDRESS + "/multicloud-vio/v0/" + \ vimid + "/" + i['name'] + "/" + tenantid j['url'] = "http:" + "//" + res[2] + + logger.info("vimid(%(vimid)s) service enpoints %(endpoint)s ", { + "vimid": vimid, "endpoint": vimEndpoints}) + tokenInfo['token']['value'] = resHeader['X-Subject-Token'] + catalog.storeEndpoint(vimid=vimid, endpoints=vimEndpoints) + except Exception as e: logging.exception("error %s" % e) return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - logger.info("vimid(%(vimid)s) service enpoints %(endpoint)s ", { - "vimid": vimid, "endpoint": vimEndpoints}) - tokenInfo['token']['value'] = resHeader['X-Subject-Token'] - catalog.storeEndpoint(vimid=vimid, endpoints=vimEndpoints) Res = Response(data=tokenInfo, status=status.HTTP_200_OK) Res['X-Subject-Token'] = resHeader['X-Subject-Token'] return Res @@ -366,14 +368,14 @@ def _keystoneV2Token(url, vimid=None, create_req=None): "/multicloud-vio/v0/" + vimid + \ "/" + cal["name"] + "/"+tenantid + logger.info("vimid(%(vimid)s) service enpoints %(endpoint)s ", { + "vimid": vimid, "endpoint": vimEndpoints}) + catalog.storeEndpoint(vimid=vimid, endpoints=vimEndpoints) + except Exception as e: logging.exception("error %s" % e) return Response(data={'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - logger.info("vimid(%(vimid)s) service enpoints %(endpoint)s ", { - "vimid": vimid, "endpoint": vimEndpoints}) - - catalog.storeEndpoint(vimid=vimid, endpoints=vimEndpoints) Res = Response(data=tokenInfo, status=status.HTTP_200_OK) return Res diff --git a/vio/vio/tests/test_proxy_identity_view.py b/vio/vio/tests/test_proxy_identity_view.py index a8bf9fb..6dfffa2 100644 --- a/vio/vio/tests/test_proxy_identity_view.py +++ b/vio/vio/tests/test_proxy_identity_view.py @@ -14,6 +14,7 @@ import mock import unittest from vio.pub.msapi import extsys +from vio.pub.utils.syscomm import catalog from vio.swagger.views.proxyplugin.httpclient import BaseClient from vio.swagger.views.proxyplugin.identity import views @@ -94,13 +95,15 @@ class TestTokenView(unittest.TestCase): @mock.patch("requests.post") @mock.patch.object(extsys, "get_vim_by_id") - def test_post_v3(self, mock_getvim, mock_post): + @mock.patch.object(catalog, "storeEndpoint") + def test_post_v3(self, mock_catalog, mock_getvim, mock_post): req = mock.Mock() req.get_full_path.return_value = "identity/v3/auth/tokens" req.body = "{}" mock_getvim.return_value = { "url": "http://onap.org/identity/v3/auth/tokens" } + res = mock.Mock() res.status_code = 200 res.headers = [("X-Subject-Token", "fake-token")] @@ -127,7 +130,8 @@ class TestTokenView(unittest.TestCase): @mock.patch("requests.post") @mock.patch.object(extsys, "get_vim_by_id") - def test_post_v2(self, mock_getvim, mock_post): + @mock.patch.object(catalog, "storeEndpoint") + def test_post_v2(self, mock_catalog, mock_getvim, mock_post): req = mock.Mock() req.get_full_path.return_value = "identity/v2.0/tokens" req.body = """{ @@ -198,7 +202,8 @@ class TestTokenV2View(unittest.TestCase): @mock.patch("requests.post") @mock.patch.object(extsys, "get_vim_by_id") - def test_post(self, mock_getvim, mock_post): + @mock.patch.object(catalog, "storeEndpoint") + def test_post(self, mock_catalog, mock_getvim, mock_post): req = mock.Mock() req.get_full_path.return_value = "identity/v2.0/tokens" req.body = """{ -- cgit 1.2.3-korg