Add windriver plugin 53/12953/4
authorBin Yang <bin.yang@windriver.com>
Wed, 20 Sep 2017 03:18:35 +0000 (11:18 +0800)
committerBin Yang <bin.yang@windriver.com>
Wed, 20 Sep 2017 03:18:35 +0000 (11:18 +0800)
Change-Id: Icd27d7af12d6920810d7cbb163e8be70db49f121
Issue-Id: MULTICLOUD-89
Signed-off-by: Bin Yang <bin.yang@windriver.com>
45 files changed:
pom.xml
windriver/.gitignore [new file with mode: 0644]
windriver/README.md [new file with mode: 0644]
windriver/assembly.xml [new file with mode: 0644]
windriver/docker/Dockerfile [new file with mode: 0644]
windriver/docker/build-image.sh [new file with mode: 0644]
windriver/initialize.sh [new file with mode: 0644]
windriver/logs/empty.txt [new file with mode: 0644]
windriver/manage.py [new file with mode: 0644]
windriver/pom.xml [new file with mode: 0644]
windriver/requirements.txt [new file with mode: 0644]
windriver/run.sh [new file with mode: 0644]
windriver/stop.sh [new file with mode: 0644]
windriver/titanium_cloud/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/urls.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/views/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/views/epacaps.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/views/extensions.py [new file with mode: 0644]
windriver/titanium_cloud/extensions/views/fcaps.py [new file with mode: 0644]
windriver/titanium_cloud/proxy/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/proxy/urls.py [new file with mode: 0644]
windriver/titanium_cloud/proxy/views/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/proxy/views/identityV3.py [new file with mode: 0644]
windriver/titanium_cloud/proxy/views/services.py [new file with mode: 0644]
windriver/titanium_cloud/pub/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/pub/config/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/pub/config/config.py [new file with mode: 0644]
windriver/titanium_cloud/registration/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/registration/views/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/registration/views/registration.py [new file with mode: 0644]
windriver/titanium_cloud/requests/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/requests/urls.py [new file with mode: 0644]
windriver/titanium_cloud/samples/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/samples/tests.py [new file with mode: 0644]
windriver/titanium_cloud/samples/urls.py [new file with mode: 0644]
windriver/titanium_cloud/samples/views.py [new file with mode: 0644]
windriver/titanium_cloud/settings.py [new file with mode: 0644]
windriver/titanium_cloud/swagger/__init__.py [new file with mode: 0644]
windriver/titanium_cloud/swagger/tests.py [new file with mode: 0644]
windriver/titanium_cloud/swagger/urls.py [new file with mode: 0644]
windriver/titanium_cloud/swagger/views.py [new file with mode: 0644]
windriver/titanium_cloud/urls.py [new file with mode: 0644]
windriver/titanium_cloud/wsgi.py [new file with mode: 0644]
windriver/tox.ini [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index 9f0acec..ccfb334 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -29,6 +29,8 @@
     
     <modules>
         <module>newton</module>
+        <module>ocata</module>
+        <module>windriver</module>
     </modules>
 
     <build>
diff --git a/windriver/.gitignore b/windriver/.gitignore
new file mode 100644 (file)
index 0000000..e86d02b
--- /dev/null
@@ -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 (file)
index 0000000..3de1fac
--- /dev/null
@@ -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 (file)
index 0000000..ef3a749
--- /dev/null
@@ -0,0 +1,70 @@
+<!--
+ 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.
+-->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>windriver</id>
+    <formats>
+        <format>zip</format>
+    </formats>
+    <fileSets>
+        <fileSet>
+            <directory>titanium_cloud</directory>
+            <outputDirectory>/titanium_cloud</outputDirectory>
+            <includes>
+                <include>**/*.py</include>
+                <include>**/*.json</include>
+                <include>**/*.xml</include>
+                <include>**/*.wsdl</include>
+                <include>**/*.xsd</include>
+                <include>**/*.bpel</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>logs</directory>
+            <outputDirectory>/logs</outputDirectory>
+            <includes>
+                <include>*.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>docker</directory>
+            <outputDirectory>/docker</outputDirectory>
+            <includes>
+                <include>*.sh</include>
+                <include>Dockerfile</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>.</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>*.py</include>
+                <include>*.txt</include>
+                <include>*.sh</include>
+                <include>*.ini</include>
+                <include>*.md</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+    <dependencySets>
+    <dependencySet>
+        <unpack>true</unpack>
+      <outputDirectory>/lib</outputDirectory>
+      <includes>
+        <include>org.onap.multicloud.openstack:multicloud-openstack-newton</include>
+      </includes>
+    </dependencySet>
+  </dependencySets>
+    <baseDirectory>windriver</baseDirectory>
+</assembly>
diff --git a/windriver/docker/Dockerfile b/windriver/docker/Dockerfile
new file mode 100644 (file)
index 0000000..ac2e62e
--- /dev/null
@@ -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 (file)
index 0000000..cc32212
--- /dev/null
@@ -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 (file)
index 0000000..5fed171
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/windriver/manage.py b/windriver/manage.py
new file mode 100644 (file)
index 0000000..1493155
--- /dev/null
@@ -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 (file)
index 0000000..6e6c9d0
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.onap.oparent</groupId>
+        <artifactId>oparent</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../oparent</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.onap.multicloud.openstack</groupId>
+    <artifactId>multicloud-openstack-windriver</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <name>multicloud/openstack/windriver</name>
+    <description>multicloud for openstack Wind River Titanium Cloud</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.multicloud.openstack</groupId>
+            <artifactId>multicloud-openstack-newton</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <type>zip</type>
+        </dependency>
+    </dependencies>
+    <build>
+      <plugins>
+        <plugin>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <configuration>
+                <appendAssemblyId>false</appendAssemblyId>
+                <descriptors>
+                    <descriptor>assembly.xml</descriptor>
+                </descriptors>
+            </configuration>
+            <executions>
+                <execution>
+                    <id>make-assembly</id>
+                    <phase>package</phase>
+                    <goals>
+                        <goal>single</goal>
+                    </goals>
+                </execution>
+            </executions>
+        </plugin>
+      </plugins>
+    </build>
+</project>
diff --git a/windriver/requirements.txt b/windriver/requirements.txt
new file mode 100644 (file)
index 0000000..841fe27
--- /dev/null
@@ -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 (file)
index 0000000..031719b
--- /dev/null
@@ -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 (file)
index 0000000..10ce746
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..b0ffec8
--- /dev/null
@@ -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<vserverid>[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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..7f638fa
--- /dev/null
@@ -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 (file)
index 0000000..2dd61fe
--- /dev/null
@@ -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 (file)
index 0000000..ad054e9
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..f848e76
--- /dev/null
@@ -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<servicetype>[0-9a-zA-Z_-]+)/(?P<requri>[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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..a6efa6a
--- /dev/null
@@ -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 (file)
index 0000000..9bd5cc4
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..bc7e855
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..e58e170
--- /dev/null
@@ -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 (file)
index 0000000..48b6e44
--- /dev/null
@@ -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 (file)
index 0000000..69f0e44
--- /dev/null
@@ -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<networkid>[0-9a-zA-Z_-]+))?',
+        network.Networks.as_view()),
+    url(r'^subnets(/(?P<subnetid>[0-9a-zA-Z_-]+))?',
+        subnet.Subnets.as_view()),
+    url(r'^images(/(?P<imageid>[0-9a-zA-Z_-]+))?',
+        image.Images.as_view()),
+    url(r'^volumes(/(?P<volumeid>[0-9a-zA-Z_-]+))?',
+        volume.Volumes.as_view()),
+    url(r'^servers(/(?P<serverid>[0-9a-zA-Z_-]+))?',
+        server.Servers.as_view()),
+    url(r'^ports(/(?P<portid>[0-9a-zA-Z_-]+))?',
+        vport.Vports.as_view()),
+    url(r'^flavors(/(?P<flavorid>[0-9a-zA-Z_-]+))?',
+        flavor.Flavors.as_view()),
+    url(r'^limits$', limits.Limits.as_view()),
+    url(r'^hosts(/(?P<hostname>[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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..d419efa
--- /dev/null
@@ -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 (file)
index 0000000..ae67a81
--- /dev/null
@@ -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 (file)
index 0000000..e51044a
--- /dev/null
@@ -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 (file)
index 0000000..393f994
--- /dev/null
@@ -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 (file)
index 0000000..802f3fb
--- /dev/null
@@ -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 (file)
index 0000000..ea9c9e5
--- /dev/null
@@ -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 (file)
index 0000000..21ef4bd
--- /dev/null
@@ -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 (file)
index 0000000..01f9374
--- /dev/null
@@ -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 (file)
index 0000000..664d8b3
--- /dev/null
@@ -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<vimid>[0-9a-zA-Z_-]+)/registry/?$',
+        registration.Registry.as_view()),
+    url(r'^api/multicloud-titanium_cloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/?$',
+        registration.Registry.as_view()),
+    url(r'^api/multicloud-titanium_cloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/exten',
+        include('titanium_cloud.extensions.urls')),
+    url(r'^api/multicloud-titanium_cloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/',
+             include('titanium_cloud.proxy.urls')),
+    url(r'^api/multicloud-titanium_cloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/tenants/?$',
+             tenants.Tenants.as_view()),
+    url(r'^api/multicloud-titanium_cloud/v0/(?P<vimid>[0-9a-zA-Z_-]+)/'
+        '(?P<tenantid>[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 (file)
index 0000000..2962328
--- /dev/null
@@ -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 (file)
index 0000000..764cf01
--- /dev/null
@@ -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
+