From a7da9df2316973357945636cc4f122746722a492 Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Wed, 20 Sep 2017 11:18:35 +0800 Subject: Add windriver plugin Change-Id: Icd27d7af12d6920810d7cbb163e8be70db49f121 Issue-Id: MULTICLOUD-89 Signed-off-by: Bin Yang --- windriver/.gitignore | 11 + windriver/README.md | 12 + windriver/assembly.xml | 70 +++++ windriver/docker/Dockerfile | 31 ++ windriver/docker/build-image.sh | 32 +++ windriver/initialize.sh | 13 + windriver/logs/empty.txt | 0 windriver/manage.py | 19 ++ windriver/pom.xml | 58 ++++ windriver/requirements.txt | 17 ++ windriver/run.sh | 32 +++ windriver/stop.sh | 16 ++ windriver/titanium_cloud/__init__.py | 10 + windriver/titanium_cloud/extensions/__init__.py | 10 + windriver/titanium_cloud/extensions/urls.py | 29 ++ .../titanium_cloud/extensions/views/__init__.py | 10 + .../titanium_cloud/extensions/views/epacaps.py | 32 +++ .../titanium_cloud/extensions/views/extensions.py | 73 +++++ windriver/titanium_cloud/extensions/views/fcaps.py | 320 +++++++++++++++++++++ windriver/titanium_cloud/proxy/__init__.py | 10 + windriver/titanium_cloud/proxy/urls.py | 32 +++ windriver/titanium_cloud/proxy/views/__init__.py | 10 + windriver/titanium_cloud/proxy/views/identityV3.py | 27 ++ windriver/titanium_cloud/proxy/views/services.py | 45 +++ windriver/titanium_cloud/pub/__init__.py | 10 + windriver/titanium_cloud/pub/config/__init__.py | 10 + windriver/titanium_cloud/pub/config/config.py | 34 +++ windriver/titanium_cloud/registration/__init__.py | 10 + .../titanium_cloud/registration/views/__init__.py | 10 + .../registration/views/registration.py | 28 ++ windriver/titanium_cloud/requests/__init__.py | 13 + windriver/titanium_cloud/requests/urls.py | 47 +++ windriver/titanium_cloud/samples/__init__.py | 10 + windriver/titanium_cloud/samples/tests.py | 29 ++ windriver/titanium_cloud/samples/urls.py | 16 ++ windriver/titanium_cloud/samples/views.py | 26 ++ windriver/titanium_cloud/settings.py | 122 ++++++++ windriver/titanium_cloud/swagger/__init__.py | 10 + windriver/titanium_cloud/swagger/tests.py | 29 ++ windriver/titanium_cloud/swagger/urls.py | 21 ++ windriver/titanium_cloud/swagger/views.py | 45 +++ windriver/titanium_cloud/urls.py | 34 +++ windriver/titanium_cloud/wsgi.py | 19 ++ windriver/tox.ini | 14 + 44 files changed, 1456 insertions(+) create mode 100644 windriver/.gitignore create mode 100644 windriver/README.md create mode 100644 windriver/assembly.xml create mode 100644 windriver/docker/Dockerfile create mode 100644 windriver/docker/build-image.sh create mode 100644 windriver/initialize.sh create mode 100644 windriver/logs/empty.txt create mode 100644 windriver/manage.py create mode 100644 windriver/pom.xml create mode 100644 windriver/requirements.txt create mode 100644 windriver/run.sh create mode 100644 windriver/stop.sh create mode 100644 windriver/titanium_cloud/__init__.py create mode 100644 windriver/titanium_cloud/extensions/__init__.py create mode 100644 windriver/titanium_cloud/extensions/urls.py create mode 100644 windriver/titanium_cloud/extensions/views/__init__.py create mode 100644 windriver/titanium_cloud/extensions/views/epacaps.py create mode 100644 windriver/titanium_cloud/extensions/views/extensions.py create mode 100644 windriver/titanium_cloud/extensions/views/fcaps.py create mode 100644 windriver/titanium_cloud/proxy/__init__.py create mode 100644 windriver/titanium_cloud/proxy/urls.py create mode 100644 windriver/titanium_cloud/proxy/views/__init__.py create mode 100644 windriver/titanium_cloud/proxy/views/identityV3.py create mode 100644 windriver/titanium_cloud/proxy/views/services.py create mode 100644 windriver/titanium_cloud/pub/__init__.py create mode 100644 windriver/titanium_cloud/pub/config/__init__.py create mode 100644 windriver/titanium_cloud/pub/config/config.py create mode 100644 windriver/titanium_cloud/registration/__init__.py create mode 100644 windriver/titanium_cloud/registration/views/__init__.py create mode 100644 windriver/titanium_cloud/registration/views/registration.py create mode 100644 windriver/titanium_cloud/requests/__init__.py create mode 100644 windriver/titanium_cloud/requests/urls.py create mode 100644 windriver/titanium_cloud/samples/__init__.py create mode 100644 windriver/titanium_cloud/samples/tests.py create mode 100644 windriver/titanium_cloud/samples/urls.py create mode 100644 windriver/titanium_cloud/samples/views.py create mode 100644 windriver/titanium_cloud/settings.py create mode 100644 windriver/titanium_cloud/swagger/__init__.py create mode 100644 windriver/titanium_cloud/swagger/tests.py create mode 100644 windriver/titanium_cloud/swagger/urls.py create mode 100644 windriver/titanium_cloud/swagger/views.py create mode 100644 windriver/titanium_cloud/urls.py create mode 100644 windriver/titanium_cloud/wsgi.py create mode 100644 windriver/tox.ini (limited to 'windriver') diff --git a/windriver/.gitignore b/windriver/.gitignore new file mode 100644 index 00000000..e86d02b0 --- /dev/null +++ b/windriver/.gitignore @@ -0,0 +1,11 @@ +.project +.classpath +.settings/ +.checkstyle +target/ +logs/*.log +*.pyc +.tox +.coverage +htmlcov/ + diff --git a/windriver/README.md b/windriver/README.md new file mode 100644 index 00000000..3de1facc --- /dev/null +++ b/windriver/README.md @@ -0,0 +1,12 @@ +# Copyright (c) 2017 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. + +# Micro service of MultiCloud plugin for Wind River Titanium Cloud. diff --git a/windriver/assembly.xml b/windriver/assembly.xml new file mode 100644 index 00000000..ef3a749f --- /dev/null +++ b/windriver/assembly.xml @@ -0,0 +1,70 @@ + + + windriver + + zip + + + + titanium_cloud + /titanium_cloud + + **/*.py + **/*.json + **/*.xml + **/*.wsdl + **/*.xsd + **/*.bpel + + + + logs + /logs + + *.txt + + + + docker + /docker + + *.sh + Dockerfile + + + + . + / + + *.py + *.txt + *.sh + *.ini + *.md + + + + + + true + /lib + + org.onap.multicloud.openstack:multicloud-openstack-newton + + + + windriver + diff --git a/windriver/docker/Dockerfile b/windriver/docker/Dockerfile new file mode 100644 index 00000000..ac2e62ef --- /dev/null +++ b/windriver/docker/Dockerfile @@ -0,0 +1,31 @@ +FROM python:2 + +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_SCHEMA_VERSION "v11" +ENV AAI_USERNAME "AAI" +ENV AAI_PASSWORD "AAI" + +EXPOSE 9005 + +# COPY ./ /opt/windriver/ +RUN apt-get update && \ + apt-get install -y memcached && \ + apt-get install -y unzip && \ + cd /opt/ && \ + wget -O multicloud-openstack-windriver.zip "https://nexus.onap.org/service/local/artifact/maven/redirect?r=snapshots&g=org.onap.multicloud.openstack&a=multicloud-openstack-windriver&e=zip&v=LATEST" && \ + unzip -q -o -B multicloud-openstack-windriver.zip && \ + chmod +x /opt/windriver/*.sh && \ + rm -f multicloud-openstack-windriver.zip && \ + pip install -r /opt/windriver/requirements.txt + +WORKDIR /opt/windriver +CMD /bin/sh -c /opt/windriver/run.sh \ No newline at end of file diff --git a/windriver/docker/build-image.sh b/windriver/docker/build-image.sh new file mode 100644 index 00000000..cc32212e --- /dev/null +++ b/windriver/docker/build-image.sh @@ -0,0 +1,32 @@ +#!/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" +ORG="onap" +VERSION="1.0.0-SNAPSHOT" +PROJECT="multicloud" +IMAGE="openstack-windriver" +DOCKER_REPOSITORY="nexus3.onap.org:10003" +IMAGE_NAME="${DOCKER_REPOSITORY}/${ORG}/${PROJECT}/${IMAGE}" + +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 . +} + +function push_image { + docker push ${IMAGE_NAME}:${VERSION} + docker push ${IMAGE_NAME}:latest +} + +build_image +push_image \ No newline at end of file diff --git a/windriver/initialize.sh b/windriver/initialize.sh new file mode 100644 index 00000000..5fed1714 --- /dev/null +++ b/windriver/initialize.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright (c) 2017 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. + +pip install -r requirements.txt diff --git a/windriver/logs/empty.txt b/windriver/logs/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/windriver/manage.py b/windriver/manage.py new file mode 100644 index 00000000..14931558 --- /dev/null +++ b/windriver/manage.py @@ -0,0 +1,19 @@ +# Copyright (c) 2017 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. + +import os +import sys + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "titanium_cloud.settings") + +if __name__ == "__main__": + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/windriver/pom.xml b/windriver/pom.xml new file mode 100644 index 00000000..6e6c9d00 --- /dev/null +++ b/windriver/pom.xml @@ -0,0 +1,58 @@ + + + + + org.onap.oparent + oparent + 1.0.0-SNAPSHOT + ../oparent + + 4.0.0 + org.onap.multicloud.openstack + multicloud-openstack-windriver + 1.0.0-SNAPSHOT + pom + multicloud/openstack/windriver + multicloud for openstack Wind River Titanium Cloud + + + org.onap.multicloud.openstack + multicloud-openstack-newton + 1.0.0-SNAPSHOT + zip + + + + + + maven-assembly-plugin + + false + + assembly.xml + + + + + make-assembly + package + + single + + + + + + + diff --git a/windriver/requirements.txt b/windriver/requirements.txt new file mode 100644 index 00000000..841fe278 --- /dev/null +++ b/windriver/requirements.txt @@ -0,0 +1,17 @@ +# 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 + +# for unit test +coverage==4.2 +mock==2.0.0 +unittest_xml_reporting==1.12.0 diff --git a/windriver/run.sh b/windriver/run.sh new file mode 100644 index 00000000..031719b4 --- /dev/null +++ b/windriver/run.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2017 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. + +#!/bin/bash + +sed -i "s/MSB_SERVICE_ADDR =.*/MSB_SERVICE_ADDR = \"${MSB_ADDR}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/MSB_SERVICE_PORT =.*/MSB_SERVICE_PORT = \"${MSB_PORT}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/AAI_ADDR =.*/AAI_ADDR = \"${AAI_ADDR}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/AAI_PORT =.*/AAI_PORT = \"${AAI_PORT}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" titanium_cloud/pub/config/config.py +sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" titanium_cloud/pub/config/config.py + +memcached -d -m 2048 -u root -c 1024 -p 11211 -P /tmp/memcached1.pid +export PYTHONPATH=lib/newton +nohup python manage.py runserver 0.0.0.0:9005 2>&1 & + +while [ ! -f logs/runtime_titanium_cloud.log ]; do + sleep 1 +done + +tail -F logs/runtime_titanium_cloud.log + diff --git a/windriver/stop.sh b/windriver/stop.sh new file mode 100644 index 00000000..10ce7464 --- /dev/null +++ b/windriver/stop.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright (c) 2017 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. + +#!/bin/bash + +ps auxww | grep 'manage.py runserver 0.0.0.0:9005' | 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/windriver/titanium_cloud/__init__.py b/windriver/titanium_cloud/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/extensions/__init__.py b/windriver/titanium_cloud/extensions/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/extensions/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/extensions/urls.py b/windriver/titanium_cloud/extensions/urls.py new file mode 100644 index 00000000..b0ffec89 --- /dev/null +++ b/windriver/titanium_cloud/extensions/urls.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017 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 titanium_cloud.extensions.views import extensions +from titanium_cloud.extensions.views import epacaps +from titanium_cloud.extensions.views import fcaps + + +urlpatterns = [ + url(r'^sions/?$', extensions.Extensions.as_view()), + url(r'^sions/epa-caps/?$', epacaps.EpaCaps.as_view()), + url(r'^sions/guest-monitor/(?P[0-9a-zA-Z_-]+)/?$', fcaps.GuestMonitor.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/windriver/titanium_cloud/extensions/views/__init__.py b/windriver/titanium_cloud/extensions/views/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/extensions/views/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/extensions/views/epacaps.py b/windriver/titanium_cloud/extensions/views/epacaps.py new file mode 100644 index 00000000..7f638fad --- /dev/null +++ b/windriver/titanium_cloud/extensions/views/epacaps.py @@ -0,0 +1,32 @@ +# Copyright (c) 2017 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 titanium_cloud.pub.config import config + + +from newton.extensions.views import epacaps as newton_epacaps + +logger = logging.getLogger(__name__) + +DEBUG=True + + +class EpaCaps(newton_epacaps.EpaCaps): + + def __init__(self): + self.proxy_prefix = config.MULTICLOUD_PREFIX + self._logger = logger diff --git a/windriver/titanium_cloud/extensions/views/extensions.py b/windriver/titanium_cloud/extensions/views/extensions.py new file mode 100644 index 00000000..2dd61fe9 --- /dev/null +++ b/windriver/titanium_cloud/extensions/views/extensions.py @@ -0,0 +1,73 @@ +# Copyright (c) 2017 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 titanium_cloud.pub.config import config +from newton.extensions.views 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 = config.MULTICLOUD_PREFIX + + + def get(self, request, vimid=""): + logger.debug("Extensions--get::data> %s" % request.data) + logger.debug("Extensions--get::vimid> %s" + % vimid) + try: + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + registered_extensions = \ + [ + { + "alias": "epa-caps", + "description": "Multiple network support", + "name": "EPACapsQuery", + "url": self.proxy_prefix + "/%s/extensions/epa-caps" \ + % (vimid), + "spec": "" + }, + { + "alias": "guest-monitor", + "description": "Multiple network support", + "name": "EPACapsQuery", + "url": self.proxy_prefix +\ + "/%s/extensions/guest-monitor/{server_id}" \ + % (vimid), + "spec": "" + } + ] + + content = { + "cloud-owner":cloud_owner, + "cloud-region-id":cloud_region_id, + "vimid":vimid, + "extensions": registered_extensions + } + return Response(data=content, status=status.HTTP_200_OK) + + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/windriver/titanium_cloud/extensions/views/fcaps.py b/windriver/titanium_cloud/extensions/views/fcaps.py new file mode 100644 index 00000000..ad054e95 --- /dev/null +++ b/windriver/titanium_cloud/extensions/views/fcaps.py @@ -0,0 +1,320 @@ +# Copyright (c) 2017 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 +import threading + +from django.core.cache import cache + +from keystoneauth1.exceptions import HttpError +from rest_framework import status +from rest_framework.response import Response +from rest_framework.views import APIView + +from titanium_cloud.pub.config import config +from newton.pub.exceptions import VimDriverNewtonException +from newton.requests.views.util import VimDriverUtils +from newton.pub.msapi import extsys + + + +#from newton.extensions.views import fcaps as newton_fcaps + +logger = logging.getLogger(__name__) + +DEBUG=True + +#dict to store running worker threads +running_threads = {} +running_thread_lock = threading.Lock() + +class GuestMonitorWorker (threading.Thread): + service = {'service_type': 'platform', + 'interface': 'public'} + def __init__(self, vimid, tenantid=None): + threading.Thread.__init__(self) + self.vimid = vimid + self.tenantid = tenantid + self.eventid = '700.213' #Guest Heartbeat failed for instance + + def run(self): + logger.debug("start GuestMonitorWorker %s,%s" % (self.vimid, self.tenantid)) + + viminfo = VimDriverUtils.get_vim_info(self.vimid) + sess = VimDriverUtils.get_session(viminfo, tenantid=self.tenantid) + + thread_info = running_threads.get(self.vimid) + if not thread_info: + return + + while thread_info.get('state') == 'start': + #wait for jobs + vservers = thread_info.get('vservers') if thread_info else None + if not vservers: + continue + + # do jobs + for (vserverid, vserverinfo) in vservers.items(): + status_code, heartbeat_event = \ + self.monitor_heartbeat(self.vimid, self.tenantid, vserverid, viminfo, sess) + + if status_code == status.HTTP_403_FORBIDDEN: + #invalid tenant, so remove this job + + running_thread_lock.acquire() + thread_info['state'] = 'error' + running_thread_lock.release() + + return #exit this thread since error + + if heartbeat_event: + #report to VES + #tbd + pass + else: + continue + + running_thread_lock.acquire() + thread_info['state'] = 'stopped' + running_thread_lock.release() + + logger.debug("stop GuestMonitorWorker %s, %s, %s" % (self.vimid, self.tenantid, self.vserverid)) +# running_thread_lock.acquire() +# running_threads.pop(self.vimid) +# running_thread_lock.release() + + def monitor_heartbeat(self, vimid, tenantid, vserverid, viminfo, session): + logger.debug("GuestMonitorWorker--monitor_heartbeat::> %s" % (vserverid)) + try: + # prepare request resource to vim instance + req_resouce = "/v1/event_log?q.field=entity_instance_id&\ + q.field=event_log_id&\ + q.op=eq&q.op=eq&q.type=&q.type=&\ + q.value=tenant\%%s.instance\%%s&\ + q.value=%s" % (tenantid, vserverid, self.eventid) + + resp = session.get(req_resouce, endpoint_filter=self.service, + headers={"Content-Type": "application/json", + "Accept": "application/json"}) + + logger.debug("response status code of monitor_heartbeat %s" % resp.status_code) + + return resp.status_code, resp.json() if resp.content else None + + except HttpError as e: + logger.error("monitor_heartbeat, HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return e.http_status, e.response.json() + except Exception as e: + logger.error(traceback.format_exc()) + logger.error("Failed to monitor_heartbeat:%s" % str(e)) + return e.http_status, e.response.json() + + +class GuestMonitor(APIView): + + def __init__(self): + self.proxy_prefix = config.MULTICLOUD_PREFIX + self._logger = logger + + def post(self, request, vimid="", vserverid=""): + '''Start guest monitoring on specified virtual server''' + self._logger.debug("GuestMonitor--post::data> %s" % request.data) + self._logger.debug("GuestMonitor--post::vimid > %s" % vimid) + + try: + # populate proxy identity url + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + + tenant_name = request.data.get('tenantName') + tenant_id = request.data.get('tenantID') + ves_url = request.data.get('vesurl') + + # prepare request resource to vim instance + # get token: + viminfo = VimDriverUtils.get_vim_info(vimid) + # the tenant should have the privilege to access the event-log API + # usually it is 'admin'. Otherwise the 403 will be returned. + sess = None + if tenant_id: + sess = VimDriverUtils.get_session(viminfo, tenantid=tenant_id) + else: + sess = VimDriverUtils.get_session(viminfo, tenantname=tenant_name) + + #now try to convert tenant_name to tenant_id + #tbd + + thread_info = running_threads[vimid] + + if thread_info and thread_info['state'] == 'error': + #the thread is in error state, so recreate with new tenant_id + running_thread_lock.acquire() + running_threads.pop(vimid) + running_thread_lock.release() + thread_info = None + + if not thread_info: + tmp_thread = GuestMonitorWorker(vimid, tenant_id) + if not tmp_thread: + raise VimDriverNewtonException(message="internal error", + content="Fail to spawn thread for Guest Monitoring", + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) + thread_info = { + 'thread': tmp_thread, + 'tenantid':tenant_id, + 'vservers':{}, + 'state':'start' + } + + running_thread_lock.acquire() + running_threads[vimid] = thread_info + running_thread_lock.release() + tmp_thread.start() + else: + thread_info['state'] = 'start' + + + vservers = thread_info.get('vservers') + vservers[vserverid] = {'vesurl': ves_url} + + return Response(status=status.HTTP_202_ACCEPTED) + + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + def GET(self, request, vimid="", vserverid=""): + '''query guest monitoring on specified virtual server''' + self._logger.debug("GuestMonitor--get::data> %s" % request.data) + self._logger.debug("GuestMonitor--get::vimid > %s" % vimid) + + try: + # populate proxy identity url + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + + tenant_name = request.data.get('tenantName') + tenant_id = request.data.get('tenantID') + vserver_id = vserverid + + # prepare request resource to vim instance + # get token: + viminfo = VimDriverUtils.get_vim_info(vimid) + # the tenant should have the privilege to access the event-log API + # usually it is 'admin'. Otherwise the 403 will be returned. + sess = None + if tenant_id: + sess = VimDriverUtils.get_session(viminfo, tenantid=tenant_id) + else: + sess = VimDriverUtils.get_session(viminfo, tenantname=tenant_name) + + #now try to convert tenant_name to tenant_id, and vserver_name to vserver_id + #tbd + + thread_info = running_threads[vimid] + if not thread_info \ + or not thread_info.get('vservers') \ + or not thread_info.get('vservers').get(vserverid): + status_code = status.HTTP_204_NO_CONTENT + content = {'error': + 'Guest Monitor job is not created for this virtual server,\ + vim id: %s, vserver id: %s' + % (self.vimid, vserverid)} + pass + elif thread_info['state'] == 'error': + status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + content = {'error': + 'Guest Monitor job for this virtual server \ + (vim id: %s, vserver id: %s) failed due to: %s' + % (self.vimid, vserverid, thread_info.get('message'))} + pass + else: + vserverinfo = thread_info.get('vservers').get(vserverid) + content = vserverinfo.get('message') + status_code = vserverinfo.get('status') or status.HTTP_200_OK + pass + + #return Response(status=status.HTTP_202_ACCEPTED) + return Response(status=status_code, data=content) + + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + + def DELETE(self, request, vimid="", vserverid=""): + '''Stop guest monitoring on specified virtual server''' + self._logger.debug("GuestMonitor--delete::data> %s" % request.data) + self._logger.debug("GuestMonitor--delete::vimid > %s" % vimid) + + try: + # populate proxy identity url + cloud_owner, cloud_region_id = extsys.decode_vim_id(vimid) + + tenant_name = request.data.get('tenantName') + tenant_id = request.data.get('tenantID') + + # prepare request resource to vim instance + # get token: + viminfo = VimDriverUtils.get_vim_info(vimid) + # the tenant should have the privilege to access the event-log API + # usually it is 'admin'. Otherwise the 403 will be returned. + sess = None + if tenant_id: + sess = VimDriverUtils.get_session(viminfo, tenantid=tenant_id) + else: + sess = VimDriverUtils.get_session(viminfo, tenantname=tenant_name) + + #now try to convert tenant_name to tenant_id, and vserver_name to vserver_id + #tbd + + thread_info = running_threads[vimid] + if not thread_info: + status_code = status.HTTP_204_NO_CONTENT + else: + vservers = thread_info.get('vservers') + if vservers.get(vserverid): + vservers.pop(vserverid) + + running_thread_lock.acquire() + if len(vservers.items()) == 0: + thread_info.stop() + running_threads.pop(vimid) + running_thread_lock.release() + status_code = status.HTTP_202_ACCEPTED + + return Response(status=status_code) + + except VimDriverNewtonException as e: + return Response(data={'error': e.content}, status=e.status_code) + except HttpError as e: + self._logger.error("HttpError: status:%s, response:%s" % (e.http_status, e.response.json())) + return Response(data=e.response.json(), status=e.http_status) + except Exception as e: + self._logger.error(traceback.format_exc()) + return Response(data={'error': str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file diff --git a/windriver/titanium_cloud/proxy/__init__.py b/windriver/titanium_cloud/proxy/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/proxy/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/proxy/urls.py b/windriver/titanium_cloud/proxy/urls.py new file mode 100644 index 00000000..f848e76c --- /dev/null +++ b/windriver/titanium_cloud/proxy/urls.py @@ -0,0 +1,32 @@ +# Copyright (c) 2017 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 titanium_cloud.proxy.views import identityV3 +from titanium_cloud.proxy.views import services + +urlpatterns = [ + # url(r'^identity/v2)$', + # identityV2.Tokens.as_view()), + url(r'^identity/v3/auth/tokens/?$', + identityV3.Tokens.as_view()), + url(r'^identity/(?:v2.0/|)tenants/?$', + services.GetTenants.as_view()), + url(r'^(?P[0-9a-zA-Z_-]+)/(?P[0-9a-zA-Z./_-]*)$', + services.Services.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/windriver/titanium_cloud/proxy/views/__init__.py b/windriver/titanium_cloud/proxy/views/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/proxy/views/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/proxy/views/identityV3.py b/windriver/titanium_cloud/proxy/views/identityV3.py new file mode 100644 index 00000000..a6efa6ac --- /dev/null +++ b/windriver/titanium_cloud/proxy/views/identityV3.py @@ -0,0 +1,27 @@ +# Copyright (c) 2017 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 titanium_cloud.pub.config import config +from newton.proxy.views import identityV3 as newton_identityV3 + +logger = logging.getLogger(__name__) + +DEBUG=True + +class Tokens(newton_identityV3.Tokens): + + def __init__(self): + self.proxy_prefix = config.MULTICLOUD_PREFIX + self._logger = logger diff --git a/windriver/titanium_cloud/proxy/views/services.py b/windriver/titanium_cloud/proxy/views/services.py new file mode 100644 index 00000000..9bd5cc4e --- /dev/null +++ b/windriver/titanium_cloud/proxy/views/services.py @@ -0,0 +1,45 @@ +# Copyright (c) 2017 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 import status + +from titanium_cloud.pub.config import config +from newton.proxy.views import services as newton_services + +logger = logging.getLogger(__name__) + +DEBUG=True + +class Services(newton_services.Services): + + def __init__(self): + self._logger = logger + + +class GetTenants(newton_services.GetTenants): + ''' + Backward compatible API for /v2.0/tenants + ''' + + def __init__(self): + self._logger = logger + + def get(self, request, vimid="", servicetype="identity", requri='v3/projects'): + self._logger.debug("GetTenants--get::META> %s" % request.META) + self._logger.debug("GetTenants--get::data> %s" % request.data) + self._logger.debug("GetTenants--get::vimid, servicetype, requri> %s,%s,%s" + % (vimid, servicetype, requri)) + + return super(GetTenants,self).get(request, vimid, servicetype, requri) diff --git a/windriver/titanium_cloud/pub/__init__.py b/windriver/titanium_cloud/pub/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/pub/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/pub/config/__init__.py b/windriver/titanium_cloud/pub/config/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/pub/config/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/pub/config/config.py b/windriver/titanium_cloud/pub/config/config.py new file mode 100644 index 00000000..bc7e8553 --- /dev/null +++ b/windriver/titanium_cloud/pub/config/config.py @@ -0,0 +1,34 @@ +# Copyright (c) 2017 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. + +import os + +# [MSB] +MSB_SERVICE_ADDR = '127.0.0.1' +MSB_SERVICE_PORT = '80' + +#[Multicloud] +MULTICLOUD_PREFIX = "http://%s:%s/api/multicloud-titanium_cloud/v0" %(MSB_SERVICE_ADDR, MSB_SERVICE_PORT) + +# [A&AI] +AAI_ADDR = "aai.api.simpledemo.openecomp.org" +AAI_PORT = "8443" +AAI_SERVICE_URL = 'https://%s:%s/aai' % (AAI_ADDR, AAI_PORT) +AAI_SCHEMA_VERSION = "v11" +AAI_USERNAME = 'AAI' +AAI_PASSWORD = 'AAI' + +AAI_BASE_URL = "%s/%s" % (AAI_SERVICE_URL, AAI_SCHEMA_VERSION) + +MULTICLOUD_APP_ID = 'MultiCloud-Titanium_Cloud' + +# [IMAGE LOCAL PATH] +ROOT_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) diff --git a/windriver/titanium_cloud/registration/__init__.py b/windriver/titanium_cloud/registration/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/registration/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/registration/views/__init__.py b/windriver/titanium_cloud/registration/views/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/registration/views/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/registration/views/registration.py b/windriver/titanium_cloud/registration/views/registration.py new file mode 100644 index 00000000..e58e170b --- /dev/null +++ b/windriver/titanium_cloud/registration/views/registration.py @@ -0,0 +1,28 @@ +# Copyright (c) 2017 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 titanium_cloud.pub.config import config + +from newton.registration.views import registration as newton_registration + +logger = logging.getLogger(__name__) + +DEBUG=True + +class Registry(newton_registration.Registry): + + def __init__(self): + self.proxy_prefix = config.MULTICLOUD_PREFIX + self._logger = logger diff --git a/windriver/titanium_cloud/requests/__init__.py b/windriver/titanium_cloud/requests/__init__.py new file mode 100644 index 00000000..48b6e44b --- /dev/null +++ b/windriver/titanium_cloud/requests/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017 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/windriver/titanium_cloud/requests/urls.py b/windriver/titanium_cloud/requests/urls.py new file mode 100644 index 00000000..69f0e444 --- /dev/null +++ b/windriver/titanium_cloud/requests/urls.py @@ -0,0 +1,47 @@ +# Copyright (c) 2017 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 newton.requests.views import network +from newton.requests.views import subnet +from newton.requests.views import image +from newton.requests.views import volume +from newton.requests.views import server +from newton.requests.views import vport +from newton.requests.views import limits +from newton.requests.views import hosts +from newton.requests.views import flavor + +urlpatterns = [ + url(r'^networks(/(?P[0-9a-zA-Z_-]+))?', + network.Networks.as_view()), + url(r'^subnets(/(?P[0-9a-zA-Z_-]+))?', + subnet.Subnets.as_view()), + url(r'^images(/(?P[0-9a-zA-Z_-]+))?', + image.Images.as_view()), + url(r'^volumes(/(?P[0-9a-zA-Z_-]+))?', + volume.Volumes.as_view()), + url(r'^servers(/(?P[0-9a-zA-Z_-]+))?', + server.Servers.as_view()), + url(r'^ports(/(?P[0-9a-zA-Z_-]+))?', + vport.Vports.as_view()), + url(r'^flavors(/(?P[0-9a-zA-Z_-]+))?', + flavor.Flavors.as_view()), + url(r'^limits$', limits.Limits.as_view()), + url(r'^hosts(/(?P[0-9a-zA-Z_-]+))?', hosts.Hosts.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/windriver/titanium_cloud/samples/__init__.py b/windriver/titanium_cloud/samples/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/samples/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/samples/tests.py b/windriver/titanium_cloud/samples/tests.py new file mode 100644 index 00000000..d419efa5 --- /dev/null +++ b/windriver/titanium_cloud/samples/tests.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017 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. + +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/windriver/titanium_cloud/samples/urls.py b/windriver/titanium_cloud/samples/urls.py new file mode 100644 index 00000000..ae67a819 --- /dev/null +++ b/windriver/titanium_cloud/samples/urls.py @@ -0,0 +1,16 @@ +# Copyright (c) 2017 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. + +from django.conf.urls import url +from titanium_cloud.samples import views + +urlpatterns = [ + url(r'^samples/?$', views.SampleList.as_view()), ] diff --git a/windriver/titanium_cloud/samples/views.py b/windriver/titanium_cloud/samples/views.py new file mode 100644 index 00000000..e51044ad --- /dev/null +++ b/windriver/titanium_cloud/samples/views.py @@ -0,0 +1,26 @@ +# Copyright (c) 2017 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. + +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/windriver/titanium_cloud/settings.py b/windriver/titanium_cloud/settings.py new file mode 100644 index 00000000..393f994e --- /dev/null +++ b/windriver/titanium_cloud/settings.py @@ -0,0 +1,122 @@ +# Copyright (c) 2017 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. + +import os +import sys + +# 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', +] + +ROOT_URLCONF = 'titanium_cloud.urls' + +WSGI_APPLICATION = 'titanium_cloud.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/' + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'standard': { + 'format': '%(asctime)s:[%(name)s]:[%(filename)s]-[%(lineno)d] [%(levelname)s]:%(message)s', + }, + }, + 'filters': { + }, + 'handlers': { + 'titanium_cloud_handler': { + 'level': 'DEBUG', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': os.path.join(BASE_DIR, 'logs/runtime_titanium_cloud.log'), + 'formatter': 'standard', + 'maxBytes': 1024 * 1024 * 50, + 'backupCount': 5, + }, + }, + + 'loggers': { + 'titanium_cloud': { + 'handlers': ['titanium_cloud_handler'], + 'level': 'DEBUG', + 'propagate': False + }, + } +} + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + } +} + +if 'test' in sys.argv: + from titanium_cloud.pub.config import config + + 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/windriver/titanium_cloud/swagger/__init__.py b/windriver/titanium_cloud/swagger/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/windriver/titanium_cloud/swagger/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2017 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. diff --git a/windriver/titanium_cloud/swagger/tests.py b/windriver/titanium_cloud/swagger/tests.py new file mode 100644 index 00000000..ea9c9e50 --- /dev/null +++ b/windriver/titanium_cloud/swagger/tests.py @@ -0,0 +1,29 @@ +# Copyright (c) 2017 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. + +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-titanium_cloud/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/windriver/titanium_cloud/swagger/urls.py b/windriver/titanium_cloud/swagger/urls.py new file mode 100644 index 00000000..21ef4bde --- /dev/null +++ b/windriver/titanium_cloud/swagger/urls.py @@ -0,0 +1,21 @@ +# Copyright (c) 2017 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. + +from django.conf.urls import patterns, url +from rest_framework.urlpatterns import format_suffix_patterns + +from titanium_cloud.swagger.views import SwaggerJsonView + +urlpatterns = [ + url(r'^api/multicloud-titanium_cloud/v0/swagger.json$', SwaggerJsonView.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/windriver/titanium_cloud/swagger/views.py b/windriver/titanium_cloud/swagger/views.py new file mode 100644 index 00000000..01f9374e --- /dev/null +++ b/windriver/titanium_cloud/swagger/views.py @@ -0,0 +1,45 @@ +# Copyright (c) 2017 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. + +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 newton.pub.exceptions import VimDriverNewtonException +from newton.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-titanium_cloud/v0/" + json_data["info"]["title"] = "Service NBI of MultiCloud plugin for OpenStack Newton" + return Response(data=json_data, status=200) + else: + return Response(data={'error':'internal error'}, status=500) + + diff --git a/windriver/titanium_cloud/urls.py b/windriver/titanium_cloud/urls.py new file mode 100644 index 00000000..664d8b3e --- /dev/null +++ b/windriver/titanium_cloud/urls.py @@ -0,0 +1,34 @@ +# Copyright (c) 2017 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. + +from django.conf.urls import include, url + +from titanium_cloud.registration.views import registration +from newton.requests.views import tenants + +urlpatterns = [ + url(r'^', include('titanium_cloud.swagger.urls')), + url(r'^', include('titanium_cloud.samples.urls')), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/registry/?$', + registration.Registry.as_view()), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/?$', + registration.Registry.as_view()), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/exten', + include('titanium_cloud.extensions.urls')), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/', + include('titanium_cloud.proxy.urls')), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/tenants/?$', + tenants.Tenants.as_view()), + url(r'^api/multicloud-titanium_cloud/v0/(?P[0-9a-zA-Z_-]+)/' + '(?P[0-9a-zA-Z_-]{8,})/', include('titanium_cloud.requests.urls')), +] + + diff --git a/windriver/titanium_cloud/wsgi.py b/windriver/titanium_cloud/wsgi.py new file mode 100644 index 00000000..2962328d --- /dev/null +++ b/windriver/titanium_cloud/wsgi.py @@ -0,0 +1,19 @@ +# Copyright (c) 2017 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. + + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "titanium_cloud.settings") + +application = get_wsgi_application() diff --git a/windriver/tox.ini b/windriver/tox.ini new file mode 100644 index 00000000..764cf01c --- /dev/null +++ b/windriver/tox.ini @@ -0,0 +1,14 @@ +[tox] +envlist = py27,py35 +skipsdist = true + +[tox:jenkins] +downloadcache = ~/cache/pip + +[testenv] +setenv = + PYTHONPATH = {toxinidir}/../newton +deps = -r{toxinidir}/requirements.txt +commands = coverage run --branch manage.py test titanium_cloud + coverage html --omit=".tox*,*test*,*__init__.py" -d htmlcov + -- cgit 1.2.3-korg