From 0d3e9ace323660381350a884b08ed92aa2290dbd Mon Sep 17 00:00:00 2001 From: Huang Haibin Date: Tue, 10 Jul 2018 19:22:34 +0800 Subject: Add Openstack Pike plugin framework Add Pike framework and one function extension Add Vagrant for test Change-Id: I045ac1f1a920b509a69d7a72f8e60fb108102839 Issue-ID: MULTICLOUD-276 Signed-off-by: Huang Haibin --- pike/.gitignore | 13 +++ pike/README.md | 15 +++ pike/assembly.xml | 77 ++++++++++++++ pike/docker/Dockerfile | 29 ++++++ pike/docker/build_image.sh | 31 ++++++ pike/initialize.sh | 16 +++ pike/logs/empty.txt | 0 pike/manage.py | 22 ++++ pike/mvn-phase-script.sh | 83 +++++++++++++++ pike/pike/__init__.py | 14 +++ pike/pike/extensions/__init__.py | 14 +++ pike/pike/extensions/tests/__init__.py | 14 +++ pike/pike/extensions/tests/test_epacaps.py | 67 ++++++++++++ pike/pike/extensions/tests/test_extensions.py | 45 ++++++++ pike/pike/extensions/urls.py | 26 +++++ pike/pike/extensions/views/__init__.py | 14 +++ pike/pike/extensions/views/epacaps.py | 33 ++++++ pike/pike/extensions/views/extensions.py | 29 ++++++ pike/pike/middleware.py | 65 ++++++++++++ pike/pike/pub/__init__.py | 14 +++ pike/pike/pub/config/__init__.py | 14 +++ pike/pike/pub/config/config.py | 13 +++ pike/pike/pub/config/log.yml | 37 +++++++ pike/pike/samples/__init__.py | 14 +++ pike/pike/samples/tests.py | 32 ++++++ pike/pike/samples/urls.py | 19 ++++ pike/pike/samples/views.py | 29 ++++++ pike/pike/settings.py | 138 ++++++++++++++++++++++++ pike/pike/swagger/__init__.py | 14 +++ pike/pike/swagger/tests.py | 32 ++++++ pike/pike/swagger/urls.py | 24 +++++ pike/pike/swagger/views.py | 48 +++++++++ pike/pike/urls.py | 26 +++++ pike/pike/wsgi.py | 21 ++++ pike/pom.xml | 117 +++++++++++++++++++++ pike/requirements.txt | 23 ++++ pike/run.sh | 18 ++++ pike/stop.sh | 18 ++++ pike/tox.ini | 27 +++++ pike/vagrant/Vagrantfile | 23 ++++ pike/vagrant/pip.conf | 4 + pike/vagrant/piprepo.sh | 7 ++ pike/vagrant/test/Dockerfile | 25 +++++ pike/vagrant/test/extsys.py | 145 ++++++++++++++++++++++++++ pike/vagrant/test/test-extensions.sh | 6 ++ pike/vagrant/test/test_multicloud.sh | 29 ++++++ pike/vagrant/test/tests | 1 + 47 files changed, 1525 insertions(+) create mode 100644 pike/.gitignore create mode 100644 pike/README.md create mode 100644 pike/assembly.xml create mode 100644 pike/docker/Dockerfile create mode 100755 pike/docker/build_image.sh create mode 100755 pike/initialize.sh create mode 100644 pike/logs/empty.txt create mode 100644 pike/manage.py create mode 100755 pike/mvn-phase-script.sh create mode 100644 pike/pike/__init__.py create mode 100644 pike/pike/extensions/__init__.py create mode 100644 pike/pike/extensions/tests/__init__.py create mode 100644 pike/pike/extensions/tests/test_epacaps.py create mode 100644 pike/pike/extensions/tests/test_extensions.py create mode 100644 pike/pike/extensions/urls.py create mode 100644 pike/pike/extensions/views/__init__.py create mode 100644 pike/pike/extensions/views/epacaps.py create mode 100644 pike/pike/extensions/views/extensions.py create mode 100644 pike/pike/middleware.py create mode 100644 pike/pike/pub/__init__.py create mode 100644 pike/pike/pub/config/__init__.py create mode 100644 pike/pike/pub/config/config.py create mode 100644 pike/pike/pub/config/log.yml create mode 100644 pike/pike/samples/__init__.py create mode 100644 pike/pike/samples/tests.py create mode 100644 pike/pike/samples/urls.py create mode 100644 pike/pike/samples/views.py create mode 100644 pike/pike/settings.py create mode 100644 pike/pike/swagger/__init__.py create mode 100644 pike/pike/swagger/tests.py create mode 100644 pike/pike/swagger/urls.py create mode 100644 pike/pike/swagger/views.py create mode 100644 pike/pike/urls.py create mode 100644 pike/pike/wsgi.py create mode 100644 pike/pom.xml create mode 100644 pike/requirements.txt create mode 100755 pike/run.sh create mode 100755 pike/stop.sh create mode 100644 pike/tox.ini create mode 100644 pike/vagrant/Vagrantfile create mode 100644 pike/vagrant/pip.conf create mode 100755 pike/vagrant/piprepo.sh create mode 100644 pike/vagrant/test/Dockerfile create mode 100644 pike/vagrant/test/extsys.py create mode 100644 pike/vagrant/test/test-extensions.sh create mode 100644 pike/vagrant/test/test_multicloud.sh create mode 100644 pike/vagrant/test/tests (limited to 'pike') diff --git a/pike/.gitignore b/pike/.gitignore new file mode 100644 index 00000000..06570027 --- /dev/null +++ b/pike/.gitignore @@ -0,0 +1,13 @@ +.project +.classpath +.settings/ +.checkstyle +target/ +logs/*.log +*.pyc +.tox +.coverage +htmlcov/ +coverage.xml +test-reports/ + diff --git a/pike/README.md b/pike/README.md new file mode 100644 index 00000000..e6231224 --- /dev/null +++ b/pike/README.md @@ -0,0 +1,15 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Micro service of MultiCloud plugin for pike. diff --git a/pike/assembly.xml b/pike/assembly.xml new file mode 100644 index 00000000..420c6c49 --- /dev/null +++ b/pike/assembly.xml @@ -0,0 +1,77 @@ + + + pike + + zip + + + + pike + /pike + + **/*.py + **/*.json + **/*.xml + **/*.wsdl + **/*.xsd + **/*.bpel + **/*.yml + + + + ../share + /lib/share + + **/*.py + **/*.json + **/*.xml + **/*.wsdl + **/*.xsd + **/*.bpel + + + + logs + /logs + + *.txt + + + + docker + /docker + + *.sh + Dockerfile + + + + . + / + + *.py + *.txt + *.sh + *.ini + *.md + + + + pike + diff --git a/pike/docker/Dockerfile b/pike/docker/Dockerfile new file mode 100644 index 00000000..45e99502 --- /dev/null +++ b/pike/docker/Dockerfile @@ -0,0 +1,29 @@ +FROM python:2.7 + +ARG HTTP_PROXY=${HTTP_PROXY} +ARG HTTPS_PROXY=${HTTPS_PROXY} + +ENV http_proxy $HTTP_PROXY +ENV https_proxy $HTTPS_PROXY + +ENV MSB_ADDR "127.0.0.1" +ENV MSB_PORT "80" +ENV AAI_ADDR "aai.api.simpledemo.openecomp.org" +ENV AAI_PORT "8443" +ENV AAI_SERVICE_URL "" +ENV AAI_SCHEMA_VERSION "v13" +ENV AAI_USERNAME "AAI" +ENV AAI_PASSWORD "AAI" + +EXPOSE 9007 + +WORKDIR /opt/pike +RUN apt-get update && apt-get install -y memcached unzip +RUN wget -O /opt/multicloud-openstack-pike.zip "https://nexus.onap.org/service/local/artifact/maven/redirect?r=snapshots&g=org.onap.multicloud.openstack&a=multicloud-openstack-pike&e=zip&v=LATEST" && \ + unzip -q -o -B /opt/multicloud-openstack-pike.zip -d /opt/ && \ + rm -f /opt/multicloud-openstack-pike.zip +RUN mkdir -p /var/log/onap/multicloud/openstack/pike/ +#COPY ./ . +RUN pip install -r requirements.txt + +CMD "/opt/pike/run.sh" diff --git a/pike/docker/build_image.sh b/pike/docker/build_image.sh new file mode 100755 index 00000000..83340be5 --- /dev/null +++ b/pike/docker/build_image.sh @@ -0,0 +1,31 @@ +#!/bin/bash +DIRNAME=`dirname $0` +DOCKER_BUILD_DIR=`cd $DIRNAME/; pwd` +echo "DOCKER_BUILD_DIR=${DOCKER_BUILD_DIR}" +cd ${DOCKER_BUILD_DIR} + +BUILD_ARGS="--no-cache" +VERSION="1.2.0-SNAPSHOT" +STAGING="1.2.0-STAGING" +OS_VERSION="pike" +IMAGE_NAME="nexus3.onap.org:10003/onap/multicloud/openstack-${OS_VERSION}" + +if [ $HTTP_PROXY ]; then + BUILD_ARGS+=" --build-arg HTTP_PROXY=${HTTP_PROXY}" +fi +if [ $HTTPS_PROXY ]; then + BUILD_ARGS+=" --build-arg HTTPS_PROXY=${HTTPS_PROXY}" +fi + +function build_image { + docker build ${BUILD_ARGS} -t ${IMAGE_NAME}:${VERSION} -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:${STAGING} . +} + +function push_image { + docker push ${IMAGE_NAME}:${VERSION} + docker push ${IMAGE_NAME}:latest + docker push ${IMAGE_NAME}:${STAGING} +} + +build_image +push_image diff --git a/pike/initialize.sh b/pike/initialize.sh new file mode 100755 index 00000000..1d64bfca --- /dev/null +++ b/pike/initialize.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +pip install -r requirements.txt diff --git a/pike/logs/empty.txt b/pike/logs/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/pike/manage.py b/pike/manage.py new file mode 100644 index 00000000..426c6b19 --- /dev/null +++ b/pike/manage.py @@ -0,0 +1,22 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pike.settings") + +if __name__ == "__main__": + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/pike/mvn-phase-script.sh b/pike/mvn-phase-script.sh new file mode 100755 index 00000000..ad1d6329 --- /dev/null +++ b/pike/mvn-phase-script.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + + +set -e + +echo "running script: [$0] for module [$1] at stage [$2]" + +export SETTINGS_FILE=${SETTINGS_FILE:-$HOME/.m2/settings.xml} +MVN_PROJECT_MODULEID="$1" +MVN_PHASE="$2" + + +FQDN="${MVN_PROJECT_GROUPID}.${MVN_PROJECT_ARTIFACTID}" +if [ "$MVN_PROJECT_MODULEID" == "__" ]; then + MVN_PROJECT_MODULEID="" +fi + +if [ -z "$WORKSPACE" ]; then + WORKSPACE=$(pwd) +fi + +# mvn phase in life cycle +MVN_PHASE="$2" + + +echo "MVN_PROJECT_MODULEID is [$MVN_PROJECT_MODULEID]" +echo "MVN_PHASE is [$MVN_PHASE]" +echo "MVN_PROJECT_GROUPID is [$MVN_PROJECT_GROUPID]" +echo "MVN_PROJECT_ARTIFACTID is [$MVN_PROJECT_ARTIFACTID]" +echo "MVN_PROJECT_VERSION is [$MVN_PROJECT_VERSION]" + +run_tox_test() +{ + set -x + echo $PWD + CURDIR=$(pwd) + TOXINIS=$(find . -name "tox.ini") + cd .. + for TOXINI in "${TOXINIS[@]}"; do + DIR=$(echo "$TOXINI" | rev | cut -f2- -d'/' | rev) + cd "${CURDIR}/${DIR}" + rm -rf ./venv-tox ./.tox + virtualenv ./venv-tox + source ./venv-tox/bin/activate + pip install --upgrade pip + pip install --upgrade tox argparse + pip freeze + cd ${CURDIR} + tox + deactivate + cd .. + rm -rf ./venv-tox ./.tox + done +} + + +case $MVN_PHASE in +clean) + echo "==> clean phase script" + rm -rf ./venv-* + ;; +test) + echo "==> test phase script" + run_tox_test + ;; +*) + echo "==> unprocessed phase" + ;; +esac + diff --git a/pike/pike/__init__.py b/pike/pike/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/extensions/__init__.py b/pike/pike/extensions/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/extensions/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/extensions/tests/__init__.py b/pike/pike/extensions/tests/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/extensions/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/extensions/tests/test_epacaps.py b/pike/pike/extensions/tests/test_epacaps.py new file mode 100644 index 00000000..40f8d3a7 --- /dev/null +++ b/pike/pike/extensions/tests/test_epacaps.py @@ -0,0 +1,67 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json + +import mock +from django.test import Client +from rest_framework import status +import unittest + +from newton_base.util import VimDriverUtils + +MOCK_VIM_INFO = { + "createTime": "2017-04-01 02:22:27", + "domain": "Default", + "name": "TiS_R4", + "password": "admin", + "tenant": "admin", + "type": "openstack", + "url": "http://128.224.180.14:5000/v3", + "userName": "admin", + "vendor": "WindRiver", + "version": "pike", + "vimId": "windriver-hudson-dc_RegionOne", + 'cloud_owner':'windriver-hudson-dc', + 'cloud_region_id':'RegionOne', + 'cloud_extra_info':'', + 'cloud_epa_caps':'{"huge_page":"true","cpu_pinning":"true",\ + "cpu_thread_policy":"true","numa_aware":"true","sriov":"true",\ + "dpdk_vswitch":"true","rdt":"false","numa_locality_pci":"true"}', + 'insecure':'True', +} + + +class TestEpaCaps(unittest.TestCase): + def setUp(self): + self.client = Client() + + @mock.patch.object(VimDriverUtils, 'get_vim_info') + def test_get_epa_caps_info(self, mock_get_vim_info): + mock_get_vim_info.return_value = MOCK_VIM_INFO + cloud_owner = "windriver-hudson-dc" + cloud_region_id = "RegionOne" + vimid = cloud_owner + "_" + cloud_region_id + + response = self.client.get( + "/api/multicloud-pike/v0/" + vimid + "/extensions/epa-caps") + json_content = response.json() + + self.assertEquals(status.HTTP_200_OK, response.status_code) + self.assertEquals(4, len(json_content.keys())) + self.assertEquals(cloud_owner, json_content["cloud-owner"]) + self.assertEquals(cloud_region_id, json_content["cloud-region-id"]) + self.assertEquals(vimid, json_content["vimid"]) + self.assertEquals(json.loads(MOCK_VIM_INFO['cloud_epa_caps']), + json_content["cloud-epa-caps"]) diff --git a/pike/pike/extensions/tests/test_extensions.py b/pike/pike/extensions/tests/test_extensions.py new file mode 100644 index 00000000..3842d4b7 --- /dev/null +++ b/pike/pike/extensions/tests/test_extensions.py @@ -0,0 +1,45 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.test import Client +from rest_framework import status +import unittest + + +class TestExtensions(unittest.TestCase): + def setUp(self): + self.client = Client() + + def test_get_extensions_info(self): + cloud_owner = "windriver-hudson-dc" + cloud_region_id = "RegionOne" + vimid = cloud_owner + "_" + cloud_region_id + + response = self.client.get( + "/api/multicloud-pike/v0/" + vimid + "/extensions/") + json_content = response.json() + + self.assertEquals(status.HTTP_200_OK, response.status_code) + self.assertEquals(4, len(json_content.keys())) + + self.assertEquals(cloud_owner, json_content["cloud-owner"]) + self.assertEquals(cloud_region_id, json_content["cloud-region-id"]) + self.assertEquals(vimid, json_content["vimid"]) + + self.assertEquals("epa-caps", json_content["extensions"][0]["alias"]) + self.assertEquals("Multiple network support", json_content["extensions"][0]["description"]) + self.assertEquals("EPACapsQuery", json_content["extensions"][0]["name"]) + self.assertEquals("http://127.0.0.1:80/api/multicloud-pike/v0/%s/extensions/epa-caps" % vimid, + json_content["extensions"][0]["url"]) + self.assertEquals("", json_content["extensions"][0]["spec"]) diff --git a/pike/pike/extensions/urls.py b/pike/pike/extensions/urls.py new file mode 100644 index 00000000..545dec98 --- /dev/null +++ b/pike/pike/extensions/urls.py @@ -0,0 +1,26 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns + +from pike.extensions.views import extensions +from pike.extensions.views import epacaps + +urlpatterns = [ + url(r'^sions/?$', extensions.Extensions.as_view()), + url(r'^sions/epa-caps/?$', epacaps.EpaCaps.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/pike/pike/extensions/views/__init__.py b/pike/pike/extensions/views/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/extensions/views/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/extensions/views/epacaps.py b/pike/pike/extensions/views/epacaps.py new file mode 100644 index 00000000..025d55df --- /dev/null +++ b/pike/pike/extensions/views/epacaps.py @@ -0,0 +1,33 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import json +import traceback + +from django.conf import settings + + +from newton_base.extensions import epacaps as newton_epacaps + +logger = logging.getLogger(__name__) + +# DEBUG=True + + +class EpaCaps(newton_epacaps.EpaCaps): + + def __init__(self): + self.proxy_prefix = settings.MULTICLOUD_PREFIX + self._logger = logger diff --git a/pike/pike/extensions/views/extensions.py b/pike/pike/extensions/views/extensions.py new file mode 100644 index 00000000..2c499f36 --- /dev/null +++ b/pike/pike/extensions/views/extensions.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from django.conf import settings +from newton_base.extensions import extensions as newton_extensions + +logger = logging.getLogger(__name__) + +# DEBUG=True + +class Extensions(newton_extensions.Extensions): + + def __init__(self): + self._logger = logger + self.proxy_prefix = settings.MULTICLOUD_PREFIX + diff --git a/pike/pike/middleware.py b/pike/pike/middleware.py new file mode 100644 index 00000000..f2618e06 --- /dev/null +++ b/pike/pike/middleware.py @@ -0,0 +1,65 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import uuid +from django.conf import settings +from onaplogging.mdcContext import MDC + +FORWARDED_FOR_FIELDS = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST", + "HTTP_X_FORWARDED_SERVER"] + +class LogContextMiddleware(object): + + # the last IP behind multiple proxies, if no exist proxies + # get local host ip. + def _getLastIp(self, request): + + ip = "" + try: + for field in FORWARDED_FOR_FIELDS: + if field in request.META: + if ',' in request.META[field]: + parts = request.META[field].split(',') + ip = parts[-1].strip().split(":")[0] + else: + ip = request.META[field].split(":")[0] + + if ip == "": + ip = request.META.get("HTTP_HOST").split(":")[0] + + except Exception: + pass + + return ip + + + def process_request(self, request): + # fetch propageted Id from other component. if do not fetch id, + # generate one. + ReqeustID = request.META.get("HTTP_X_TRANSACTIONID", None) + if ReqeustID is None: + ReqeustID = str(uuid.uuid3(uuid.NAMESPACE_URL, settings.MULTIVIM_VERSION)) + MDC.put("requestID", ReqeustID) + # generate the reqeust id + InvocationID = str(uuid.uuid4()) + MDC.put("invocationID", InvocationID) + MDC.put("serviceName", settings.MULTIVIM_VERSION) + MDC.put("serviceIP", self._getLastIp(request)) + return None + + def process_response(self, request, response): + + MDC.clear() + return response + diff --git a/pike/pike/pub/__init__.py b/pike/pike/pub/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/pub/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/pub/config/__init__.py b/pike/pike/pub/config/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/pub/config/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/pub/config/config.py b/pike/pike/pub/config/config.py new file mode 100644 index 00000000..ae1ce9db --- /dev/null +++ b/pike/pike/pub/config/config.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/pike/pike/pub/config/log.yml b/pike/pike/pub/config/log.yml new file mode 100644 index 00000000..73a14eef --- /dev/null +++ b/pike/pike/pub/config/log.yml @@ -0,0 +1,37 @@ +version: 1 +disable_existing_loggers: False + +loggers: + pike: + handlers: [console_handler, file_handler] + level: "DEBUG" + propagate: False + newton_base: + handlers: [console_handler, file_handler] + level: "DEBUG" + propagate: False + common: + handlers: [console_handler, file_handler] + level: "DEBUG" + propagate: False +handlers: + console_handler: + level: "DEBUG" + class: "logging.StreamHandler" + formatter: "mdcFormat" + file_handler: + level: "DEBUG" + class: "logging.handlers.RotatingFileHandler" + filename: "/var/log/onap/multicloud/openstack/pike/pike.log" + formatter: "mdcFormat" + maxBytes: 1024*1024*50 + backupCount: 10 +formatters: + standard: + format: "%(asctime)s|||||%(name)s||%(thread)||%(funcName)s||%(levelname)s||%(message)s" + mdcFormat: + format: "%(asctime)s|||||%(name)s||%(thread)s||%(funcName)s||%(levelname)s||%(message)s||||%(mdc)s \t" + mdcfmt: "{requestID} {invocationID} {serviceName} {serviceIP}" + datefmt: "%Y-%m-%d %H:%M:%S" + (): onaplogging.mdcformatter.MDCFormatter + diff --git a/pike/pike/samples/__init__.py b/pike/pike/samples/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/samples/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/samples/tests.py b/pike/pike/samples/tests.py new file mode 100644 index 00000000..b294a52b --- /dev/null +++ b/pike/pike/samples/tests.py @@ -0,0 +1,32 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import json +from django.test import Client +from rest_framework import status + + +class SampleViewTest(unittest.TestCase): + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_sample(self): + response = self.client.get("/samples/") + self.assertEqual(status.HTTP_200_OK, response.status_code, response.content) + resp_data = response.json() + self.assertEqual({"status": "active"}, resp_data) diff --git a/pike/pike/samples/urls.py b/pike/pike/samples/urls.py new file mode 100644 index 00000000..94bd5669 --- /dev/null +++ b/pike/pike/samples/urls.py @@ -0,0 +1,19 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf.urls import url +from pike.samples import views + +urlpatterns = [ + url(r'^samples/$', views.SampleList.as_view()), ] diff --git a/pike/pike/samples/views.py b/pike/pike/samples/views.py new file mode 100644 index 00000000..58d1d80b --- /dev/null +++ b/pike/pike/samples/views.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from rest_framework.views import APIView +from rest_framework.response import Response + +logger = logging.getLogger(__name__) + + +class SampleList(APIView): + """ + List all samples. + """ + def get(self, request, format=None): + logger.debug("get") + return Response({"status": "active"}) diff --git a/pike/pike/settings.py b/pike/pike/settings.py new file mode 100644 index 00000000..39c83d47 --- /dev/null +++ b/pike/pike/settings.py @@ -0,0 +1,138 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys + +from logging import config +from onaplogging import monkey +monkey.patch_all() + +CACHE_EXPIRATION_TIME = 3600 + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '3o-wney!99y)^h3v)0$j16l9=fdjxcb+a8g+q3tfbahcnu2b0o' + +# SECURITY WARNING: don't run with debug turned on in production! +# DEBUG = True + +ALLOWED_HOSTS = ['*'] + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', +] + +MIDDLEWARE_CLASSES = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'pike.middleware.LogContextMiddleware', +] + +ROOT_URLCONF = 'pike.urls' + +WSGI_APPLICATION = 'pike.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_RENDERER_CLASSES': ( + 'rest_framework.renderers.JSONRenderer', + ), + + 'DEFAULT_PARSER_CLASSES': ( + 'rest_framework.parsers.JSONParser', + 'rest_framework.parsers.MultiPartParser', + # 'rest_framework.parsers.FormParser', + # 'rest_framework.parsers.FileUploadParser', + ) +} + +TIME_ZONE = 'UTC' + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.6/howto/static-files/ + +STATIC_URL = '/static/' + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + } +} + +# [MSB] +MSB_SERVICE_ADDR = os.environ.get('MSB_ADDR', "127.0.0.1") +MSB_SERVICE_PORT = os.environ.get('MSB_PORT', "80") + +#[Multicloud] +MULTICLOUD_PREFIX = "http://%s:%s/api/multicloud-pike/v0" % ( + MSB_SERVICE_ADDR, MSB_SERVICE_PORT) + +# [A&AI] +AAI_ADDR = os.environ.get('AAI_ADDR', "aai.api.simpledemo.openecomp.org") +AAI_PORT = os.environ.get('AAI_PORT', "8443") + +AAI_SERVICE_URL = os.environ.get('AAI_SERVICE_URL', "") +if AAI_SERVICE_URL == "": + AAI_SERVICE_URL = 'https://%s:%s/aai' % (AAI_ADDR, AAI_PORT) + +AAI_SCHEMA_VERSION = os.environ.get('AAI_SCHEMA_VERSION', "v13") +AAI_USERNAME = os.environ.get('AAI_USERNAME', "AAI") +AAI_PASSWORD = os.environ.get('AAI_PASSWORD', "AAI") + +AAI_BASE_URL = "%s/%s" % (AAI_SERVICE_URL, AAI_SCHEMA_VERSION) + +MULTICLOUD_APP_ID = 'MultiCloud-Pike' + +# [IMAGE LOCAL PATH] +ROOT_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +OPENSTACK_VERSION = "pike" +MULTIVIM_VERSION = "multicloud-" + OPENSTACK_VERSION + +LOGGING_CONFIG = None +# yaml configuration of logging +LOGGING_FILE = os.path.join(BASE_DIR, 'pike/pub/config/log.yml') +config.yamlConfig(filepath=LOGGING_FILE, watchDog=True) + +if 'test' in sys.argv: + + #LOGGING['handlers']['pike_handler']['filename'] = 'logs/pike.log' + + REST_FRAMEWORK = {} + import platform + + if platform.system() == 'Linux': + TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' + TEST_OUTPUT_VERBOSE = True + TEST_OUTPUT_DESCRIPTIONS = True + TEST_OUTPUT_DIR = 'test-reports' diff --git a/pike/pike/swagger/__init__.py b/pike/pike/swagger/__init__.py new file mode 100644 index 00000000..afa702d3 --- /dev/null +++ b/pike/pike/swagger/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/pike/pike/swagger/tests.py b/pike/pike/swagger/tests.py new file mode 100644 index 00000000..fe1b81c8 --- /dev/null +++ b/pike/pike/swagger/tests.py @@ -0,0 +1,32 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import json +from django.test import Client +from rest_framework import status + + +class SampleViewTest(unittest.TestCase): + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_sample(self): + response = self.client.get("/api/multicloud-pike/v0/swagger.json") + self.assertEqual(status.HTTP_200_OK, response.status_code, response.content) +# resp_data = response.json() +# self.assertEqual({"status": "active"}, resp_data) diff --git a/pike/pike/swagger/urls.py b/pike/pike/swagger/urls.py new file mode 100644 index 00000000..c06f7b49 --- /dev/null +++ b/pike/pike/swagger/urls.py @@ -0,0 +1,24 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf.urls import patterns, url +from rest_framework.urlpatterns import format_suffix_patterns + +from pike.swagger.views import SwaggerJsonView + +urlpatterns = [ + url(r'^api/multicloud-pike/v0/swagger.json$', SwaggerJsonView.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/pike/pike/swagger/views.py b/pike/pike/swagger/views.py new file mode 100644 index 00000000..ddf34731 --- /dev/null +++ b/pike/pike/swagger/views.py @@ -0,0 +1,48 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import os +import traceback + +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView + +from common.exceptions import VimDriverNewtonException +from newton_base.swagger import views as newton_json_view + +logger = logging.getLogger(__name__) + + +class SwaggerJsonView(newton_json_view.SwaggerJsonView): + + def get(self, request): + ''' + reuse newton code and update the basePath + :param request: + :return: + ''' + + resp = super(SwaggerJsonView,self).get(request) + json_data = resp.data if resp else None + if json_data: + json_data["basePath"] = "/api/multicloud-pike/v0/" + json_data["info"]["title"] = "Service NBI of MultiCloud plugin for OpenStack Pike" + return Response(data=json_data, status=200) + else: + return Response(data={'error':'internal error'}, status=500) + + diff --git a/pike/pike/urls.py b/pike/pike/urls.py new file mode 100644 index 00000000..6ff32d91 --- /dev/null +++ b/pike/pike/urls.py @@ -0,0 +1,26 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf.urls import include, url + +from newton_base.openoapi import tenants + +urlpatterns = [ + url(r'^', include('pike.swagger.urls')), + url(r'^', include('pike.samples.urls')), + url(r'^api/multicloud-pike/v0/(?P[0-9a-zA-Z_-]+)/exten', + include('pike.extensions.urls')), +] + + diff --git a/pike/pike/wsgi.py b/pike/pike/wsgi.py new file mode 100644 index 00000000..ebe63812 --- /dev/null +++ b/pike/pike/wsgi.py @@ -0,0 +1,21 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pike.settings") + +application = get_wsgi_application() diff --git a/pike/pom.xml b/pike/pom.xml new file mode 100644 index 00000000..05869654 --- /dev/null +++ b/pike/pom.xml @@ -0,0 +1,117 @@ + + + + + org.onap.oparent + oparent + 1.1.0 + ../oparent + + 4.0.0 + org.onap.multicloud.openstack + multicloud-openstack-pike + 1.2.0-SNAPSHOT + pom + multicloud/openstack/pike + multicloud for openstack pike + + UTF-8 + UTF-8 + UTF-8 + https://nexus.onap.org + . + xunit-results.xml + coverage.xml + py + Python + **/*.py + **/venv-tox/**,**/.tox/**, **/tests/**,setup.py + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + ${project.basedir}/mvn-phase-script.sh + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + clean phase script + clean + + exec + + + + __ + clean + + + + + test script + test + + exec + + + + __ + test + + + + + + + maven-assembly-plugin + + false + + assembly.xml + + + + + make-assembly + package + + single + + + + + + + diff --git a/pike/requirements.txt b/pike/requirements.txt new file mode 100644 index 00000000..d9e87f87 --- /dev/null +++ b/pike/requirements.txt @@ -0,0 +1,23 @@ +# rest framework +Django==1.9.6 +djangorestframework==3.3.3 + +# for call rest api +httplib2==0.9.2 + +# for call openstack auth and transport api +keystoneauth1==2.18.0 + +#python-memcached +python-memcached + +#uwsgi for parallel processing +uwsgi + +# for unit test +coverage==4.2 +mock==2.0.0 +unittest_xml_reporting==1.12.0 + +# for onap logging +onappylog>=1.0.6 diff --git a/pike/run.sh b/pike/run.sh new file mode 100755 index 00000000..e3df3b3c --- /dev/null +++ b/pike/run.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +memcached -d -m 2048 -u root -c 1024 -p 11211 -P /tmp/memcached1.pid +export PYTHONPATH=lib/share +uwsgi --http :9007 --module pike.wsgi --master --processes 4 diff --git a/pike/stop.sh b/pike/stop.sh new file mode 100755 index 00000000..9e433eb4 --- /dev/null +++ b/pike/stop.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +#ps auxww | grep 'manage.py runserver 0.0.0.0:9007' | awk '{print $2}' | xargs kill -9 +ps auxww |grep 'uwsgi --http :9007 --module pike.wsgi --master' |awk '{print $2}' |xargs kill -9 +ps auxww | grep 'memcached -d -m 2048 -u root -c 1024 -p 11211 -P /tmp/memcached1.pid' | awk '{print $2}' | xargs kill -9 diff --git a/pike/tox.ini b/pike/tox.ini new file mode 100644 index 00000000..20a7f6cc --- /dev/null +++ b/pike/tox.ini @@ -0,0 +1,27 @@ +[tox] +envlist = py27,cov +skipsdist = true + +[tox:jenkins] +downloadcache = ~/cache/pip + +[flake8] +ignore = E501,E722 +exclude = ./venv-tox,./.tox +max-complexity = 27 + +[testenv] +setenv = + PYTHONPATH = {toxinidir}/../share +deps = -r{toxinidir}/requirements.txt +commands = + coverage run --branch manage.py test pike + coverage report --omit="./venv-tox/*,./.tox/*,*tests*,*__init__.py,*newton_base*,*common*" --fail-under=30 + +[testenv:pep8] +deps=flake8 +commands=flake8 + +[testenv:cov] +commands = coverage xml --omit="./venv-tox/*,./.tox/*,*tests*,*__init__.py,*newton_base*,*common*, *site-packages*" + diff --git a/pike/vagrant/Vagrantfile b/pike/vagrant/Vagrantfile new file mode 100644 index 00000000..666f307b --- /dev/null +++ b/pike/vagrant/Vagrantfile @@ -0,0 +1,23 @@ +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! + +Vagrant.configure("2") do |config| + + config.vm.box = "bento/ubuntu-16.04" + + config.vm.provider :virtualbox do |vb| + vb.customize ["modifyvm", :id, "--memory", 9192] + vb.customize ["modifyvm", :id, "--cpus", 4] + vb.customize ["modifyvm", :id, "--nicpromisc3", "allow-all"] + vb.customize "post-boot",["controlvm", :id, "setlinkstate1", "on"] + end + + config.vm.define "onap" do |config| + config.vm.hostname = "onap" + config.vm.synced_folder "../..", "/openstack" + config.vm.network "private_network", ip: "192.168.0.30" + config.vm.network :private_network, ip: "192.168.1.30" + config.vm.provision "shell", path: "piprepo.sh", privileged: false + config.vm.provision "shell", path: "test/test_multicloud.sh", privileged: false + end + +end diff --git a/pike/vagrant/pip.conf b/pike/vagrant/pip.conf new file mode 100644 index 00000000..73e7f4c4 --- /dev/null +++ b/pike/vagrant/pip.conf @@ -0,0 +1,4 @@ +[global] +index-url = https://pypi.douban.com/simple/ +[install] +trusted-host = pypi.douban.com diff --git a/pike/vagrant/piprepo.sh b/pike/vagrant/piprepo.sh new file mode 100755 index 00000000..737ad4f3 --- /dev/null +++ b/pike/vagrant/piprepo.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -ex + +mkdir -p ~/.pip +cp /vagrant/pip.conf ~/.pip/ +sudo cp /vagrant/pip.conf /etc/pip.conf diff --git a/pike/vagrant/test/Dockerfile b/pike/vagrant/test/Dockerfile new file mode 100644 index 00000000..00f8250c --- /dev/null +++ b/pike/vagrant/test/Dockerfile @@ -0,0 +1,25 @@ +FROM python:2 + +ENV MSB_ADDR "127.0.0.1" +ENV MSB_PORT "80" +ENV AAI_ADDR "aai.api.simpledemo.openecomp.org" +ENV AAI_PORT "8443" +ENV AAI_SCHEMA_VERSION "v13" +ENV AAI_USERNAME "AAI" +ENV AAI_PASSWORD "AAI" + +EXPOSE 9007 + +COPY multicloud-openstack-pike.zip /opt +RUN apt-get update && \ + apt-get install -y vim memcached unzip && \ + cd /opt/ && \ + unzip -q -o -B multicloud-openstack-pike.zip && \ + chmod +x /opt/pike/*.sh && \ + rm -f multicloud-openstack-pike.zip && \ + pip install -r /opt/pike/requirements.txt + +ADD extsys.py /opt/pike/lib/share/common/msapi/extsys.py + +WORKDIR /opt/pike +CMD /bin/sh -c /opt/pike/run.sh diff --git a/pike/vagrant/test/extsys.py b/pike/vagrant/test/extsys.py new file mode 100644 index 00000000..78b41387 --- /dev/null +++ b/pike/vagrant/test/extsys.py @@ -0,0 +1,145 @@ +# Copyright (c) 2017-2018 Wind River Systems, 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. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import re + +from rest_framework import status +from common.exceptions import VimDriverNewtonException +from common.utils.restcall import req_by_msb,req_to_aai + + +logger = logging.getLogger(__name__) + +tisr4 = { + "createTime": "2017-04-01 02:22:27", + "domain": "Default", + "name": "TiS_R4", + "password": "admin", + "tenant": "admin", + "type": "openstack", + "url": "http://192.168.1.10:5000/v3", + "userName": "admin", + "vendor": "OpenStack", + "version": "pike", + "vimId": "openstack-hudson-dc_RegionOne", + 'cloud_owner':'openstack-hudson-dc', + 'cloud_region_id':'RegionOne', + 'cloud_extra_info':'', + 'cloud_epa_caps':'{"huge_page":"true","cpu_pinning":"true",\ + "cpu_thread_policy":"true","numa_aware":"true","sriov":"true",\ + "dpdk_vswitch":"true","rdt":"false","numa_locality_pci":"true"}', + 'insecure':'True', +} + +# "vimId": "6e720f68-34b3-44f0-a6a4-755929b20393" + +def mock_get_vim_by_id(method): + def wrapper(vimid): + return tisr4 + return wrapper + +def mock_delete_vim_by_id(method): + def wrapper(vimid): + return status.HTTP_202_ACCEPTED + return wrapper + +#def get_vims(): +# retcode, content, status_code = \ +# req_by_msb("/api/aai-cloudInfrastructure/v1/cloud-infrastructure/cloud-regions", "GET") +# if retcode != 0: +# logger.error("Status code is %s, detail is %s.", status_code, content) +# raise VimDriverNewtonException("Failed to query VIMs from extsys.") +# return json.JSONDecoder().decode(content) + +@mock_get_vim_by_id +def get_vim_by_id(vim_id): + + cloud_owner,cloud_region_id = decode_vim_id(vim_id) + + if cloud_owner and cloud_region_id: + retcode, content, status_code = \ + req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" + % (cloud_owner,cloud_region_id),"GET") + if retcode != 0: + logger.error("Status code is %s, detail is %s.", status_code, content) + raise VimDriverNewtonException( + "Failed to query VIM with id (%s:%s,%s)." % (vim_id,cloud_owner,cloud_region_id), + status_code, content) + tmp_viminfo = json.JSONDecoder().decode(content) + + #assume esr-system-info-id is composed by {cloud-owner} _ {cloud-region-id} + retcode2,content2,status_code2 = \ + req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" + + "/esr-system-info-list/esr-system-info/%s_%s" \ + % (cloud_owner,cloud_region_id,cloud_owner,cloud_region_id), + "GET") + if retcode2 != 0: + logger.error("Status code is %s, detail is %s.", status_code, content) + raise VimDriverNewtonException( + "Failed to query ESR system with id (%s:%s,%s)." % (vim_id,cloud_owner,cloud_region_id), + status_code, content) + tmp_authinfo = json.JSONDecoder().decode(content2) + + #convert vim information + + if tmp_viminfo: + viminfo = {} + viminfo['vimId'] = vim_id + viminfo['cloud_owner'] = cloud_owner + viminfo['cloud_region_id'] = cloud_region_id + viminfo['type'] = tmp_viminfo['cloud-type'] + viminfo['name'] = tmp_viminfo['complex-name'] + viminfo['version'] = tmp_viminfo['cloud-region-version'] + viminfo['cloud_extra_info'] = tmp_viminfo['cloud-extra-info'] + viminfo['cloud_epa_caps'] = tmp_viminfo['cloud-epa-caps'] + + if tmp_authinfo: + viminfo['userName'] = tmp_authinfo['user-name'] + viminfo['password'] = tmp_authinfo['password'] + viminfo['domain'] = tmp_authinfo['cloud-domain'] + viminfo['url'] = tmp_authinfo['service-url'] + viminfo['tenant'] = tmp_authinfo['default-tenant'] + viminfo['cacert'] = tmp_authinfo['ssl-cacert'] + viminfo['insecure'] = tmp_authinfo['ssl-insecure'] + else: + return None + + return viminfo + else: + return None + else: + return None + +@mock_delete_vim_by_id +def delete_vim_by_id(vim_id): + cloud_owner, cloud_region_id = decode_vim_id(vim_id) + if cloud_owner and cloud_region_id: + retcode, content, status_code = \ + req_to_aai("/cloud-infrastructure/cloud-regions/cloud-region/%s/%s" + % ( cloud_owner, cloud_region_id), "DELETE") + if retcode != 0: + logger.error("Status code is %s, detail is %s.", status_code, content) + raise VimDriverNewtonException( + "Failed to delete VIM in AAI with id (%s:%s,%s)." % (vim_id,cloud_owner,cloud_region_id), + status_code, content) + return 0 + # return non zero if failed to decode cloud owner and region id + return 1 + +def decode_vim_id(vim_id): + m = re.search(r'^([0-9a-zA-Z-]+)_([0-9a-zA-Z_-]+)$', vim_id) + cloud_owner, cloud_region_id = m.group(1), m.group(2) + return cloud_owner, cloud_region_id diff --git a/pike/vagrant/test/test-extensions.sh b/pike/vagrant/test/test-extensions.sh new file mode 100644 index 00000000..82c254a8 --- /dev/null +++ b/pike/vagrant/test/test-extensions.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -ex + +MULTICLOUD_PLUGIN_ENDPOINT=http://172.16.77.40:9007/api/multicloud-pike/v0/openstack-hudson-dc_RegionOne +curl -v -s -H "Content-Type: application/json" -X GET $MULTICLOUD_PLUGIN_ENDPOINT/extensions +curl -v -s -H "Content-Type: application/json" -X GET $MULTICLOUD_PLUGIN_ENDPOINT/extensions/epa-caps diff --git a/pike/vagrant/test/test_multicloud.sh b/pike/vagrant/test/test_multicloud.sh new file mode 100644 index 00000000..efc934ce --- /dev/null +++ b/pike/vagrant/test/test_multicloud.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -ex + +sudo apt-get update -y +sudo apt-get install -y docker.io maven npm virtualenv python-dev + +git clone http://gerrit.onap.org/r/oparent +mkdir $HOME/.m2 +cp oparent/settings.xml $HOME/.m2 + +git clone /openstack +cd openstack +mvn clean install +cp pike/target/multicloud-openstack-pike*.zip pike/vagrant/test/multicloud-openstack-pike.zip + +cd pike/vagrant/test +sudo docker build -t multicloud-pike-test:latest . +sudo docker network create --subnet=172.16.77.0/24 onap +sudo docker run -d -t --name pike-test --network onap --ip 172.16.77.40 -e MSB_ADDR=172.16.77.40 -e MSB_PORT=9007 multicloud-pike-test + +while true; do + sleep 10 + curl http://172.16.77.40:9007/api/multicloud-pike/v0/swagger.json && break +done + +for i in `cat tests` +do + bash ./$i +done diff --git a/pike/vagrant/test/tests b/pike/vagrant/test/tests new file mode 100644 index 00000000..018c7a48 --- /dev/null +++ b/pike/vagrant/test/tests @@ -0,0 +1 @@ +test-extensions.sh -- cgit 1.2.3-korg