summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vio/docker/Dockerfile4
-rw-r--r--vio/requirements.txt14
-rwxr-xr-xvio/run.sh17
-rwxr-xr-xvio/stop.sh3
-rw-r--r--vio/vio/api_v2/api_definition/images.yaml76
-rw-r--r--vio/vio/api_v2/api_definition/ports.yaml83
-rw-r--r--vio/vio/api_v2/api_router/controller_builder.py68
-rwxr-xr-xvio/vio/event_listener/server.py7
-rw-r--r--vio/vio/pub/config/config.py4
-rw-r--r--vio/vio/settings.py4
-rw-r--r--vio/vio/swagger/urls.py7
-rw-r--r--vio/vio/swagger/views/fakeplugin/fakeData/fakeResponse.py27
-rw-r--r--vio/vio/swagger/views/fakeplugin/image/views.py18
-rw-r--r--vio/vio/tests/test_aai_client.py169
-rw-r--r--vio/vio/tests/test_image_view.py93
-rw-r--r--vio/vio/tests/test_proxy_identity_view.py264
-rw-r--r--vio/vio/tests/test_restcall.py66
17 files changed, 880 insertions, 44 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
diff --git a/vio/run.sh b/vio/run.sh
index f3ba7a1..4b58fe5 100755
--- a/vio/run.sh
+++ b/vio/run.sh
@@ -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/api_v2/api_definition/images.yaml b/vio/vio/api_v2/api_definition/images.yaml
new file mode 100644
index 0000000..f2e4e72
--- /dev/null
+++ b/vio/vio/api_v2/api_definition/images.yaml
@@ -0,0 +1,76 @@
+---
+ info:
+ version: "1.0.0"
+ title: "Multi Cloud Image"
+ description: "Definition of Image API"
+ termsOfService: "http://swagger.io/terms/"
+ schemes:
+ - "http"
+ produces:
+ - "application/json"
+ paths:
+ /{vimid}/{tenantid}/images/{imageid}:
+ parameters:
+ - type: string
+ name: vimid
+ - type: string
+ format: uuid
+ name: tenantid
+ - type: string
+ name: imageid
+ in: path
+ required: true
+ get:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/image"
+ get_all:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ type: "array"
+ items:
+ $ref: "#/definitions/image"
+ post:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/image"
+ delete:
+ responses: "204"
+ vim_path: "/image/v2/images"
+ definitions:
+ image:
+ plural_vim_resource: "images"
+ vim_resource: "image"
+ plural: "images"
+ properties:
+ name:
+ type: string
+ required: true
+ source: image.name
+ id:
+ type: string
+ source: image.id
+ status:
+ type: string
+ source: image.status
+ imageType:
+ type: string
+ source: image.disk_format
+ containerFormat:
+ type: string
+ source: image.container_format
+ visibility:
+ type: string
+ source: image.visibility
+ size:
+ type: integer
+ source: image.size
diff --git a/vio/vio/api_v2/api_definition/ports.yaml b/vio/vio/api_v2/api_definition/ports.yaml
new file mode 100644
index 0000000..0599ae2
--- /dev/null
+++ b/vio/vio/api_v2/api_definition/ports.yaml
@@ -0,0 +1,83 @@
+---
+ info:
+ version: "1.0.0"
+ title: "Multi Cloud Port"
+ description: "Definition of Port API"
+ termsOfService: "http://swagger.io/terms/"
+ schemes:
+ - "http"
+ produces:
+ - "application/json"
+ paths:
+ /{vimid}/{tenantid}/ports/{portid}:
+ parameters:
+ - type: string
+ name: vimid
+ - type: string
+ format: uuid
+ name: tenantid
+ - type: string
+ name: portid
+ in: path
+ required: true
+ get:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/port"
+ get_all:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ type: "array"
+ items:
+ $ref: "#/definitions/port"
+ post:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/port"
+ delete:
+ responses: "204"
+ vim_path: "/network/v2.0/ports"
+ definitions:
+ port:
+ plural_vim_resource: "ports"
+ vim_resource: "port"
+ plural: "port"
+ properties:
+ name:
+ type: string
+ required: true
+ source: port.name
+ id:
+ type: string
+ source: port.id
+ status:
+ type: string
+ source: port.status
+ networkId:
+ type: string
+ source: port.network_id
+ required: true
+ vnicType:
+ source: port.binding:vnic_type
+ securityGroups:
+ type: string
+ source: port.security_groups
+ tenantId:
+ type: string
+ source: port.tenant_id
+ macAddress:
+ type: string
+ source: port.mac_address
+ subnetId:
+ source: port.fixed_ips[0].subnet_id
+ ip:
+ source: port.fixed_ips[0].ip_address
diff --git a/vio/vio/api_v2/api_router/controller_builder.py b/vio/vio/api_v2/api_router/controller_builder.py
index 9c01301..a3c70b2 100644
--- a/vio/vio/api_v2/api_router/controller_builder.py
+++ b/vio/vio/api_v2/api_router/controller_builder.py
@@ -16,12 +16,16 @@ from keystoneauth1.identity import v3 as keystone_v3
from keystoneauth1 import session
import pecan
from pecan import rest
+import re
from vio.api_v2.api_definition import utils
from vio.pub import exceptions
from vio.pub.msapi import extsys
+OBJ_IN_ARRAY = "(\w+)\[(\d+)\]\.(\w+)"
+
+
def _get_vim_auth_session(vim_id, tenant_id):
""" Get the auth session to backend VIM """
@@ -67,48 +71,56 @@ def _convert_default_value(default):
return default
+def _property_exists(resource, attr, required=False):
+ if attr not in resource:
+ if required:
+ raise Exception("Required field %s is missed in VIM "
+ "resource %s", (attr, resource))
+ else:
+ return False
+
+ return True
+
+
def _convert_vim_res_to_mc_res(vim_resource, res_properties):
mc_resource = {}
for key in res_properties:
- vim_res, attr = res_properties[key]["source"].split('.')
-
- if attr not in vim_resource[vim_res]:
- if res_properties[key].get("required"):
- raise Exception("Required field %s is missed in VIM "
- "resource %s", (attr, vim_resource))
+ vim_res, attr = res_properties[key]["source"].split('.', 1)
+ # action = res_properties[key].get("action", "copy")
+ if re.match(OBJ_IN_ARRAY, attr):
+ attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups()
+ if _property_exists(vim_resource[vim_res], attr):
+ mc_resource[key] = (
+ vim_resource[vim_res][attr][int(index)][sub_attr])
+ else:
+ if _property_exists(vim_resource[vim_res], attr,
+ res_properties[key].get("required")):
+ mc_resource[key] = vim_resource[vim_res][attr]
else:
if "default" in res_properties[key]:
mc_resource[key] = _convert_default_value(
res_properties[key]["default"])
- # None required fields missed, just skip.
- continue
-
- action = res_properties[key].get("action", "copy")
- # TODO(xiaohhui): Actions should be in constants.
- if action == "copy":
- mc_resource[key] = vim_resource[vim_res][attr]
-
return mc_resource
def _convert_mc_res_to_vim_res(mc_resource, res_properties):
vim_resource = {}
for key in res_properties:
- vim_res, attr = res_properties[key]["source"].split('.')
-
- if key not in mc_resource:
- if res_properties[key].get("required"):
- raise Exception("Required field %s is missed in MultiCloud "
- "resource %s", (key, mc_resource))
- else:
- # None required fields missed, just skip.
- continue
-
- action = res_properties[key].get("action", "copy")
- # TODO(xiaohhui): Actions should be in constants.
- if action == "copy":
- vim_resource[attr] = mc_resource[key]
+ vim_res, attr = res_properties[key]["source"].split('.', 1)
+ # action = res_properties[key].get("action", "copy")
+ if re.match(OBJ_IN_ARRAY, attr):
+ attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups()
+ if _property_exists(mc_resource, key):
+ vim_resource[attr] = vim_resource.get(attr, [])
+ if vim_resource[attr]:
+ vim_resource[attr][0].update({sub_attr: mc_resource[key]})
+ else:
+ vim_resource[attr].append({sub_attr: mc_resource[key]})
+ else:
+ if _property_exists(mc_resource, key,
+ res_properties[key].get("required")):
+ vim_resource[attr] = mc_resource[key]
return vim_resource
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_aai_client.py b/vio/vio/tests/test_aai_client.py
new file mode 100644
index 0000000..80d5200
--- /dev/null
+++ b/vio/vio/tests/test_aai_client.py
@@ -0,0 +1,169 @@
+# 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.utils import restcall
+
+
+class TestAAIClient(unittest.TestCase):
+
+ def setUp(self):
+ self.view = restcall.AAIClient("vmware", "4.0")
+
+ @mock.patch.object(restcall, "call_req")
+ def test_get_vim(self, mock_call):
+ mock_call.return_value = [0, '{"cloudOwner": "vmware"}']
+ ret = self.view.get_vim(get_all=True)
+ expect_ret = {"cloudOwner": "vmware"}
+ self.assertEqual(expect_ret, ret)
+
+ @mock.patch.object(restcall.AAIClient, "get_vim")
+ @mock.patch.object(restcall, "call_req")
+ def test_update_identity_url(self, mock_call, mock_getvim):
+ mock_getvim.return_value = {}
+ self.view.update_identity_url()
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_add_tenants(self, mock_call):
+ tenants = {"tenants": [{"name": "admin", "id": "admin-id"}]}
+ self.view.add_tenants(tenants)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_add_flavors(self, mock_call):
+ flavors = {
+ "flavors": [{
+ "name": "m1.small",
+ "id": "1",
+ "vcpus": 1,
+ "ram": 512,
+ "disk": 10,
+ "ephemeral": 0,
+ "swap": 0,
+ "is_public": True,
+ "links": [{"href": "http://fake-url"}],
+ "is_disabled": False
+ }]
+ }
+ self.view.add_flavors(flavors)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_add_images(self, mock_call):
+ images = {
+ "images": [{
+ "name": "ubuntu-16.04",
+ "id": "image-id"
+ }]
+ }
+ self.view.add_images(images)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_add_networks(self, mock_call):
+ networks = {
+ "networks": [{
+ "name": "net-1",
+ "id": "net-id",
+ "segmentationId": 144
+ }]
+ }
+ self.view.add_networks(networks)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_add_pservers(self, mock_call):
+ pservers = {
+ "hypervisors": [{
+ "name": "compute-1",
+ "vcpus": 100,
+ "local_disk_size": 1000,
+ "memory_size": 10240,
+ "host_ip": "10.0.0.7",
+ "id": "compute-1-id"
+ }]
+ }
+ self.view.add_pservers(pservers)
+ self.assertEqual(mock_call.call_count, 2)
+
+ @mock.patch.object(restcall, "call_req")
+ def test_del_tenants(self, mock_call):
+ mock_call.return_value = [0]
+ rsp = {
+ "tenants": {
+ "tenant": [{
+ "tenant-id": "tenant-id",
+ "resource-version": "version-1"
+ }]
+ }
+ }
+ self.view._del_tenants(rsp)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_del_flavors(self, mock_call):
+ mock_call.return_value = [0]
+ rsp = {
+ "flavors": {
+ "flavor": [{
+ "flavor-id": "fake-id",
+ "resource-version": "fake-version"
+ }]
+ }
+ }
+ self.view._del_flavors(rsp)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_del_images(self, mock_call):
+ mock_call.return_value = [0]
+ rsp = {
+ "images": {
+ "image": [{
+ "image-id": "fake-id",
+ "resource-version": "fake-version"
+ }]
+ }
+ }
+ self.view._del_images(rsp)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_del_networks(self, mock_call):
+ mock_call.return_value = [0]
+ rsp = {
+ "oam-networks": {
+ "oam-network": [{
+ "network-uuid": "fake-id",
+ "resource-version": "fake-version"
+ }]
+ }
+ }
+ self.view._del_networks(rsp)
+ mock_call.assert_called_once()
+
+ @mock.patch.object(restcall, "call_req")
+ def test_del_azs(self, mock_call):
+ mock_call.return_value = [0]
+ rsp = {
+ "availability-zones": {
+ "availability-zone": [{
+ "availability-zone-name": "fake-name",
+ "resource-version": "fake-version"
+ }]
+ }
+ }
+ self.view._del_azs(rsp)
+ mock_call.assert_called_once()
diff --git a/vio/vio/tests/test_image_view.py b/vio/vio/tests/test_image_view.py
new file mode 100644
index 0000000..112ee5a
--- /dev/null
+++ b/vio/vio/tests/test_image_view.py
@@ -0,0 +1,93 @@
+# 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.image import views
+from vio.pub.vim.vimapi.glance import OperateImage
+
+
+class TestGetDeleteImageView(unittest.TestCase):
+
+ def setUp(self):
+ self.view = views.GetDeleteImageView()
+
+ @mock.patch.object(OperateImage.OperateImage, "get_vim_image")
+ @mock.patch.object(extsys, "get_vim_by_id")
+ def test_get(self, mock_getvim, mock_getimg):
+ mock_getvim.return_value = {
+ "tenant": "tenant-id"
+ }
+ img = mock.Mock()
+ img.to_dict.return_value = {
+ "id": "image-id"
+ }
+ mock_getimg.return_value = img
+ resp = self.view.get(mock.Mock(), "vmware_nova", "tenant1", "image1")
+ self.assertEqual(200, resp.status_code)
+ self.assertEqual("image-id", resp.data.get('id'))
+
+ @mock.patch.object(OperateImage.OperateImage, "delete_vim_image")
+ @mock.patch.object(extsys, "get_vim_by_id")
+ def test_delete(self, mock_getvim, mock_delimg):
+ mock_getvim.return_value = {
+ "tenant": "tenant-id"
+ }
+ resp = self.view.delete(
+ mock.Mock(), "vmware_nova", "tenant1", "image1")
+ self.assertEqual(204, resp.status_code)
+ mock_delimg.assert_called_once()
+
+
+class TestCreateListImagesView(unittest.TestCase):
+
+ def setUp(self):
+ self.view = views.CreateListImagesView()
+
+ @mock.patch.object(OperateImage.OperateImage, "get_vim_images")
+ @mock.patch.object(extsys, "get_vim_by_id")
+ def test_get(self, mock_getvim, mock_getimgs):
+ mock_getvim.return_value = {
+ "tenant": "tenant-id"
+ }
+ img = mock.Mock()
+ img.to_dict.return_value = {
+ "id": "image-id"
+ }
+ mock_getimgs.return_value = [img]
+ resp = self.view.get(
+ mock.Mock(query_params=[]), "vmware_nova", "tenant1")
+ self.assertEqual(200, resp.status_code)
+
+ @mock.patch.object(OperateImage.OperateImage, "get_vim_image")
+ @mock.patch.object(OperateImage.OperateImage, "get_vim_images")
+ @mock.patch.object(extsys, "get_vim_by_id")
+ def test_post(self, mock_getvim, mock_getimgs, mock_getimg):
+ mock_getvim.return_value = {
+ "tenant": "tenant-id"
+ }
+ img = mock.Mock()
+ img.id = "image-id"
+ img.name = "image-a"
+ img.to_dict.return_value = {
+ "id": "image-id",
+ "name": "image-a"
+ }
+ mock_getimgs.return_value = [img]
+ req = mock.Mock()
+ req.body = """{
+ "name": "image-a"
+ }"""
+ resp = self.view.post(req, "vmware_nova", "tenant1")
+ self.assertEqual(200, resp.status_code)
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)