diff options
-rw-r--r-- | vio/docker/Dockerfile | 4 | ||||
-rw-r--r-- | vio/requirements.txt | 14 | ||||
-rwxr-xr-x | vio/run.sh | 17 | ||||
-rwxr-xr-x | vio/stop.sh | 3 | ||||
-rwxr-xr-x | vio/vio/event_listener/server.py | 7 | ||||
-rw-r--r-- | vio/vio/pub/config/config.py | 4 | ||||
-rw-r--r-- | vio/vio/settings.py | 4 | ||||
-rw-r--r-- | vio/vio/swagger/urls.py | 7 | ||||
-rw-r--r-- | vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py | 27 | ||||
-rw-r--r-- | vio/vio/swagger/views/fakeplugin/image/views.py | 18 | ||||
-rw-r--r-- | vio/vio/tests/test_proxy_identity_view.py | 264 | ||||
-rw-r--r-- | vio/vio/tests/test_restcall.py | 66 |
12 files changed, 419 insertions, 16 deletions
diff --git a/vio/docker/Dockerfile b/vio/docker/Dockerfile index 9c67741..30d7ce8 100644 --- a/vio/docker/Dockerfile +++ b/vio/docker/Dockerfile @@ -7,8 +7,8 @@ ENV AAI_PORT "8443" ENV AAI_SCHEMA_VERSION "v11" ENV AAI_USERNAME "AAI" ENV AAI_PASSWORD "AAI" -ENV MR_ADDR “127.0.0.1” -ENV MR_PORT “3904” +ENV MR_ADDR "127.0.0.1" +ENV MR_PORT "3904" EXPOSE 9004 diff --git a/vio/requirements.txt b/vio/requirements.txt index 32384a9..1e2334c 100644 --- a/vio/requirements.txt +++ b/vio/requirements.txt @@ -13,7 +13,7 @@ django-redis-cache==0.13.1 httplib2==0.9.2 # for call openstack api -openstacksdk==0.9.14 +openstacksdk==0.9.15 python-cinderclient==3.5.0 # for unit test @@ -24,3 +24,15 @@ unittest_xml_reporting==1.12.0 # for onap logging onappylog>=1.0.6 + +# for event +oslo_messaging + +# for pecan framework +uwsgi +pecan>=1.2.1 +oslo.concurrency>=3.21.0 +oslo.config>=4.11.0 +oslo.service>=1.25.0 +eventlet>=0.20.0 +PyYAML>=3.1.0 @@ -26,11 +26,16 @@ sed -i "s/MR_PORT =.*/MR_PORT = \"${MR_PORT}\"/g" vio/pub/config/config.py logDir="/var/log/onap/multicloud/vio" -nohup python manage.py runserver 0.0.0.0:9004 2>&1 & -nohup python vio/event_listener/server.py 2>&1 & - -while [ ! -f $logDir/vio.log ]; do - sleep 1 -done +if [ "$WEB_FRAMEWORK" == "pecan" ] +then + python multivimbroker/scripts/api.py +else + # nohup python manage.py runserver 0.0.0.0:9004 2>&1 & + nohup uwsgi --http :9004 --module vio.wsgi --master --processes 4 & + nohup python vio/event_listener/server.py 2>&1 & + while [ ! -f $logDir/vio.log ]; do + sleep 1 + done tail -F $logDir/vio.log +fi diff --git a/vio/stop.sh b/vio/stop.sh index 718b3cb..e07394a 100755 --- a/vio/stop.sh +++ b/vio/stop.sh @@ -11,4 +11,5 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -ps auxww | grep 'manage.py runserver 0.0.0.0:9004' | awk '{print $2}' | xargs kill -9 +# ps auxww | grep 'manage.py runserver 0.0.0.0:9004' | awk '{print $2}' | xargs kill -9 +ps auxww |grep 'uwsgi --http :9004 --module vio.wsgi --master' |awk '{print $2}' |xargs kill -9 diff --git a/vio/vio/event_listener/server.py b/vio/vio/event_listener/server.py index 83b9e6f..5e6dc00 100755 --- a/vio/vio/event_listener/server.py +++ b/vio/vio/event_listener/server.py @@ -9,8 +9,11 @@ import ConfigParser import json import os import requests -from vio.pub.config.config import MR_ADDR -from vio.pub.config.config import MR_PORT +import sys +sys.path.append("..") +from pub.config.config import MR_ADDR # noqa +from pub.config.config import MR_PORT # noqa + LOG = logging.getLogger(__name__) diff --git a/vio/vio/pub/config/config.py b/vio/vio/pub/config/config.py index 757ba28..b6b8caa 100644 --- a/vio/vio/pub/config/config.py +++ b/vio/vio/pub/config/config.py @@ -29,8 +29,8 @@ AAI_USERNAME = 'AAI' AAI_PASSWORD = 'AAI' # [DMaaP] -MR_ADDR = "127.0.0.1" -MR_PORT = "3904" +MR_ADDR = '127.0.0.1' +MR_PORT = '3904' # [MDC] SERVICE_NAME = "multicloud-vio" diff --git a/vio/vio/settings.py b/vio/vio/settings.py index f1dad0f..68411ea 100644 --- a/vio/vio/settings.py +++ b/vio/vio/settings.py @@ -26,9 +26,9 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '3o-wney!99y)^h3v)0$j16l9=fdjxcb+a8g+q3tfbahcnu2b0o' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +# DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['*'] # Application definition diff --git a/vio/vio/swagger/urls.py b/vio/vio/swagger/urls.py index 3871599..e0195fc 100644 --- a/vio/vio/swagger/urls.py +++ b/vio/vio/swagger/urls.py @@ -65,6 +65,8 @@ from vio.swagger.views.fakeplugin.image.views import FakeImage from vio.swagger.views.fakeplugin.image.views import FakeImageVersion from vio.swagger.views.fakeplugin.image.views import FakeImageDetail from vio.swagger.views.fakeplugin.image.views import FakeImageSchema +from vio.swagger.views.fakeplugin.image.views import FakeImageDownload +from vio.swagger.views.fakeplugin.image.views import FakeImageUpload from vio.swagger.views.fakeplugin.nova.views import FakeNovaServer from vio.swagger.views.fakeplugin.nova.views import FakeNovaHypervisors from vio.swagger.views.fakeplugin.nova.views import FakeNovaAggregate @@ -210,6 +212,11 @@ urlpatterns = [ FakeImageDetail.as_view()), url(r'^api/multicloud-vio/v0/vmware_fake/glance/v2/images', FakeImage.as_view()), + url(r'^api/multicloud-vio/v0/vmware_fake/glance/v2/image/file/' + r'(?P<imageid>[0-9a-z-A-Z\-\_]+)$', + FakeImageDownload.as_view()), + url(r'^api/multicloud-vio/v0/vmware_fake/glance/v2/image/file$', + FakeImageUpload.as_view()), url(r'^api/multicloud-vio/v0/vmware_fake/glance/version', FakeImageVersion.as_view()), url(r'^api/multicloud-vio/v0/vmware_fake/neutron$', diff --git a/vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py b/vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py index 0368f02..c23a1b2 100644 --- a/vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py +++ b/vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py @@ -1854,6 +1854,33 @@ def image_detail(): return data +def upload_image(req): + + data = { + "status": "active", + "name": req.get('name'), + "tags": [], + "container_format": req.get('container_format'), + "created_at": "2014-05-05T17:15:10Z", + "disk_format": req.get('disk_format'), + "updated_at": "2014-05-05T17:15:11Z", + "visibility": req.get('visibility'), + "self": "/v2/images/1bea47ed-f6a9-463b-b423-14b9cca9ad27", + "min_disk": 0, + "protected": "false", + "id": Imageid, + "file": "/v2/images/1bea47ed-f6a9-463b-b423-14b9cca9ad27/file", + "checksum": "64d7c1cd2b6f60c92c14662941cb7913", + "owner": "5ef70662f8b34079a6eddb8da9d75fe8", + "size": 13167616, + "min_ram": 0, + "schema": req.get('schema'), + "virtual_size": "null" + } + + return data + + def list_image(): data = { diff --git a/vio/vio/swagger/views/fakeplugin/image/views.py b/vio/vio/swagger/views/fakeplugin/image/views.py index 6d6e242..74d7467 100644 --- a/vio/vio/swagger/views/fakeplugin/image/views.py +++ b/vio/vio/swagger/views/fakeplugin/image/views.py @@ -2,11 +2,13 @@ from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response +import json from vio.swagger.views.fakeplugin.fakeData.fakeResponse import image_detail from vio.swagger.views.fakeplugin.fakeData.fakeResponse import list_image from vio.swagger.views.fakeplugin.fakeData.fakeResponse import image_schema from vio.swagger.views.fakeplugin.fakeData.fakeResponse import image_version +from vio.swagger.views.fakeplugin.fakeData.fakeResponse import upload_image false = "false" null = "null" @@ -42,3 +44,19 @@ class FakeImageVersion(APIView): data = image_version() return Response(data=data, status=status.HTTP_200_OK) + + +class FakeImageDownload(APIView): + + def get(self, request, imageid): + + data = image_detail() + return Response(data=data, status=status.HTTP_200_OK) + + +class FakeImageUpload(APIView): + + def post(self, request): + req = json.loads(request.body) + data = upload_image(dict(req)) + return Response(data=data, status=status.HTTP_201_CREATED) diff --git a/vio/vio/tests/test_proxy_identity_view.py b/vio/vio/tests/test_proxy_identity_view.py new file mode 100644 index 0000000..a8bf9fb --- /dev/null +++ b/vio/vio/tests/test_proxy_identity_view.py @@ -0,0 +1,264 @@ +# Copyright (c) 2018 VMware, Inc. +# +# 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. + +import mock +import unittest + +from vio.pub.msapi import extsys +from vio.swagger.views.proxyplugin.httpclient import BaseClient +from vio.swagger.views.proxyplugin.identity import views + + +class TestIdentityServer(unittest.TestCase): + + def setUp(self): + self.view = views.IdentityServer() + + @mock.patch.object(BaseClient, "buildRequest") + @mock.patch.object(BaseClient, "_request") + def test_get(self, mock_req, mock_build): + mock_build.return_value = ("http://onap.org", {}, None) + self.view.get(mock.Mock(), "openstack_regionone") + mock_req.assert_called_once() + + @mock.patch.object(BaseClient, "send") + def test_patch(self, mock_send): + self.view.patch(mock.Mock(), "openstack_regionone", None) + mock_send.assert_called_once() + + @mock.patch.object(BaseClient, "send") + def test_post(self, mock_send): + self.view.post(mock.Mock(), "openstack_regionone", None) + mock_send.assert_called_once() + + @mock.patch.object(BaseClient, "send") + def test_delete(self, mock_send): + self.view.delete(mock.Mock(), "openstack_regionone", None) + mock_send.assert_called_once() + + @mock.patch.object(BaseClient, "send") + def test_head(self, mock_send): + self.view.head(mock.Mock(), "openstack_regionone", None) + mock_send.assert_called_once() + + +class TestTokenView(unittest.TestCase): + + def setUp(self): + self.view = views.TokenView() + + @mock.patch("requests.get") + @mock.patch.object(extsys, "get_vim_by_id") + def test_get_v3(self, mock_getvim, mock_req): + req = mock.Mock() + req.get_full_path.return_value = "identity/v3" + res = mock.Mock() + res.status_code = 200 + res.json.return_value = { + "version": { + "links": [{ + "href": "" + }] + } + } + mock_req.return_value = res + resp = self.view.get(req, "vmware_nova") + self.assertEqual(resp.status_code, 200) + + @mock.patch.object(extsys, "get_vim_by_id") + def test_get_v2(self, mock_getvim): + req = mock.Mock() + req.get_full_path.return_value = "identity/v2.0" + resp = self.view.get(req, "vmware_nova") + self.assertEqual(resp.status_code, 405) + + @mock.patch.object(BaseClient, "buildRequest") + @mock.patch.object(BaseClient, "_request") + def test_delete(self, mock_req, mock_build): + req = mock.Mock() + req.META = { + "HTTP_X_SUBJECT_TOKEN": "aaa" + } + mock_build.return_value = ("http://onap.org", {}, None) + self.view.delete(req, "openstack_regionone") + mock_req.assert_called_once() + + @mock.patch("requests.post") + @mock.patch.object(extsys, "get_vim_by_id") + def test_post_v3(self, 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")] + res.json.return_value = { + "token": { + "value": "token-value", + "project": { + "id": "project-id" + }, + "catalog": [{ + "type": "volume", + "id": "3e4941704e9941a582b157ac7203ec1b", + "name": "cinder", + "endpoints": [{ + "url": "http://onap.org/api/multicloud/v0/xxx", + "interface": "public" + }] + }] + } + } + mock_post.return_value = res + resp = self.view.post(req, "vmware_nova") + self.assertEqual(200, resp.status_code) + + @mock.patch("requests.post") + @mock.patch.object(extsys, "get_vim_by_id") + def test_post_v2(self, mock_getvim, mock_post): + req = mock.Mock() + req.get_full_path.return_value = "identity/v2.0/tokens" + req.body = """{ + "auth": { + "tenantName": "tenant-name", + "passwordCredentials": { + "username": "admin", + "password": "pass" + } + } + }""" + mock_getvim.return_value = { + "url": "http://onap.org/identity/v2.0/tokens" + } + res = mock.Mock() + res.status_code = 200 + res.headers = [("X-Subject-Token", "fake-token")] + res.json.return_value = { + "access": { + "token": { + "value": "token-value", + "tenant": { + "id": "tenant-id" + }, + }, + "serviceCatalog": [{ + "type": "volume", + "id": "3e4941704e9941a582b157ac7203ec1b", + "name": "cinder", + "endpoints": [{ + "adminURL": "http://onap.org/api/multicloud/v0/xxx", + "internalURL": "http://onap.org/api/multicloud/v0/xxx", + "publicURL": "http://onap.org/api/multicloud/v0/xxx" + }] + }] + } + } + mock_post.return_value = res + resp = self.view.post(req, "vmware_nova") + self.assertEqual(200, resp.status_code) + + +class TestTokenV2View(unittest.TestCase): + + def setUp(self): + self.view = views.TokenV2View() + + @mock.patch("requests.get") + @mock.patch.object(extsys, "get_vim_by_id") + def test_get_v2(self, mock_getvim, mock_get): + req = mock.Mock() + req.get_full_path.return_value = "identity/v2.0" + mock_getvim.return_value = { + "url": "http://onap.org/identity/v3" + } + res = mock.Mock() + res.status_code = 200 + res.json.return_value = { + "version": { + "links": [{ + "href": "" + }] + } + } + mock_get.return_value = res + resp = self.view.get(req, "vmware_nova") + self.assertEqual(resp.status_code, 200) + + @mock.patch("requests.post") + @mock.patch.object(extsys, "get_vim_by_id") + def test_post(self, mock_getvim, mock_post): + req = mock.Mock() + req.get_full_path.return_value = "identity/v2.0/tokens" + req.body = """{ + "auth": { + "tenantName": "tenant-name", + "passwordCredentials": { + "username": "admin", + "password": "pass" + } + } + }""" + mock_getvim.return_value = { + "url": "http://onap.org/identity/v2.0/tokens" + } + res = mock.Mock() + res.status_code = 200 + res.headers = [("X-Subject-Token", "fake-token")] + res.json.return_value = { + "access": { + "token": { + "value": "token-value", + "tenant": { + "id": "tenant-id" + }, + }, + "serviceCatalog": [{ + "type": "volume", + "id": "3e4941704e9941a582b157ac7203ec1b", + "name": "cinder", + "endpoints": [{ + "adminURL": "http://onap.org/api/multicloud/v0/xxx", + "internalURL": "http://onap.org/api/multicloud/v0/xxx", + "publicURL": "http://onap.org/api/multicloud/v0/xxx" + }] + }] + } + } + mock_post.return_value = res + resp = self.view.post(req, "vmware_nova") + self.assertEqual(200, resp.status_code) + + +class TestIdentityVersionLink(unittest.TestCase): + + def setUp(self): + self.view = views.IdentityVersionLink() + + @mock.patch.object(BaseClient, "buildRequest") + @mock.patch.object(BaseClient, "_request") + def test_get(self, mock_req, mock_build): + mock_build.return_value = ("http://onap.org", {}, None) + res = mock.Mock() + res.status_code = 200 + res.data = { + "version": { + "links": [{ + "href": "" + }] + } + } + mock_req.return_value = res + resp = self.view.get(mock.Mock(), "vmware_nova") + self.assertEqual(200, resp.status_code) diff --git a/vio/vio/tests/test_restcall.py b/vio/vio/tests/test_restcall.py new file mode 100644 index 0000000..051dddf --- /dev/null +++ b/vio/vio/tests/test_restcall.py @@ -0,0 +1,66 @@ +# Copyright (c) 2017-2018 VMware, Inc. +# 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. + +import mock +import unittest + +from vio.pub.utils import restcall + + +class TestRestCall(unittest.TestCase): + + def test_combine_url(self): + url = ["http://a.com/test/", "http://a.com/test/", + "http://a.com/test", "http://a.com/test"] + res = ["/resource", "resource", "/resource", "resource"] + expected = "http://a.com/test/resource" + for i in range(len(url)): + self.assertEqual(expected, restcall.combine_url(url[i], res[i])) + + @mock.patch.object(restcall, "call_req") + def test_get_res_from_aai(self, mock_call): + res = "cloud-regions" + content = "" + expect_url = "https://aai.api.simpledemo.openecomp.org:8443/aai/v13" + expect_user = "AAI" + expect_pass = "AAI" + expect_headers = { + 'X-FromAppId': 'MultiCloud', + 'X-TransactionId': '9001', + 'content-type': 'application/json', + 'accept': 'application/json' + } + restcall.get_res_from_aai(res, content=content) + mock_call.assert_called_once_with( + expect_url, expect_user, expect_pass, restcall.rest_no_auth, + res, "GET", content, expect_headers) + + @mock.patch.object(restcall, "call_req") + def test_req_by_msb(self, mock_call): + res = "multicloud" + method = "GET" + content = "no content" + restcall.req_by_msb(res, method, content=content) + expect_url = "http://127.0.0.1:10080/" + mock_call.assert_called_once_with( + expect_url, "", "", restcall.rest_no_auth, res, method, + content) + + @mock.patch("httplib2.Http.request") + def test_call_req_success(self, mock_req): + mock_resp = { + "status": "200" + } + resp_content = "hello" + mock_req.return_value = mock_resp, resp_content + expect_ret = [0, resp_content, "200", mock_resp] + ret = restcall.call_req("http://onap.org/", "user", "pass", + restcall.rest_no_auth, "vim", "GET") + self.assertEqual(expect_ret, ret) |