diff options
Diffstat (limited to 'newton')
50 files changed, 6986 insertions, 0 deletions
diff --git a/newton/.gitignore b/newton/.gitignore new file mode 100644 index 00000000..821f62a6 --- /dev/null +++ b/newton/.gitignore @@ -0,0 +1,2 @@ +logs/*.log +*.pyc
\ No newline at end of file diff --git a/newton/README.md b/newton/README.md new file mode 100644 index 00000000..ca2bb587 --- /dev/null +++ b/newton/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 network service life cycle management. diff --git a/newton/assembly.xml b/newton/assembly.xml new file mode 100644 index 00000000..81b17ee6 --- /dev/null +++ b/newton/assembly.xml @@ -0,0 +1,54 @@ +<!-- + 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>newton</id> + <formats> + <format>zip</format> + </formats> + <fileSets> + <fileSet> + <directory>newton</directory> + <outputDirectory>/newton</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>.</directory> + <outputDirectory>/</outputDirectory> + <includes> + <include>*.py</include> + <include>*.txt</include> + <include>*.sh</include> + <include>*.ini</include> + <include>*.md</include> + </includes> + </fileSet> + </fileSets> + <baseDirectory>newton</baseDirectory> + <!--baseDirectory>multivimdriver-openstack/newton</baseDirectory--> +</assembly> diff --git a/newton/initialize.sh b/newton/initialize.sh new file mode 100755 index 00000000..5fed1714 --- /dev/null +++ b/newton/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/newton/manage.py b/newton/manage.py new file mode 100644 index 00000000..9011afd9 --- /dev/null +++ b/newton/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", "newton.settings") + +if __name__ == "__main__": + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/newton/newton/__init__.py b/newton/newton/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/__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/newton/newton/pub/__init__.py b/newton/newton/pub/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/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/newton/newton/pub/config/__init__.py b/newton/newton/pub/config/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/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/newton/newton/pub/config/config.py b/newton/newton/pub/config/config.py new file mode 100644 index 00000000..e27682bd --- /dev/null +++ b/newton/newton/pub/config/config.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. + +import os + +# [MSB] +MSB_SERVICE_IP = '127.0.0.1' +MSB_SERVICE_PORT = '10080' + +# [IMAGE LOCAL PATH] +ROOT_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +# [REDIS] +REDIS_HOST = '127.0.0.1' +REDIS_PORT = '6379' +REDIS_PASSWD = '' + +# [mysql] +DB_IP = "127.0.0.1" +DB_PORT = 3306 +DB_NAME = "multivimnewton" +DB_USER = "root" +DB_PASSWD = "password" + +# [register] +REG_TO_MSB_WHEN_START = True +REG_TO_MSB_REG_URL = "/openoapi/microservices/v1/services" +REG_TO_MSB_REG_PARAM = { + "serviceName": "multivim-newton", + "version": "v1", + "url": "/openoapi/multivim-newton/v1", + "protocol": "REST", + "visualRange": "1", + "nodes": [{ + "ip": "127.0.0.1", + "port": "9003", + "ttl": 0 + }] +} diff --git a/newton/newton/pub/database/__init__.py b/newton/newton/pub/database/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/pub/database/__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/newton/newton/pub/database/models.py b/newton/newton/pub/database/models.py new file mode 100644 index 00000000..0a23fc4e --- /dev/null +++ b/newton/newton/pub/database/models.py @@ -0,0 +1,20 @@ +# 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.db import models + +class VimInstModel(models.Model): + class Meta: + db_table = 'vim_inst_type_mapping' + + vimid = models.CharField(db_column='VIMID', primary_key=True, max_length=200) + vimtype = models.CharField(db_column="VIMTYPE", max_length=200) + viminst_url = models.CharField(db_column="VIMINSTURL", max_length=200) diff --git a/newton/newton/pub/exceptions.py b/newton/newton/pub/exceptions.py new file mode 100644 index 00000000..dff87e8a --- /dev/null +++ b/newton/newton/pub/exceptions.py @@ -0,0 +1,14 @@ +# 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. + + +class VimDriverNewtonException(Exception): + pass diff --git a/newton/newton/pub/msapi/__init__.py b/newton/newton/pub/msapi/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/pub/msapi/__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/newton/newton/pub/msapi/extsys.py b/newton/newton/pub/msapi/extsys.py new file mode 100644 index 00000000..748d33a9 --- /dev/null +++ b/newton/newton/pub/msapi/extsys.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 json +import logging + +from newton.pub.exceptions import VimDriverNewtonException +from newton.pub.utils.restcall import req_by_msb + +logger = logging.getLogger(__name__) + + +def get_vims(): + ret = req_by_msb("/openoapi/extsys/v1/vims", "GET") + if ret[0] != 0: + logger.error("Status code is %s, detail is %s.", ret[2], ret[1]) + raise VimDriverNewtonException("Failed to query VIMs from extsys.") + return json.JSONDecoder().decode(ret[1]) + + +def get_vim_by_id(vim_id): + ret = req_by_msb("/openoapi/extsys/v1/vims/%s" % vim_id, "GET") + if ret[0] != 0: + logger.error("Status code is %s, detail is %s.", ret[2], ret[1]) + raise VimDriverNewtonException("Failed to query VIM with id (%s) from extsys." % vim_id) + return json.JSONDecoder().decode(ret[1]) diff --git a/newton/newton/pub/utils/__init__.py b/newton/newton/pub/utils/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/pub/utils/__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/newton/newton/pub/utils/enumutil.py b/newton/newton/pub/utils/enumutil.py new file mode 100644 index 00000000..4a5c3b10 --- /dev/null +++ b/newton/newton/pub/utils/enumutil.py @@ -0,0 +1,14 @@ +# 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. + + +def enum(**enums): + return type('Enum', (), enums) diff --git a/newton/newton/pub/utils/fileutil.py b/newton/newton/pub/utils/fileutil.py new file mode 100644 index 00000000..a33186ec --- /dev/null +++ b/newton/newton/pub/utils/fileutil.py @@ -0,0 +1,49 @@ +# 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 shutil +import logging +import traceback +import urllib2 + +logger = logging.getLogger(__name__) + + +def make_dirs(path): + if not os.path.exists(path): + os.makedirs(path, 0777) + + +def delete_dirs(path): + try: + if os.path.exists(path): + shutil.rmtree(path) + except Exception as e: + logger.error(traceback.format_exc()) + logger.error("Failed to delete %s:%s", path, e.message) + + +def download_file_from_http(url, local_dir, file_name): + local_file_name = os.path.join(local_dir, file_name) + is_download_ok = False + try: + make_dirs(local_dir) + r = urllib2.Request(url) + req = urllib2.urlopen(r) + save_file = open(local_file_name, 'wb') + save_file.write(req.read()) + save_file.close() + req.close() + is_download_ok = True + except: + logger.error(traceback.format_exc()) + logger.error("Failed to download %s to %s.", url, local_file_name) + return is_download_ok, local_file_name diff --git a/newton/newton/pub/utils/idutil.py b/newton/newton/pub/utils/idutil.py new file mode 100644 index 00000000..8e344f30 --- /dev/null +++ b/newton/newton/pub/utils/idutil.py @@ -0,0 +1,17 @@ +# 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 redisco import containers as cont + + +def get_auto_id(id_type, id_group="auto_id_hash"): + auto_id_hash = cont.Hash(id_group) + auto_id_hash.hincrby(id_type, 1) + return auto_id_hash.hget(id_type) diff --git a/newton/newton/pub/utils/restcall.py b/newton/newton/pub/utils/restcall.py new file mode 100644 index 00000000..6f9f9d8b --- /dev/null +++ b/newton/newton/pub/utils/restcall.py @@ -0,0 +1,92 @@ +# 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 sys +import traceback +import logging +import urllib2 +import uuid +import httplib2 + +from newton.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT + +rest_no_auth, rest_oneway_auth, rest_bothway_auth = 0, 1, 2 +HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED = '200', '201', '204', '202' +status_ok_list = [HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT, HTTP_202_ACCEPTED] +HTTP_404_NOTFOUND, HTTP_403_FORBIDDEN, HTTP_401_UNAUTHORIZED, HTTP_400_BADREQUEST = '404', '403', '401', '400' + +logger = logging.getLogger(__name__) + + +def call_req(base_url, user, passwd, auth_type, resource, method, content=''): + callid = str(uuid.uuid1()) + logger.debug("[%s]call_req('%s','%s','%s',%s,'%s','%s','%s')" % ( + callid, base_url, user, passwd, auth_type, resource, method, content)) + ret = None + resp_status = '' + try: + full_url = combine_url(base_url, resource) + headers = {'content-type': 'application/json', 'accept': 'application/json'} + if user: + headers['Authorization'] = 'Basic ' + ('%s:%s' % (user, passwd)).encode("base64") + ca_certs = None + for retry_times in range(3): + http = httplib2.Http(ca_certs=ca_certs, disable_ssl_certificate_validation=(auth_type == rest_no_auth)) + http.follow_all_redirects = True + try: + resp, resp_content = http.request(full_url, method=method.upper(), body=content, headers=headers) + resp_status, resp_body = resp['status'], resp_content.decode('UTF-8') + logger.debug("[%s][%d]status=%s,resp_body=%s)" % (callid, retry_times, resp_status, resp_body)) + if resp_status in status_ok_list: + ret = [0, resp_body, resp_status] + else: + ret = [1, resp_body, resp_status] + break + except Exception as ex: + if 'httplib.ResponseNotReady' in str(sys.exc_info()): + logger.debug("retry_times=%d", retry_times) + logger.error(traceback.format_exc()) + ret = [1, "Unable to connect to %s" % full_url, resp_status] + continue + raise ex + except urllib2.URLError as err: + ret = [2, str(err), resp_status] + except Exception as ex: + logger.error(traceback.format_exc()) + logger.error("[%s]ret=%s" % (callid, str(sys.exc_info()))) + res_info = str(sys.exc_info()) + if 'httplib.ResponseNotReady' in res_info: + res_info = "The URL[%s] request failed or is not responding." % full_url + ret = [3, res_info, resp_status] + except: + logger.error(traceback.format_exc()) + ret = [4, str(sys.exc_info()), resp_status] + + logger.debug("[%s]ret=%s" % (callid, str(ret))) + return ret + + +def req_by_msb(resource, method, content=''): + base_url = "http://%s:%s/" % (MSB_SERVICE_IP, MSB_SERVICE_PORT) + return call_req(base_url, "", "", rest_no_auth, resource, method, content) + + +def combine_url(base_url, resource): + full_url = None + if base_url.endswith('/') and resource.startswith('/'): + full_url = base_url[:-1] + resource + elif base_url.endswith('/') and not resource.startswith('/'): + full_url = base_url + resource + elif not base_url.endswith('/') and resource.startswith('/'): + full_url = base_url + resource + else: + full_url = base_url + '/' + resource + return full_url diff --git a/newton/newton/pub/utils/share_lock.py b/newton/newton/pub/utils/share_lock.py new file mode 100755 index 00000000..aba599a2 --- /dev/null +++ b/newton/newton/pub/utils/share_lock.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# 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 time + +import redis + +from newton.pub.config.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWD + + +class SharedLock: + def __init__(self, lock_key, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWD, db=9, lock_timeout=5 * 60): + self.lock_key = lock_key + self.lock_timeout = lock_timeout + self.redis = redis.Redis(host=host, port=port, db=db, password=password) + self.acquire_time = -1 + + def acquire(self): + begin = now = int(time.time()) + while (now - begin) < self.lock_timeout: + + result = self.redis.setnx(self.lock_key, now + self.lock_timeout + 1) + if result == 1 or result is True: + self.acquire_time = now + return True + + current_lock_timestamp = self.redis.get(self.lock_key) + if not current_lock_timestamp: + time.sleep(1) + continue + + current_lock_timestamp = int(current_lock_timestamp) + + if now > current_lock_timestamp: + next_lock_timestamp = self.redis.getset(self.lock_key, now + self.lock_timeout + 1) + if not next_lock_timestamp: + time.sleep(1) + continue + next_lock_timestamp = int(next_lock_timestamp) + + if next_lock_timestamp == current_lock_timestamp: + self.acquire_time = now + return True + else: + time.sleep(1) + continue + return False + + def release(self): + now = int(time.time()) + if now > self.acquire_time + self.lock_timeout: + # key expired, do nothing and let other clients handle it + return + self.acquire_time = None + self.redis.delete(self.lock_key) + + +def do_biz_with_share_lock(lock_name, callback): + lock = SharedLock(lock_name) + try: + if not lock.acquire(): + raise Exception(lock_name + " timeout") + callback() + except Exception as e: + raise e + finally: + lock.release() diff --git a/newton/newton/pub/utils/syscomm.py b/newton/newton/pub/utils/syscomm.py new file mode 100644 index 00000000..735129a6 --- /dev/null +++ b/newton/newton/pub/utils/syscomm.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. + +import inspect + + +def fun_name(): + return inspect.stack()[1][3] diff --git a/newton/newton/pub/utils/timeutil.py b/newton/newton/pub/utils/timeutil.py new file mode 100644 index 00000000..984bb8d6 --- /dev/null +++ b/newton/newton/pub/utils/timeutil.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. + +import datetime + + +def now_time(fmt="%Y-%m-%d %H:%M:%S"): + return datetime.datetime.now().strftime(fmt) diff --git a/newton/newton/pub/utils/toscautil.py b/newton/newton/pub/utils/toscautil.py new file mode 100644 index 00000000..ec6e2009 --- /dev/null +++ b/newton/newton/pub/utils/toscautil.py @@ -0,0 +1,2603 @@ +# 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 + +def safe_get(key_val, key): + return key_val[key] if key in key_val else "" + + +def find_node_name(node_id, node_list): + for node in node_list: + if node['id'] == node_id: + return node['template_name'] + raise Exception('can not find node(%s).' % node_id) + + +def find_node_type(node_id, node_list): + for node in node_list: + if node['id'] == node_id: + return node['type_name'] + raise Exception('can not find node(%s).' % node_id) + + +def find_related_node(node_id, src_json_model, requirement_name): + related_nodes = [] + for model_tpl in safe_get(src_json_model, "node_templates"): + for rt in safe_get(model_tpl, 'requirement_templates'): + if safe_get(rt, 'name') == requirement_name and \ + safe_get(rt, 'target_node_template_name') == node_id: + related_nodes.append(model_tpl['name']) + return related_nodes + + +def convert_props(src_node, dest_node): + if 'properties' in src_node and src_node['properties']: + for prop_name, prop_info in src_node['properties'].items(): + if 'value' in prop_info: + dest_node['properties'][prop_name] = prop_info['value'] + + +def convert_metadata(src_json): + return src_json['metadata'] if 'metadata' in src_json else {} + + +def convert_inputs(src_json): + inputs = {} + if 'inputs' in src_json: + src_inputs = src_json['inputs'] + for param_name, param_info in src_inputs.items(): + input_param = {} + if 'type_name' in param_info: + input_param['type'] = param_info['type_name'] + if 'description' in param_info: + input_param['description'] = param_info['description'] + if 'value' in param_info: + input_param['value'] = param_info['value'] + inputs[param_name] = input_param + return inputs + + +def convert_vnf_node(src_node, src_json_model): + vnf_node = {'type': src_node['type_name'], 'vnf_id': src_node['template_name'], + 'description': '', 'properties': {}, 'dependencies': [], 'networks': []} + convert_props(src_node, vnf_node) + for model_tpl in safe_get(src_json_model, "node_templates"): + if model_tpl['name'] != vnf_node['vnf_id']: + continue + vnf_node['dependencies'] = [{ + 'key_name': requirement['name'], + 'vl_id': requirement['target_node_template_name']} for \ + requirement in safe_get(model_tpl, 'requirement_templates') if \ + safe_get(requirement, 'target_capability_name') == 'virtual_linkable'] + vnf_node['networks'] = [requirement['target_node_template_name'] for \ + requirement in safe_get(model_tpl, 'requirement_templates') if \ + safe_get(requirement, 'name') == 'dependency'] + return vnf_node + + +def convert_pnf_node(src_node, src_json_model): + pnf_node = {'pnf_id': src_node['template_name'], 'description': '', 'properties': {}} + convert_props(src_node, pnf_node) + pnf_node['cps'] = find_related_node(src_node['id'], src_json_model, 'virtualbinding') + return pnf_node + + +def convert_vl_node(src_node, src_node_list): + vl_node = {'vl_id': src_node['template_name'], 'description': '', 'properties': {}} + convert_props(src_node, vl_node) + vl_node['route_id'] = '' + for relation in safe_get(src_node, 'relationships'): + if safe_get(relation, 'type_name').endswith('.VirtualLinksTo'): + vl_node['route_id'] = find_node_name(relation['target_node_id'], src_node_list) + break + vl_node['route_external'] = (src_node['type_name'].find('.RouteExternalVL') > 0) + return vl_node + + +def convert_cp_node(src_node, src_node_list, model_type='NSD'): + cp_node = {'cp_id': src_node['template_name'], 'description': '', 'properties': {}} + convert_props(src_node, cp_node) + src_relationships = src_node['relationships'] + for relation in src_relationships: + if safe_get(relation, 'name') == 'virtualLink': + cp_node['vl_id'] = find_node_name(relation['target_node_id'], src_node_list) + elif safe_get(relation, 'name') == 'virtualbinding': + node_key = 'pnf_id' if model_type == 'NSD' else 'vdu_id' + cp_node[node_key] = find_node_name(relation['target_node_id'], src_node_list) + return cp_node + + +def convert_router_node(src_node, src_node_list): + router_node = {'router_id': src_node['template_name'], 'description': '', 'properties': {}} + convert_props(src_node, router_node) + for relation in src_node['relationships']: + if safe_get(relation, 'name') != 'external_virtual_link': + continue + router_node['external_vl_id'] = find_node_name(relation['target_node_id'], src_node_list) + router_node['external_ip_addresses'] = [] + if 'properties' not in relation: + continue + for prop_name, prop_info in relation['properties'].items(): + if prop_name == 'router_ip_address': + router_node['external_ip_addresses'].append(prop_info['value']) + break + return router_node + + +def convert_fp_node(src_node, src_node_list, src_json_model): + fp_node = {'fp_id': src_node['template_name'], 'description': '', + 'properties': {}, 'forwarder_list': []} + convert_props(src_node, fp_node) + for relation in safe_get(src_node, 'relationships'): + if safe_get(relation, 'name') != 'forwarder': + continue + forwarder_point = {'type': 'vnf'} + target_node_type = find_node_type(relation['target_node_id'], src_node_list).upper() + if target_node_type.find('.CP.') >= 0 or target_node_type.endswith('.CP'): + forwarder_point['type'] = 'cp' + forwarder_point['node_name'] = find_node_name(relation['target_node_id'], src_node_list) + forwarder_point['capability'] = '' + if forwarder_point['type'] == 'vnf': + for node_tpl in src_json_model["node_templates"]: + if fp_node['fp_id'] != node_tpl["name"]: + continue + for r_tpl in safe_get(node_tpl, "requirement_templates"): + if safe_get(r_tpl, "target_node_template_name") != forwarder_point['node_name']: + continue + forwarder_point['capability'] = safe_get(r_tpl, "target_capability_name") + break + break + fp_node['forwarder_list'].append(forwarder_point) + return fp_node + + +def convert_vnffg_group(src_group, src_group_list, src_node_list): + vnffg = {'vnffg_id': src_group['template_name'], 'description': '', + 'properties': {}, 'members': []} + convert_props(src_group, vnffg) + for member_node_id in src_group['member_node_ids']: + vnffg['members'].append(find_node_name(member_node_id, src_node_list)) + return vnffg + + +def convert_imagefile_node(src_node, src_node_list): + image_node = {'image_file_id': src_node['template_name'], 'description': '', + 'properties': {}} + convert_props(src_node, image_node) + return image_node + + +def convert_localstorage_node(src_node, src_node_list): + localstorage_node = {'local_storage_id': src_node['template_name'], 'description': '', + 'properties': {}} + convert_props(src_node, localstorage_node) + return localstorage_node + + +def convert_vdu_node(src_node, src_node_list, src_json_model): + vdu_node = {'vdu_id': src_node['template_name'], 'description': '', 'properties': {}, + 'image_file': '', 'local_storages': [], 'dependencies': [], 'nfv_compute': {}, + 'vls': [], 'artifacts': []} + convert_props(src_node, vdu_node) + + for relation in src_node['relationships']: + r_id, r_name = safe_get(relation, 'target_node_id'), safe_get(relation, 'name') + if r_name == 'guest_os': + vdu_node['image_file'] = find_node_name(r_id, src_node_list) + elif r_name == 'local_storage': + vdu_node['local_storages'].append(find_node_name(r_id, src_node_list)) + elif r_name.endswith('.AttachesTo'): + nt = find_node_type(r_id, src_node_list) + if nt.endswith('.BlockStorage.Local') or nt.endswith('.LocalStorage'): + vdu_node['local_storages'].append(find_node_name(r_id, src_node_list)) + + for capability in src_node['capabilities']: + if capability['name'] != 'nfv_compute': + continue + for prop_name, prop_info in capability['properties'].items(): + if 'value' in prop_info: + vdu_node['nfv_compute'][prop_name] = prop_info['value'] + + vdu_node['cps'] = find_related_node(src_node['id'], src_json_model, 'virtualbinding') + + for cp_node in vdu_node['cps']: + for src_cp_node in src_node_list: + if src_cp_node['template_name'] != cp_node: + continue + for relation in safe_get(src_cp_node, 'relationships'): + if relation['name'] != 'virtualLink': + continue + vl_node_name = find_node_name(relation['target_node_id'], src_node_list) + if vl_node_name not in vdu_node['vls']: + vdu_node['vls'].append(vl_node_name) + + for item in safe_get(src_node, 'artifacts'): + artifact = {'artifact_name': item['name'], 'type': item['type_name'], + 'file': item['source_path']} + vdu_node['artifacts'].append(artifact) + + return vdu_node + + +def convert_exposed_node(src_json, src_nodes, exposed): + for item in safe_get(safe_get(src_json, 'substitution'), 'requirements'): + exposed['external_cps'].append({'key_name': item['mapped_name'], + "cp_id": find_node_name(item['node_id'], src_nodes)}) + for item in safe_get(safe_get(src_json, 'substitution'), 'capabilities'): + exposed['forward_cps'].append({'key_name': item['mapped_name'], + "cp_id": find_node_name(item['node_id'], src_nodes)}) + + +def convert_vnffgs(src_json_inst, src_nodes): + vnffgs = [] + src_groups = safe_get(src_json_inst, 'groups') + for group in src_groups: + type_name = group['type_name'].upper() + if type_name.find('.VNFFG.') >= 0 or type_name.endswith('.VNFFG'): + vnffgs.append(convert_vnffg_group(group, src_groups, src_nodes)) + return vnffgs + + +def convert_common(src_json, target_json): + if isinstance(src_json, (unicode, str)): + src_json_dict = json.loads(src_json) + else: + src_json_dict = src_json + src_json_inst = src_json_dict["instance"] + src_json_model = src_json_dict["model"] if "model" in src_json_dict else {} + + target_json['metadata'] = convert_metadata(src_json_inst) + target_json['inputs'] = convert_inputs(src_json_inst) + target_json['vls'] = [] + target_json['cps'] = [] + target_json['routers'] = [] + + return src_json_inst, src_json_model + + +def convert_nsd_model(src_json): + target_json = {'vnfs': [], 'pnfs': [], 'fps': []} + src_json_inst, src_json_model = convert_common(src_json, target_json) + + src_nodes = src_json_inst['nodes'] + for node in src_nodes: + type_name = node['type_name'] + if type_name.find('.VNF.') > 0 or type_name.endswith('.VNF'): + target_json['vnfs'].append(convert_vnf_node(node, src_json_model)) + elif type_name.find('.PNF.') > 0 or type_name.endswith('.PNF'): + target_json['pnfs'].append(convert_pnf_node(node, src_json_model)) + elif type_name.find('.VL.') > 0 or type_name.endswith('.VL') \ + or node['type_name'].find('.RouteExternalVL') > 0: + target_json['vls'].append(convert_vl_node(node, src_nodes)) + elif type_name.find('.CP.') > 0 or type_name.endswith('.CP'): + target_json['cps'].append(convert_cp_node(node, src_nodes)) + elif type_name.find('.FP.') > 0 or type_name.endswith('.FP'): + target_json['fps'].append(convert_fp_node(node, src_nodes, src_json_model)) + elif type_name.endswith('.Router'): + target_json['routers'].append(convert_router_node(node, src_nodes)) + + target_json['vnffgs'] = convert_vnffgs(src_json_inst, src_nodes) + + target_json['ns_exposed'] = {'external_cps': [], 'forward_cps': []} + convert_exposed_node(src_json_inst, src_nodes, target_json['ns_exposed']) + return json.dumps(target_json) + + +def convert_vnfd_model(src_json): + target_json = {'image_files': [], 'local_storages': [], 'vdus': []} + src_json_inst, src_json_model = convert_common(src_json, target_json) + + src_nodes = src_json_inst['nodes'] + for node in src_nodes: + type_name = node['type_name'] + if type_name.endswith('.ImageFile'): + target_json['image_files'].append(convert_imagefile_node(node, src_nodes)) + elif type_name.endswith('.BlockStorage.Local') or type_name.endswith('.LocalStorage'): + target_json['local_storages'].append(convert_localstorage_node(node, src_nodes)) + elif type_name.find('.VDU.') > 0 or type_name.endswith('.VDU'): + target_json['vdus'].append(convert_vdu_node(node, src_nodes, src_json_model)) + elif type_name.find('.VL.') > 0 or type_name.endswith('.VL') \ + or node['type_name'].find('.RouteExternalVL') > 0: + target_json['vls'].append(convert_vl_node(node, src_nodes)) + elif type_name.find('.CP.') > 0 or type_name.endswith('.CP'): + target_json['cps'].append(convert_cp_node(node, src_nodes, 'VNFD')) + elif type_name.endswith('.Router'): + target_json['routers'].append(convert_router_node(node, src_nodes)) + + target_json['vnf_exposed'] = {'external_cps': [], 'forward_cps': []} + convert_exposed_node(src_json_inst, src_nodes, target_json['vnf_exposed']) + return json.dumps(target_json) + +if __name__ == '__main__': + src_json = json.dumps( + { + "instance":{ + "metadata":{ + "vendor":"ZTE", + "name":"VCPE_NS", + "csarVersion":"v1.0", + "csarType":"NSAR", + "csarProvider":"ZTE", + "version":1, + "invariant_id":"vcpe_ns_sff_1", + "id":"VCPE_NS", + "description":"vcpe_ns" + }, + "nodes":[ + { + "id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "type_name":"tosca.nodes.nfv.ext.FP", + "template_name":"path2", + "properties":{ + "symmetric":{ + "type_name":"boolean", + "value":False + }, + "policy":{ + "type_name":"tosca.datatypes.nfv.ext.FPPolicy", + "value":{ + "type":"ACL", + "criteria":{ + "dest_port_range":"1-100", + "ip_protocol":"tcp", + "source_ip_range":[ + "119.1.1.1-119.1.1.10" + ], + "dest_ip_range":[ + {"get_input":"NatIpRange"} + ], + "dscp":0, + "source_port_range":"1-100" + } + } + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + } + ], + "relationships":[ + { + "name":"forwarder", + "source_requirement_index":0, + "target_node_id":"m6000_data_out_qeukdtf6g87cnparxi51fa8s6" + }, + { + "name":"forwarder", + "source_requirement_index":1, + "target_node_id":"m600_tunnel_cp_imwfk5l48ljz0g9knc6d68hv5" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"VNAT_cfdljtspvkp234irka59wgab0", + "target_capability_name":"feature" + } + ] + }, + { + "id":"path1_bv53fblv26hawr8dj4fxe2rsd", + "type_name":"tosca.nodes.nfv.ext.FP", + "template_name":"path1", + "properties":{ + "symmetric":{ + "type_name":"boolean", + "value":True + }, + "policy":{ + "type_name":"tosca.datatypes.nfv.ext.FPPolicy", + "value":{ + "type":"ACL", + "criteria":{ + "dest_port_range":"1-100", + "ip_protocol":"tcp", + "source_ip_range":[ + "1-100" + ], + "dest_ip_range":[ + "1-100" + ], + "dscp":4, + "source_port_range":"1-100" + } + } + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + } + ], + "relationships":[ + { + "name":"forwarder", + "source_requirement_index":0, + "target_node_id":"m6000_data_in_eldly5txw4frny3cc349uz3nc" + }, + { + "name":"forwarder", + "source_requirement_index":1, + "target_node_id":"m600_tunnel_cp_imwfk5l48ljz0g9knc6d68hv5" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"VFW_57z0ua89aiyl8ncvw7h7mjf34", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":3, + "target_node_id":"VNAT_cfdljtspvkp234irka59wgab0", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":4, + "target_node_id":"m600_tunnel_cp_imwfk5l48ljz0g9knc6d68hv5" + }, + { + "name":"forwarder", + "source_requirement_index":5, + "target_node_id":"m6000_data_out_qeukdtf6g87cnparxi51fa8s6" + } + ] + }, + { + "id":"m6000_data_out_qeukdtf6g87cnparxi51fa8s6", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "template_name":"m6000_data_out", + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"11-22-33-22-11-44" + }, + "interface_name":{ + "type_name":"string", + "value":"xgei-0/4/1/5" + }, + "ip_address":{ + "type_name":"string", + "value":"176.1.1.2" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"virtualbinding", + "source_requirement_index":0, + "target_node_id":"m6000_s_7qtzo5nuocyfmebc6kp9raq18", + "target_capability_name":"feature" + }, + { + "name":"virtualLink", + "source_requirement_index":1, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"VFW_57z0ua89aiyl8ncvw7h7mjf34", + "type_name":"tosca.nodes.nfv.ext.zte.VNF.VFW", + "template_name":"VFW", + "properties":{ + "is_shared":{ + "type_name":"boolean", + "value":False + }, + "plugin_info":{ + "type_name":"string", + "value":"vbrasplugin_1.0" + }, + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "vnf_extend_type":{ + "type_name":"string", + "value":"driver" + }, + "name":{ + "type_name":"string", + "value":"VFW" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "cross_dc":{ + "type_name":"boolean", + "value":False + }, + "vnf_type":{ + "type_name":"string", + "value":"VFW" + }, + "vnfd_version":{ + "type_name":"string", + "value":"1.0.0" + }, + "id":{ + "type_name":"string", + "value":"vcpe_vfw_zte_1_0" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":True + }, + "adjust_vnf_capacity":{ + "type_name":"boolean", + "value":True + }, + "vmnumber_overquota_alarm":{ + "type_name":"boolean", + "value":True + }, + "csarProvider":{ + "type_name":"string", + "value":"ZTE" + }, + "csarVersion":{ + "type_name":"string", + "value":"v1.0" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + }, + "csarType":{ + "type_name":"string", + "value":"NFAR" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + }, + { + "name":"vfw_fw_inout", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"vfw_ctrl_by_manager_cp", + "source_requirement_index":0, + "target_node_id":"ext_mnet_net_au2otee5mcy0dnpqykj487zr3", + "target_capability_name":"feature" + }, + { + "name":"vfw_data_cp", + "source_requirement_index":1, + "target_node_id":"sfc_data_network_vx3pc1oahn0k0pa5q722yafee", + "target_capability_name":"feature" + }, + { + "name":"virtualLink", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":3, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"m600_tunnel_cp_imwfk5l48ljz0g9knc6d68hv5", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "template_name":"m600_tunnel_cp", + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"00-11-00-22-33-00" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/13" + }, + "ip_address":{ + "type_name":"string", + "value":"191.167.100.5" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"virtualLink", + "source_requirement_index":0, + "target_node_id":"ext_datanet_net_qtqzlx5dsthzs883hxjn6hyhd", + "target_capability_name":"feature" + }, + { + "name":"virtualbinding", + "source_requirement_index":1, + "target_node_id":"m6000_s_7qtzo5nuocyfmebc6kp9raq18", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"ext_mnet_net_au2otee5mcy0dnpqykj487zr3", + "type_name":"tosca.nodes.nfv.ext.VL.Vmware", + "template_name":"ext_mnet_net", + "properties":{ + "name":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "id":"m6000_data_in_eldly5txw4frny3cc349uz3nc", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "template_name":"m6000_data_in", + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"11-22-33-22-11-41" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/7" + }, + "ip_address":{ + "type_name":"string", + "value":"1.1.1.1" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + }, + "bond":{ + "type_name":"string", + "value":"none" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"virtualbinding", + "source_requirement_index":0, + "target_node_id":"m6000_s_7qtzo5nuocyfmebc6kp9raq18", + "target_capability_name":"feature" + }, + { + "name":"virtualLink", + "source_requirement_index":1, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"ext_datanet_net_qtqzlx5dsthzs883hxjn6hyhd", + "type_name":"tosca.nodes.nfv.ext.VL.Vmware", + "template_name":"ext_datanet_net", + "properties":{ + "name":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "id":"m600_mnt_cp_l3488y2a8ilyfdn0l89ni4os7", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "template_name":"m600_mnt_cp", + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"00-11-00-22-33-11" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/1" + }, + "ip_address":{ + "type_name":"string", + "value":"10.46.244.51" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + }, + "bond":{ + "type_name":"string", + "value":"none" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"virtualLink", + "source_requirement_index":0, + "target_node_id":"ext_mnet_net_au2otee5mcy0dnpqykj487zr3", + "target_capability_name":"feature" + }, + { + "name":"virtualbinding", + "source_requirement_index":1, + "target_node_id":"m6000_s_7qtzo5nuocyfmebc6kp9raq18", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"sfc_data_network_vx3pc1oahn0k0pa5q722yafee", + "type_name":"tosca.nodes.nfv.ext.zte.VL", + "template_name":"sfc_data_network", + "properties":{ + "name":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "is_predefined":{ + "type_name":"boolean", + "value":False + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "id":"m6000_s_7qtzo5nuocyfmebc6kp9raq18", + "type_name":"tosca.nodes.nfv.ext.PNF", + "template_name":"m6000_s", + "properties":{ + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "pnf_type":{ + "type_name":"string", + "value":"m6000s" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "management_address":{ + "type_name":"string", + "value":"111111" + }, + "id":{ + "type_name":"string", + "value":"m6000_s" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":False + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtualBinding", + "type_name":"tosca.capabilities.nfv.VirtualBindable" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"forwarder", + "source_requirement_index":0, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + }, + { + "id":"VNAT_cfdljtspvkp234irka59wgab0", + "type_name":"tosca.nodes.nfv.ext.zte.VNF.VNAT", + "template_name":"VNAT", + "properties":{ + "is_shared":{ + "type_name":"boolean", + "value":False + }, + "plugin_info":{ + "type_name":"string", + "value":"vbrasplugin_1.0" + }, + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "name":{ + "type_name":"string", + "value":"VNAT" + }, + "vnf_extend_type":{ + "type_name":"string", + "value":"driver" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "cross_dc":{ + "type_name":"boolean", + "value":False + }, + "vnf_type":{ + "type_name":"string", + "value":"VNAT" + }, + "vnfd_version":{ + "type_name":"string", + "value":"1.0.0" + }, + "id":{ + "type_name":"string", + "value":"vcpe_vnat_zte_1" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":True + }, + "adjust_vnf_capacity":{ + "type_name":"boolean", + "value":True + }, + "vmnumber_overquota_alarm":{ + "type_name":"boolean", + "value":True + }, + "csarProvider":{ + "type_name":"string", + "value":"ZTE" + }, + "NatIpRange":{ + "type_name":"string", + "value":"192.167.0.10-192.168.0.20" + }, + "csarVersion":{ + "type_name":"string", + "value":"v1.0" + }, + "csarType":{ + "type_name":"string", + "value":"NFAR" + } + }, + "interfaces":[ + { + "name":"Standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "capabilities":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + }, + { + "name":"vnat_fw_inout", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "relationships":[ + { + "name":"vnat_ctrl_by_manager_cp", + "source_requirement_index":0, + "target_node_id":"ext_mnet_net_au2otee5mcy0dnpqykj487zr3", + "target_capability_name":"feature" + }, + { + "name":"vnat_data_cp", + "source_requirement_index":1, + "target_node_id":"sfc_data_network_vx3pc1oahn0k0pa5q722yafee", + "target_capability_name":"feature" + }, + { + "name":"virtualLink", + "source_requirement_index":2, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + }, + { + "name":"forwarder", + "source_requirement_index":3, + "target_node_id":"path2_kgmfqr5ldqs9lj3oscrgxqefc", + "target_capability_name":"feature" + } + ] + } + ], + "groups":[ + { + "id":"vnffg1_wk1aqhk6exoh5fmds2unu0uyc", + "type_name":"tosca.groups.nfv.VNFFG", + "template_name":"vnffg1", + "properties":{ + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "connection_point":{ + "type_name":"list", + "value":[ + "m6000_data_in", + "m600_tunnel_cp", + "m6000_data_out" + ] + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "constituent_vnfs":{ + "type_name":"list", + "value":[ + "VFW", + "VNAT" + ] + }, + "number_of_endpoints":{ + "type_name":"integer", + "value":3 + }, + "dependent_virtual_link":{ + "type_name":"list", + "value":[ + "sfc_data_network", + "ext_datanet_net", + "ext_mnet_net" + ] + } + }, + "interfaces":[ + { + "name":"standard", + "description":"This lifecycle interface defines the essential, normative operations that TOSCA nodes may support.", + "type_name":"tosca.interfaces.node.lifecycle.Standard", + "operations":[ + { + "name":"create", + "description":"Standard lifecycle create operation." + }, + { + "name":"stop", + "description":"Standard lifecycle stop operation." + }, + { + "name":"start", + "description":"Standard lifecycle start operation." + }, + { + "name":"delete", + "description":"Standard lifecycle delete operation." + }, + { + "name":"configure", + "description":"Standard lifecycle configure operation." + } + ] + } + ], + "member_node_ids":[ + "path1_bv53fblv26hawr8dj4fxe2rsd", + "path2_kgmfqr5ldqs9lj3oscrgxqefc" + ] + } + ], + "substitution":{ + "node_type_name":"tosca.nodes.nfv.NS.VCPE_NS" + }, + "inputs":{ + "externalDataNetworkName":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "sfc_data_network":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "NatIpRange":{ + "type_name":"string", + "value":"192.167.0.10-192.168.0.20" + }, + "externalManageNetworkName":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + } + } + }, + "model":{ + "metadata":{ + "vendor":"ZTE", + "name":"VCPE_NS", + "csarVersion":"v1.0", + "csarType":"NSAR", + "csarProvider":"ZTE", + "version":1, + "invariant_id":"vcpe_ns_sff_1", + "id":"VCPE_NS", + "description":"vcpe_ns" + }, + "node_templates":[ + { + "name":"path2", + "type_name":"tosca.nodes.nfv.ext.FP", + "default_instances":1, + "min_instances":0, + "properties":{ + "symmetric":{ + "type_name":"boolean", + "value":False + }, + "policy":{ + "type_name":"tosca.datatypes.nfv.ext.FPPolicy", + "value":{ + "type":"ACL", + "criteria":{ + "dest_port_range":"1-100", + "ip_protocol":"tcp", + "source_ip_range":[ + "119.1.1.1-119.1.1.10" + ], + "dest_ip_range":[ + {"get_input":"NatIpRange"} + ], + "dscp":0, + "source_port_range":"1-100" + } + } + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ed0288a10>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + } + ], + "requirement_templates":[ + { + "name":"forwarder", + "target_node_template_name":"m6000_data_out" + }, + { + "name":"forwarder", + "target_node_template_name":"m600_tunnel_cp" + }, + { + "name":"forwarder", + "target_node_template_name":"VNAT", + "target_capability_name":"vnat_fw_inout" + } + ] + }, + { + "name":"path1", + "type_name":"tosca.nodes.nfv.ext.FP", + "default_instances":1, + "min_instances":0, + "properties":{ + "symmetric":{ + "type_name":"boolean", + "value":True + }, + "policy":{ + "type_name":"tosca.datatypes.nfv.ext.FPPolicy", + "value":{ + "type":"ACL", + "criteria":{ + "dest_port_range":"1-100", + "ip_protocol":"tcp", + "source_ip_range":[ + "1-100" + ], + "dest_ip_range":[ + "1-100" + ], + "dscp":4, + "source_port_range":"1-100" + } + } + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec81df090>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + } + ], + "requirement_templates":[ + { + "name":"forwarder", + "target_node_template_name":"m6000_data_in" + }, + { + "name":"forwarder", + "target_node_template_name":"m600_tunnel_cp" + }, + { + "name":"forwarder", + "target_node_template_name":"VFW", + "target_capability_name":"vfw_fw_inout" + }, + { + "name":"forwarder", + "target_node_template_name":"VNAT", + "target_capability_name":"vnat_fw_inout" + }, + { + "name":"forwarder", + "target_node_template_name":"m600_tunnel_cp" + }, + { + "name":"forwarder", + "target_node_template_name":"m6000_data_out" + } + ] + }, + { + "name":"m6000_data_out", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "default_instances":1, + "min_instances":0, + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"11-22-33-22-11-44" + }, + "interface_name":{ + "type_name":"string", + "value":"xgei-0/4/1/5" + }, + "ip_address":{ + "type_name":"string", + "value":"176.1.1.2" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec82c6610>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"virtualbinding", + "target_node_template_name":"m6000_s", + "target_capability_name":"virtualBinding" + }, + { + "name":"virtualLink", + "target_node_type_name":"tosca.nodes.Root" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"VFW", + "type_name":"tosca.nodes.nfv.ext.zte.VNF.VFW", + "default_instances":1, + "min_instances":0, + "properties":{ + "is_shared":{ + "type_name":"boolean", + "value":False + }, + "plugin_info":{ + "type_name":"string", + "value":"vbrasplugin_1.0" + }, + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "vnf_extend_type":{ + "type_name":"string", + "value":"driver" + }, + "name":{ + "type_name":"string", + "value":"VFW" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "cross_dc":{ + "type_name":"boolean", + "value":False + }, + "vnf_type":{ + "type_name":"string", + "value":"VFW" + }, + "vnfd_version":{ + "type_name":"string", + "value":"1.0.0" + }, + "id":{ + "type_name":"string", + "value":"vcpe_vfw_zte_1_0" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":True + }, + "adjust_vnf_capacity":{ + "type_name":"boolean", + "value":True + }, + "vmnumber_overquota_alarm":{ + "type_name":"boolean", + "value":True + }, + "csarProvider":{ + "type_name":"string", + "value":"ZTE" + }, + "csarVersion":{ + "type_name":"string", + "value":"v1.0" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + }, + "csarType":{ + "type_name":"string", + "value":"NFAR" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec8281950>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + }, + { + "name":"vfw_fw_inout", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"vfw_ctrl_by_manager_cp", + "target_node_template_name":"ext_mnet_net", + "target_capability_name":"virtual_linkable" + }, + { + "name":"vfw_data_cp", + "target_node_template_name":"sfc_data_network", + "target_capability_name":"virtual_linkable" + }, + { + "name":"virtualLink", + "target_node_type_name":"tosca.nodes.Root" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"m600_tunnel_cp", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "default_instances":1, + "min_instances":0, + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"00-11-00-22-33-00" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/13" + }, + "ip_address":{ + "type_name":"string", + "value":"191.167.100.5" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x1ae39d0>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"virtualLink", + "target_node_template_name":"ext_datanet_net", + "target_capability_name":"virtual_linkable" + }, + { + "name":"virtualbinding", + "target_node_template_name":"m6000_s", + "target_capability_name":"virtualBinding" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"ext_mnet_net", + "type_name":"tosca.nodes.nfv.ext.VL.Vmware", + "default_instances":1, + "min_instances":0, + "properties":{ + "name":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ed00f89d0>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "name":"m6000_data_in", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "default_instances":1, + "min_instances":0, + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"11-22-33-22-11-41" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/7" + }, + "ip_address":{ + "type_name":"string", + "value":"1.1.1.1" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + }, + "bond":{ + "type_name":"string", + "value":"none" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x1745710>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"virtualbinding", + "target_node_template_name":"m6000_s", + "target_capability_name":"virtualBinding" + }, + { + "name":"virtualLink", + "target_node_type_name":"tosca.nodes.Root" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"ext_datanet_net", + "type_name":"tosca.nodes.nfv.ext.VL.Vmware", + "default_instances":1, + "min_instances":0, + "properties":{ + "name":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8eac063990>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "name":"m600_mnt_cp", + "type_name":"tosca.nodes.nfv.ext.zte.CP", + "default_instances":1, + "min_instances":0, + "properties":{ + "direction":{ + "type_name":"string", + "value":"bidirectional" + }, + "vnic_type":{ + "type_name":"string", + "value":"normal" + }, + "bandwidth":{ + "type_name":"integer", + "value":0 + }, + "mac_address":{ + "type_name":"string", + "value":"00-11-00-22-33-11" + }, + "interface_name":{ + "type_name":"string", + "value":"gei-0/4/0/1" + }, + "ip_address":{ + "type_name":"string", + "value":"10.46.244.51" + }, + "order":{ + "type_name":"integer", + "value":0 + }, + "sfc_encapsulation":{ + "type_name":"string", + "value":"mac" + }, + "bond":{ + "type_name":"string", + "value":"none" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec81264d0>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"virtualLink", + "target_node_template_name":"ext_mnet_net", + "target_capability_name":"virtual_linkable" + }, + { + "name":"virtualbinding", + "target_node_template_name":"m6000_s", + "target_capability_name":"virtualBinding" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"sfc_data_network", + "type_name":"tosca.nodes.nfv.ext.zte.VL", + "default_instances":1, + "min_instances":0, + "properties":{ + "name":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "dhcp_enabled":{ + "type_name":"boolean", + "value":True + }, + "is_predefined":{ + "type_name":"boolean", + "value":False + }, + "location_info":{ + "type_name":"tosca.datatypes.nfv.ext.LocationInfo", + "value":{ + "tenant":"admin", + "vimid":2, + "availability_zone":"nova" + } + }, + "ip_version":{ + "type_name":"integer", + "value":4 + }, + "mtu":{ + "type_name":"integer", + "value":1500 + }, + "network_name":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "network_type":{ + "type_name":"string", + "value":"vlan" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec813c6d0>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtual_linkable", + "type_name":"tosca.capabilities.nfv.VirtualLinkable" + } + ] + }, + { + "name":"m6000_s", + "type_name":"tosca.nodes.nfv.ext.PNF", + "default_instances":1, + "min_instances":0, + "properties":{ + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "pnf_type":{ + "type_name":"string", + "value":"m6000s" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "management_address":{ + "type_name":"string", + "value":"111111" + }, + "id":{ + "type_name":"string", + "value":"m6000_s" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":False + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec8132490>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"virtualBinding", + "type_name":"tosca.capabilities.nfv.VirtualBindable" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + }, + { + "name":"VNAT", + "type_name":"tosca.nodes.nfv.ext.zte.VNF.VNAT", + "default_instances":1, + "min_instances":0, + "properties":{ + "is_shared":{ + "type_name":"boolean", + "value":False + }, + "plugin_info":{ + "type_name":"string", + "value":"vbrasplugin_1.0" + }, + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "request_reclassification":{ + "type_name":"boolean", + "value":False + }, + "name":{ + "type_name":"string", + "value":"VNAT" + }, + "vnf_extend_type":{ + "type_name":"string", + "value":"driver" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "cross_dc":{ + "type_name":"boolean", + "value":False + }, + "vnf_type":{ + "type_name":"string", + "value":"VNAT" + }, + "vnfd_version":{ + "type_name":"string", + "value":"1.0.0" + }, + "id":{ + "type_name":"string", + "value":"vcpe_vnat_zte_1" + }, + "nsh_aware":{ + "type_name":"boolean", + "value":True + }, + "adjust_vnf_capacity":{ + "type_name":"boolean", + "value":True + }, + "vmnumber_overquota_alarm":{ + "type_name":"boolean", + "value":True + }, + "csarProvider":{ + "type_name":"string", + "value":"ZTE" + }, + "NatIpRange":{ + "type_name":"string", + "value":"192.167.0.10-192.168.0.20" + }, + "csarVersion":{ + "type_name":"string", + "value":"v1.0" + }, + "csarType":{ + "type_name":"string", + "value":"NFAR" + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x1bba810>" + ], + "capability_templates":[ + { + "name":"feature", + "type_name":"tosca.capabilities.Node" + }, + { + "name":"forwarder", + "type_name":"tosca.capabilities.nfv.Forwarder" + }, + { + "name":"vnat_fw_inout", + "type_name":"tosca.capabilities.nfv.Forwarder" + } + ], + "requirement_templates":[ + { + "name":"vnat_ctrl_by_manager_cp", + "target_node_template_name":"ext_mnet_net", + "target_capability_name":"virtual_linkable" + }, + { + "name":"vnat_data_cp", + "target_node_template_name":"sfc_data_network", + "target_capability_name":"virtual_linkable" + }, + { + "name":"virtualLink", + "target_node_type_name":"tosca.nodes.Root" + }, + { + "name":"forwarder", + "target_node_type_name":"tosca.nodes.Root" + } + ] + } + ], + "group_templates":[ + { + "name":"vnffg1", + "type_name":"tosca.groups.nfv.VNFFG", + "properties":{ + "vendor":{ + "type_name":"string", + "value":"zte" + }, + "connection_point":{ + "type_name":"list", + "value":[ + "m6000_data_in", + "m600_tunnel_cp", + "m6000_data_out" + ] + }, + "version":{ + "type_name":"string", + "value":"1.0" + }, + "constituent_vnfs":{ + "type_name":"list", + "value":[ + "VFW", + "VNAT" + ] + }, + "number_of_endpoints":{ + "type_name":"integer", + "value":3 + }, + "dependent_virtual_link":{ + "type_name":"list", + "value":[ + "sfc_data_network", + "ext_datanet_net", + "ext_mnet_net" + ] + } + }, + "interface_templates":[ + "<aria.modeling.model_elements.InterfaceTemplate object at 0x7f8ec811cd10>" + ], + "member_node_template_names":[ + "path1", + "path2" + ] + } + ], + "substitution_template":{ + "node_type_name":"tosca.nodes.nfv.NS.VCPE_NS" + }, + "inputs":{ + "externalDataNetworkName":{ + "type_name":"string", + "value":"vlan_4004_tunnel_net" + }, + "sfc_data_network":{ + "type_name":"string", + "value":"sfc_data_network" + }, + "NatIpRange":{ + "type_name":"string", + "value":"192.167.0.10-192.168.0.20" + }, + "externalManageNetworkName":{ + "type_name":"string", + "value":"vlan_4008_mng_net" + }, + "externalPluginManageNetworkName":{ + "type_name":"string", + "value":"vlan_4007_plugin_net" + } + } + } + } + ) + print convert_nsd_model(src_json) + + + + diff --git a/newton/newton/pub/utils/values.py b/newton/newton/pub/utils/values.py new file mode 100644 index 00000000..a5b5e3a3 --- /dev/null +++ b/newton/newton/pub/utils/values.py @@ -0,0 +1,22 @@ +# 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. + + +def ignore_case_get(args, key, def_val=""): + if not key: + return def_val + if key in args: + return args[key] + for old_key in args: + if old_key.upper() == key.upper(): + return args[old_key] + return def_val + diff --git a/newton/newton/samples/__init__.py b/newton/newton/samples/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/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/newton/newton/samples/tests.py b/newton/newton/samples/tests.py new file mode 100644 index 00000000..50b571a3 --- /dev/null +++ b/newton/newton/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 = json.loads(response.content) + self.assertEqual({"status": "active"}, resp_data) diff --git a/newton/newton/samples/urls.py b/newton/newton/samples/urls.py new file mode 100644 index 00000000..6f1b23a8 --- /dev/null +++ b/newton/newton/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 newton.samples import views + +urlpatterns = [ + url(r'^samples/$', views.SampleList.as_view()), ] diff --git a/newton/newton/samples/views.py b/newton/newton/samples/views.py new file mode 100644 index 00000000..e51044ad --- /dev/null +++ b/newton/newton/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/newton/newton/settings.py b/newton/newton/settings.py new file mode 100644 index 00000000..8a5cc010 --- /dev/null +++ b/newton/newton/settings.py @@ -0,0 +1,140 @@ +# 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 + +import redisco + +from newton.pub.config.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWD +from newton.pub.config.config import DB_NAME, DB_IP, DB_USER, DB_PASSWD, DB_PORT + +# 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', + 'newton.pub.database', +] + +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 = 'newton.urls' + +WSGI_APPLICATION = 'newton.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', + ) +} + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': DB_NAME, + 'HOST': DB_IP, + 'PORT': DB_PORT, + 'USER': DB_USER, + 'PASSWORD': DB_PASSWD, + }, +} + +redisco.connection_setup(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWD, db=0) +# CACHE_BACKEND = 'redis_cache.cache://%s@%s:%s' % (REDIS_PASSWD, REDIS_HOST, REDIS_PORT) + +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': { + 'newton_handler': { + 'level': 'DEBUG', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': os.path.join(BASE_DIR, 'logs/runtime_newton.log'), + 'formatter': 'standard', + 'maxBytes': 1024 * 1024 * 50, + 'backupCount': 5, + }, + }, + + 'loggers': { + 'newton': { + 'handlers': ['newton_handler'], + 'level': 'DEBUG', + 'propagate': False + }, + } +} + +if 'test' in sys.argv: + from newton.pub.config import config + config.REG_TO_MSB_WHEN_START = False + DATABASES = {} + DATABASES['default'] = { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } + 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/newton/newton/swagger/__init__.py b/newton/newton/swagger/__init__.py new file mode 100644 index 00000000..802f3fba --- /dev/null +++ b/newton/newton/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/newton/newton/swagger/multivim.flavor.swagger.json b/newton/newton/swagger/multivim.flavor.swagger.json new file mode 100644 index 00000000..60dc7d8b --- /dev/null +++ b/newton/newton/swagger/multivim.flavor.swagger.json @@ -0,0 +1,397 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/flavors": { + "post": { + "tags": [ + "vim flavors" + ], + "summary": "create a flavor", + "description": "create a flavor", + "operationId": "create_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim flavor request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimFlavor" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query vim flavors list", + "description": "query vim flavors list", + "operationId": "query_vim_flavors", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim flavors request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimFlavors" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/flavors/{flavorid}": { + "delete": { + "tags": [ + "vim flavors" + ], + "summary": "delete specific vim flavor", + "description": "delete specific vim flavor", + "operationId": "delete_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + }, + "get": { + "tags": [ + "vim flavors" + ], + "summary": "query specific vim flavor", + "description": "query specific vim flavor", + "operationId": "query_vim_flavor", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "flavorid", + "in": "path", + "description": "vim flavor id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimFlavorInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim flavor is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimFlavor": { + "type": "object", + "required": [ + "vcpu", + "name", + "memory", + "disk" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + } + } + }, + "VimFlavorExtraSpecInfo": { + "type": "object", + "properties": { + "keyName": { + "type": "string", + "description": "extra spec key" + }, + "value": { + "type": "string", + "description": "extra spec value" + } + } + }, + "ListVimFlavors": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "flavor name to filter flavor list" + }, + "limit": { + "type": "integer", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "flavor ID of the last-seen item" + } + } + }, + "VimFlavorsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "flavors" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "flavors": { + "type": "array", + "description": "flavor list information", + "items": { + "$ref": "#/definitions/VimFlavorInfo" + } + } + } + }, + "VimFlavorInfo": { + "type": "object", + "required": [ + "name", + "id", + "vcpu", + "memory", + "disk", + "ephemeral", + "swap", + "isPublic" + ], + "properties": { + "name": { + "type": "string", + "description": "flavor name" + }, + "id": { + "type": "string", + "description": "flavor UUID" + }, + "vcpu": { + "type": "integer", + "description": "virtual cpu number" + }, + "memory": { + "type": "integer", + "description": "memory size" + }, + "disk": { + "type": "integer", + "description": "The size of the root disk" + }, + "ephemeral": { + "type": "integer", + "description": "The size of the ephemeral disk" + }, + "swap": { + "type": "integer", + "description": "The size of the swap disk" + }, + "isPublic": { + "type": "boolean", + "description": "whether the flavor is public" + }, + "extraSpecs": { + "type": "array", + "description": "list of extra specs", + "items": { + "$ref": "#/definitions/VimFlavorExtraSpecInfo" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.host.swagger.json b/newton/newton/swagger/multivim.host.swagger.json new file mode 100644 index 00000000..db24a17c --- /dev/null +++ b/newton/newton/swagger/multivim.host.swagger.json @@ -0,0 +1,183 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/hosts": { + "get": { + "tags": [ + "vim hosts" + ], + "summary": "query vim hosts list", + "description": "query vim hosts list", + "operationId": "query_vim_hosts", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim hosts request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimHosts" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimHostsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim host is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/hosts/{hostname}": { + "get": { + "tags": [ + "vim hosts" + ], + "summary": "query specific vim host", + "description": "query specific vim host", + "operationId": "query_vim_host", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "hostname", + "in": "path", + "description": "vim host name", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimHostInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim host is not accessable" + } + } + } + } + }, + "definitions": { + "VimHostsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "hosts" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "hosts": { + "type": "array", + "description": "list of host information", + "items": { + "$ref": "#/definitions/VimHostInfo" + } + } + } + }, + "VimHostInfo": { + "type": "object", + "required": [ + "name", + "service" + ], + "properties": { + "name": { + "type": "string", + "description": "host name" + }, + "service": { + "type": "string", + "description": "service name running on the host" + }, + "zone": { + "type": "string", + "description": "available zone name of the host" + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.image.swagger.json b/newton/newton/swagger/multivim.image.swagger.json new file mode 100644 index 00000000..b6102ec5 --- /dev/null +++ b/newton/newton/swagger/multivim.image.swagger.json @@ -0,0 +1,384 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/images": { + "post": { + "tags": [ + "vim images" + ], + "summary": "create a image", + "description": "create a image", + "operationId": "create_vim_image", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim image request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimImage" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimImageInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim image is not accessable" + } + } + }, + "get": { + "tags": [ + "vim images" + ], + "summary": "query vim images list", + "description": "query vim images list", + "operationId": "query_vim_images", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim images request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimImages" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimImagesInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim image is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/images/{imageid}": { + "delete": { + "tags": [ + "vim images" + ], + "summary": "delete specific vim image", + "description": "delete specific vim image", + "operationId": "delete_vim_image", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "imageid", + "in": "path", + "description": "vim image id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim image is not accessable" + } + } + }, + "get": { + "tags": [ + "vim images" + ], + "summary": "query specific vim image", + "description": "query specific vim image", + "operationId": "query_vim_image", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "imageid", + "in": "path", + "description": "vim image id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimImageInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim image is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimImage": { + "type": "object", + "required": [ + "imagePath", + "name", + "imageType", + "containerFormat" + ], + "properties": { + "name": { + "type": "string", + "description": "image name" + }, + "imageType": { + "type": "string", + "description": "image type: ami, ari, aki, vhd, vhdx, vmdk, raw, qcow2, vdi, iso" + }, + "imagePath": { + "type": "string", + "description": "image url to catalog" + }, + "containerFormat": { + "type": "string", + "description": "image container format: ami, ari, aki, bare, ovf, ova, docker" + }, + "visibility": { + "type": "string", + "description": "public, private, shared, or community" + }, + "properties": { + "type": "array", + "description": "list of properties", + "items": { + "$ref": "#/definitions/VimImagePropertyInfo" + } + } + } + }, + "VimImagePropertyInfo": { + "type": "object", + "properties": { + "keyName": { + "type": "string", + "description": "property name" + }, + "value": { + "type": "string", + "description": "property value" + } + } + }, + "ListVimImages": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "image name to filter image list" + }, + "limit": { + "type": "string", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "image ID of the last-seen item" + } + } + }, + "VimImagesInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "images" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "images": { + "type": "array", + "description": "image list information", + "items": { + "$ref": "#/definitions/VimImageInfo" + } + } + } + }, + "VimImageInfo": { + "type": "object", + "required": [ + "name", + "status", + "id" + ], + "properties": { + "name": { + "type": "string", + "description": "image name" + }, + "id": { + "type": "string", + "description": "image UUID" + }, + "imageType": { + "type": "string", + "description": "image type: ami, ari, aki, vhd, vhdx, vmdk, raw, qcow2, vdi, iso" + }, + "imagePath": { + "type": "string", + "description": "image url to catalog" + }, + "containerFormat": { + "type": "string", + "description": "image container format: ami, ari, aki, bare, ovf, ova, docker" + }, + "visibility": { + "type": "string", + "description": "public, private, shared, or community" + }, + "properties": { + "type": "array", + "description": "list of properties", + "items": { + "$ref": "#/definitions/VimImagePropertyInfo" + } + }, + "status": { + "type": "string", + "description": "image status" + }, + "size": { + "type": "string", + "description": "image size" + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.limit.swagger.json b/newton/newton/swagger/multivim.limit.swagger.json new file mode 100644 index 00000000..f5605b5c --- /dev/null +++ b/newton/newton/swagger/multivim.limit.swagger.json @@ -0,0 +1,158 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/limits": { + "get": { + "tags": [ + "vim limits" + ], + "summary": "query vim limits list", + "description": "query vim limits list", + "operationId": "query_vim_limits", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimLimitsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim limits is not accessable" + } + } + } + } + }, + "definitions": { + "VimLimitsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "maxPersonality": { + "type": "integer", + "description": "The number of allowed injected files for each tenant" + }, + "maxPersonalitySize": { + "type": "integer", + "description": "The number of allowed bytes of content for each injected file" + }, + "maxServerGroupMembers": { + "type": "integer", + "description": "The number of allowed members for each server group" + }, + "maxServerGroups": { + "type": "integer", + "description": "The number of allowed server groups for each tenant" + }, + "maxServerMeta": { + "type": "integer", + "description": "The number of allowed metadata items for each instance" + }, + "maxTotalCores": { + "type": "integer", + "description": "The number of allowed instance cores for each tenant" + }, + "maxTotalInstances": { + "type": "integer", + "description": "The number of allowed instances for each tenant" + }, + "maxTotalKeypairs": { + "type": "integer", + "description": "The number of allowed key pairs for each user" + }, + "maxTotalRAMSize": { + "type": "integer", + "description": "The amount of allowed instance RAM, in MB, for each tenant" + }, + "maxTotalVolumeGigabytes": { + "type": "integer", + "description": "The maximum total amount of volumes, in gibibytes (GiB)." + }, + "maxTotalVolumes": { + "type": "integer", + "description": "The maximum number of volumes" + }, + "totalGigabytesUsed": { + "type": "integer", + "description": "The total number of gibibytes (GiB) used" + }, + "network": { + "type": "integer", + "description": "The number of networks allowed for each project" + }, + "subnet": { + "type": "integer", + "description": "The number of subnets allowed for each project" + }, + "subnetpool": { + "type": "integer", + "description": "The number of subnet pools allowed for each project" + }, + "security_group_rule": { + "type": "integer", + "description": "The number of security group rules allowed for each project" + }, + "security_group": { + "type": "integer", + "description": "The number of security groups allowed for each project" + }, + "router": { + "type": "integer", + "description": "The number of routers allowed for each project" + }, + "port": { + "type": "integer", + "description": "The number of ports allowed for each project" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.network.swagger.json b/newton/newton/swagger/multivim.network.swagger.json new file mode 100644 index 00000000..fb120b29 --- /dev/null +++ b/newton/newton/swagger/multivim.network.swagger.json @@ -0,0 +1,360 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/networks": { + "post": { + "tags": [ + "vim networks" + ], + "summary": "create a network", + "description": "create a network", + "operationId": "create_vim_network", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim network request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimNetwork" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimNetworkInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim network is not accessable" + } + } + }, + "get": { + "tags": [ + "vim networks" + ], + "summary": "query vim networks list", + "description": "query vim networks list", + "operationId": "query_vim_networks", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim networks request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimNetworks" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimNetworksInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim network is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/networks/{networkid}": { + "delete": { + "tags": [ + "vim networks" + ], + "summary": "delete specific vim network", + "description": "delete specific vim network", + "operationId": "delete_vim_network", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "networkid", + "in": "path", + "description": "vim network id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the network is not accessable" + } + } + }, + "get": { + "tags": [ + "vim networks" + ], + "summary": "query specific vim network", + "description": "query specific vim network", + "operationId": "query_vim_network", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "networkid", + "in": "path", + "description": "vim network id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimNetworkInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim network is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimNetwork": { + "type": "object", + "required": [ + "networkType", + "name", + "shared" + ], + "properties": { + "name": { + "type": "string", + "description": "network name" + }, + "networkType": { + "type": "string", + "description": "network type" + }, + "physicalNetwork": { + "type": "string", + "description": "physical network name" + }, + "segmentationId": { + "type": "integer", + "description": "segmentation ID of physical network" + }, + "vlanTransparent": { + "type": "boolean", + "description": "vlan transparent" + }, + "shared": { + "type": "boolean", + "description": "network is shared across tenants" + }, + "routerExternal": { + "type": "boolean", + "description": "network can provide floating IPs via a router" + } + } + }, + "ListVimNetworks": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "network name" + } + } + }, + "VimNetworksInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "networks" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "networks": { + "type": "array", + "description": "network information", + "items": { + "$ref": "#/definitions/VimNetworkInfo" + } + } + } + }, + "VimNetworkInfo": { + "type": "object", + "required": [ + "name", + "status", + "id" + ], + "properties": { + "name": { + "type": "string", + "description": "network name" + }, + "id": { + "type": "string", + "description": "network UUID" + }, + "status": { + "type": "string", + "description": "network status" + }, + "networkType": { + "type": "string", + "description": "network type" + }, + "physicalNetwork": { + "type": "string", + "description": "physical network name" + }, + "segmentationId": { + "type": "boolean", + "description": "segmentationId of physical network" + }, + "vlanTransparent": { + "type": "boolean", + "description": "vlan transparent" + }, + "shared": { + "type": "boolean", + "description": "network is shared across tenants" + }, + "routerExternal": { + "type": "boolean", + "description": "network can provide floating IPs via a router" + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.server.swagger.json b/newton/newton/swagger/multivim.server.swagger.json new file mode 100644 index 00000000..82de1223 --- /dev/null +++ b/newton/newton/swagger/multivim.server.swagger.json @@ -0,0 +1,493 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/servers": { + "post": { + "tags": [ + "vim servers" + ], + "summary": "create a server", + "description": "create a server", + "operationId": "create_vim_server", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim server request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimServer" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimServerInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim server is not accessable" + } + } + }, + "get": { + "tags": [ + "vim servers" + ], + "summary": "query vim servers list", + "description": "query vim servers list", + "operationId": "query_vim_servers", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim servers request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimServers" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimServersInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim server is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/servers/{serverid}": { + "delete": { + "tags": [ + "vim servers" + ], + "summary": "delete specific vim server", + "description": "delete specific vim server", + "operationId": "delete_vim_server", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "serverid", + "in": "path", + "description": "vim server id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim server is not accessable" + } + } + }, + "get": { + "tags": [ + "vim servers" + ], + "summary": "query specific vim server", + "description": "query specific vim server", + "operationId": "query_vim_server", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "serverid", + "in": "path", + "description": "vim server id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimServerInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim server is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimServer": { + "type": "object", + "required": [ + "name", + "boot", + "flavorId" + ], + "properties": { + "name": { + "type": "string", + "description": "server name" + }, + "boot": { + "type": "object", + "description": "Parameters to start a server", + "properties": { + "type": { + "type": "integer", + "description": "boot type: 1: boot from volume, 2: boot from image" + }, + "volumeId": { + "type": "string", + "description": "volume UUID to boot server" + }, + "imageId": { + "type": "string", + "description": "image UUID to boot server" + } + } + }, + "flavorId": { + "type": "string", + "description": "flavor uuid to start server" + }, + "contextArray": { + "type": "array", + "description": "list of injected files", + "items": { + "$ref": "#/definitions/VimServerContextInfo" + } + }, + "volumeArray": { + "type": "array", + "description": "list of volumes attached to a server", + "items": { + "$ref": "#/definitions/VimServerVolumeInfo" + } + }, + "nicArray": { + "type": "array", + "description": "list of volumes attached to a server", + "items": { + "$ref": "#/definitions/VimServerNicInfo" + } + }, + "availabilityZone": { + "type": "string", + "description": "The availability zone from which to launch the server." + }, + "metadata": { + "type": "array", + "description": "list of key-value pairs for metadata to start a server", + "items": { + "$ref": "#/definitions/VimServerKeyValuePair" + } + }, + "userdata": { + "type": "string", + "description": "user data to start a aserver" + }, + "securityGroups": { + "type": "array", + "description": "list of security groups for a server", + "items": { + "type": "string", + "description": "name of security group" + } + }, + "serverGroup": { + "type": "string", + "description": "server group" + } + } + }, + "VimServerKeyValuePair": { + "type": "object", + "properties": { + "keyName": { + "type": "string", + "description": "key name" + }, + "value": { + "type": "string", + "description": "value " + } + } + }, + "VimServerContextInfo": { + "type": "object", + "properties": { + "fileName": { + "type": "string", + "description": "Injected file name" + }, + "fileData": { + "type": "string", + "description": "Injected file content " + } + } + }, + "VimServerVolumeInfo": { + "type": "object", + "properties": { + "volumeId": { + "type": "string", + "description": "volume UUID" + } + } + }, + "VimServerNicInfo": { + "type": "object", + "properties": { + "portId": { + "type": "string", + "description": "virtual port UUID to boot a server" + } + } + }, + "ListVimServers": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "server name to filter server list" + }, + "limit": { + "type": "integer", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "server ID of the last-seen item" + } + } + }, + "VimServersInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "servers" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "servers": { + "type": "array", + "description": "server list information", + "items": { + "$ref": "#/definitions/VimServerInfo" + } + } + } + }, + "VimServerInfo": { + "type": "object", + "required": [ + "name", + "status", + "id" + ], + "properties": { + "name": { + "type": "string", + "description": "server name" + }, + "id": { + "type": "string", + "description": "server UUID" + }, + "status": { + "type": "string", + "description": "server status,0:INACTIVE,1:ACTIVE,2:ERROR" + }, + "boot": { + "type": "object", + "description": "Parameters to start a server", + "properties": { + "type": { + "type": "integer", + "description": "boot type: 1: boot from volume, 2: boot from image" + }, + "volumeId": { + "type": "string", + "description": "volume UUID to boot server" + }, + "ImageId": { + "type": "string", + "description": "image UUID to boot server" + } + } + }, + "flavorId": { + "type": "string", + "description": "flavor uuid to start server" + }, + "volumeArray": { + "type": "array", + "description": "list of volumes attached to a server", + "items": { + "$ref": "#/definitions/VimServerVolumeInfo" + } + }, + "nicArray": { + "type": "array", + "description": "list of volumes attached to a server", + "items": { + "$ref": "#/definitions/VimServerNicInfo" + } + }, + "availabilityZone": { + "type": "string", + "description": "available zone for a server" + }, + "metadata": { + "type": "array", + "description": "list of key-value pairs for metadata to start a server", + "items": { + "$ref": "#/definitions/VimServerKeyValuePair" + } + }, + "securityGroups": { + "type": "array", + "description": "list of security groups for a server", + "items": { + "type": "string", + "description": "name of security group" + } + }, + "serverGroup": { + "type": "string", + "description": "server group" + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.subnet.swagger.json b/newton/newton/swagger/multivim.subnet.swagger.json new file mode 100644 index 00000000..d862a68f --- /dev/null +++ b/newton/newton/swagger/multivim.subnet.swagger.json @@ -0,0 +1,428 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/subnets": { + "post": { + "tags": [ + "vim subnets" + ], + "summary": "create a subnet", + "description": "create a subnet", + "operationId": "create_vim_subnet", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim subnet request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimSubnet" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimSubnetInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim subnet is not accessable" + } + } + }, + "get": { + "tags": [ + "vim subnets" + ], + "summary": "query vim subnets list", + "description": "query vim subnets list", + "operationId": "query_vim_subnets", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim subnets request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimSubnets" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimSubnetsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim subnet is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/subnets/{subnetid}": { + "delete": { + "tags": [ + "vim subnets" + ], + "summary": "delete specific vim subnet", + "description": "delete specific vim subnet", + "operationId": "delete_vim_subnet", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "subnetid", + "in": "path", + "description": "vim subnet id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the subnet is not accessable" + } + } + }, + "get": { + "tags": [ + "vim subnets" + ], + "summary": "query specific vim subnet", + "description": "query specific vim subnet", + "operationId": "query_vim_subnet", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "subnetid", + "in": "path", + "description": "vim subnet id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimSubnetInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim subnet id is invalid" + } + } + } + } + }, + "definitions": { + "CreateVimSubnet": { + "type": "object", + "required": [ + "networkId", + "name", + "cidr", + "ipVersion" + ], + "properties": { + "networkId": { + "type": "string", + "description": "network UUID" + }, + "name": { + "type": "string", + "description": "subnet name" + }, + "cidr": { + "type": "string", + "description": "subnet CIDR" + }, + "ipVersion": { + "type": "integer", + "description": "IP version: 4 for IPv4, 6 for IPv6" + }, + "enableDhcp": { + "type": "boolean", + "description": "Enable DHCP or not" + }, + "gatewayIp": { + "type": "string", + "description": "gateway IP address" + }, + "dnsNameservers": { + "type": "array", + "description": "DNS Nameservers", + "items": { + "type": "string" + } + }, + "hostRoutes": { + "type": "array", + "description": "Host route entries", + "items": { + "$ref": "#/definitions/VimHostRouteInfo" + } + }, + "allocationPools": { + "type": "array", + "description": "IP address allocation pools", + "items": { + "$ref": "#/definitions/VimIpAllocationPoolInfo" + } + } + } + }, + "VimHostRouteInfo": { + "type": "object", + "properties": { + "destination": { + "type": "string", + "description": "destination field of a route entry" + }, + "nexthop ": { + "type": "string", + "description": "next hop of a route entry" + } + } + }, + "VimIpAllocationPoolInfo": { + "type": "object", + "properties": { + "start": { + "type": "string", + "description": "start IP address of a pool" + }, + "end ": { + "type": "string", + "description": "end IP address of a pool" + } + } + }, + "ListVimSubnets": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "subnet name" + } + } + }, + "VimSubnetsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "subnets" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "subnets": { + "type": "array", + "description": "subnets information", + "items": { + "$ref": "#/definitions/VimSubnetInfo" + } + } + } + }, + "VimSubnetInfo": { + "type": "object", + "required": [ + "name", + "status", + "id", + "networkId", + "cidr", + "ipVersion" + ], + "properties": { + "name": { + "type": "string", + "description": "subnet name" + }, + "id": { + "type": "string", + "description": "subnet UUID" + }, + "status": { + "type": "string", + "description": "subnet status" + }, + "networkId": { + "type": "string", + "description": "network UUID" + }, + "networkName": { + "type": "string", + "description": "network name" + }, + "cidr": { + "type": "string", + "description": "subnet CIDR" + }, + "ipVersion": { + "type": "integer", + "description": "IP version: 4 for IPv4, 6 for IPv6" + }, + "enableDhcp": { + "type": "boolean", + "description": "Enable DHCP or not" + }, + "gatewayIp": { + "type": "string", + "description": "gateway IP address" + }, + "dnsNameservers": { + "type": "array", + "description": "DNS Nameservers", + "items": { + "type": "string" + } + }, + "hostRoutes": { + "type": "array", + "description": "Host route entries", + "items": { + "$ref": "#/definitions/VimHostRouteInfo" + } + }, + "allocationPools": { + "type": "array", + "description": "IP address allocation pools", + "items": { + "$ref": "#/definitions/VimIpAllocationPoolInfo" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.tenant.swagger.json b/newton/newton/swagger/multivim.tenant.swagger.json new file mode 100644 index 00000000..062a0bda --- /dev/null +++ b/newton/newton/swagger/multivim.tenant.swagger.json @@ -0,0 +1,119 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/tenants": { + "get": { + "tags": [ + "vim tenants" + ], + "summary": "query vim tenants list", + "description": "query vim tenants list", + "operationId": "query_vim_tenants", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim tenants request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimTenants" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimTenantsInfo" + } + }, + "404": { + "description": "the vim id is wrong" + }, + "500": { + "description": "the vim tenants is not accessable" + } + } + } + } + }, + "definitions": { + "ListVimTenants": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "tenant name to filter tenant list" + } + } + }, + "VimTenantsInfo": { + "type": "object", + "required": [ + "vimId", + "tenants" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenants": { + "type": "array", + "description": "tenant list information", + "items": { + "$ref": "#/definitions/VimTenantInfo" + } + } + } + }, + "VimTenantInfo": { + "type": "object", + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string", + "description": "tenant name" + }, + "id": { + "type": "string", + "description": "tenant UUID" + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.volume.swagger.json b/newton/newton/swagger/multivim.volume.swagger.json new file mode 100644 index 00000000..5b26d8c0 --- /dev/null +++ b/newton/newton/swagger/multivim.volume.swagger.json @@ -0,0 +1,379 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/volumes": { + "post": { + "tags": [ + "vim volumes" + ], + "summary": "create a volume", + "description": "create a volume", + "operationId": "create_vim_volume", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim volume request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimVolume" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimVolumeInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim volume is not accessable" + } + } + }, + "get": { + "tags": [ + "vim volumes" + ], + "summary": "query vim volumes list", + "description": "query vim volumes list", + "operationId": "query_vim_volumes", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim volumes request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimVolumes" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimVolumesInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim volume is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/volumes/{volumeid}": { + "delete": { + "tags": [ + "vim volumes" + ], + "summary": "delete specific vim volume", + "description": "delete specific vim volume", + "operationId": "delete_vim_volume", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "volumeid", + "in": "path", + "description": "vim volume id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim volume is not accessable" + } + } + }, + "get": { + "tags": [ + "vim volumes" + ], + "summary": "query specific vim volume", + "description": "query specific vim volume", + "operationId": "query_vim_volume", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "volumeid", + "in": "path", + "description": "vim volume id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimVolumeInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim volume is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimVolume": { + "type": "object", + "required": [ + "name", + "volumeSize" + ], + "properties": { + "name": { + "type": "string", + "description": "volume name" + }, + "volumeSize": { + "type": "integer", + "description": "volume size" + }, + "imageName": { + "type": "string", + "description": "image name to create volume" + }, + "volumeType": { + "type": "string", + "description": "volume type" + }, + "availabilityZone": { + "type": "integer", + "description": "available zone for volume" + } + } + }, + "ListVimVolumes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "volume name to filter volume list" + }, + "limit": { + "type": "integer", + "description": "Requests a page size of items" + }, + "marker": { + "type": "string", + "description": "volume ID of the last-seen item" + } + } + }, + "VimVolumesInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "volumes" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "volumes": { + "type": "array", + "description": "volume list information", + "items": { + "$ref": "#/definitions/VimVolumeInfo" + } + } + } + }, + "VimVolumeInfo": { + "type": "object", + "required": [ + "name", + "id", + "status" + ], + "properties": { + "name": { + "type": "string", + "description": "volume name" + }, + "id": { + "type": "string", + "description": "volume UUID" + }, + "createTime": { + "type": "string", + "description": "created time" + }, + "volumeSize": { + "type": "integer", + "description": "volume size" + }, + "volumeType": { + "type": "string", + "description": "volume type" + }, + "availabilityZone": { + "type": "integer", + "description": "available zone for volume" + }, + "attachments": { + "type": "array", + "description": "attachment list information", + "items": { + "$ref": "#/definitions/VimVolumeAttachmentInfo" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "return code: 0: Already exist 1: Newly created" + } + } + }, + "VimVolumeAttachmentInfo": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "attachment UUID" + }, + "serverId": { + "type": "string", + "description": "server UUID" + }, + "volumeId": { + "type": "string", + "description": "volume UUID" + }, + "deviceId": { + "type": "string", + "description": "device UUID" + }, + "hostName": { + "type": "string", + "description": "host name" + } + } + } + } +} diff --git a/newton/newton/swagger/multivim.vport.swagger.json b/newton/newton/swagger/multivim.vport.swagger.json new file mode 100644 index 00000000..f722c26f --- /dev/null +++ b/newton/newton/swagger/multivim.vport.swagger.json @@ -0,0 +1,378 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "MultiVIM Service rest API" + }, + "basePath": "/openoapi/multivim/v1/", + "tags": [ + { + "name": "MultiVIM broker" + } + ], + "paths": { + "/{vimid}/{tenantid}/ports": { + "post": { + "tags": [ + "vim virtual ports" + ], + "summary": "create a virtual port", + "description": "create a virtual port", + "operationId": "create_vim_port", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "create vim virtual port request param", + "required": true, + "schema": { + "$ref": "#/definitions/CreateVimPort" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimPortInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim virtual port is not accessable" + } + } + }, + "get": { + "tags": [ + "vim virtual ports" + ], + "summary": "query vim ports list", + "description": "query vim ports list", + "operationId": "query_vim_ports", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "get a list of vim virtual ports request param", + "required": false, + "schema": { + "$ref": "#/definitions/ListVimPorts" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimPortsInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim virtual port is not accessable" + } + } + } + }, + "/{vimid}/{tenantid}/ports/{portid}": { + "delete": { + "tags": [ + "vim virtual ports" + ], + "summary": "delete specific vim virtual port", + "description": "delete specific vim virtual port", + "operationId": "delete_vim_port", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "portid", + "in": "path", + "description": "vim virtual port id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "successful operation" + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the virtual port is not accessable" + } + } + }, + "get": { + "tags": [ + "vim virtual ports" + ], + "summary": "query specific vim virtual port", + "description": "query specific vim virtual port", + "operationId": "query_vim_port", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "vimid", + "in": "path", + "description": "vim instance id", + "required": true, + "type": "string" + }, + { + "name": "tenantid", + "in": "path", + "description": "tenant UUID", + "required": true, + "type": "string" + }, + { + "name": "portid", + "in": "path", + "description": "vim virtual port id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VimPortInfo" + } + }, + "404": { + "description": "the vim id or tenant UUID is wrong" + }, + "500": { + "description": "the vim virtual port id is not accessable" + } + } + } + } + }, + "definitions": { + "CreateVimPort": { + "type": "object", + "required": [ + "networkId", + "subnetId", + "name", + "cidr", + "ipVersion" + ], + "properties": { + "networkId": { + "type": "string", + "description": "network UUID" + }, + "subnetId": { + "type": "string", + "description": "subnet UUID" + }, + "name": { + "type": "string", + "description": "virtual port name" + }, + "ip": { + "type": "string", + "description": "virtual port fixed IP" + }, + "macAddress": { + "type": "string", + "description": "virtual port MAC address" + }, + "vnicType": { + "type": "string", + "description": "vnicType: normal,direct,macvtap" + }, + "securityGroups": { + "type": "array", + "description": "List of security group names", + "items": { + "type": "string" + } + } + } + }, + "ListVimPorts": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "virtual port name" + } + } + }, + "VimPortsInfo": { + "type": "object", + "required": [ + "vimId", + "tenantId", + "ports" + ], + "properties": { + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "ports": { + "type": "array", + "description": "ports information", + "items": { + "$ref": "#/definitions/VimPortInfo" + } + } + } + }, + "VimPortInfo": { + "type": "object", + "required": [ + "name", + "status", + "id", + "networkId", + "subnetId" + ], + "properties": { + "name": { + "type": "string", + "description": "virtual port name" + }, + "id": { + "type": "string", + "description": "virtual port UUID" + }, + "status": { + "type": "string", + "description": "subnet status" + }, + "networkId": { + "type": "string", + "description": "network UUID" + }, + "networkName": { + "type": "string", + "description": "network name" + }, + "subnetName": { + "type": "string", + "description": "subnet name" + }, + "subnetId": { + "type": "string", + "description": "subnet UUID" + }, + "ip": { + "type": "string", + "description": "virtual port fixed IP" + }, + "macAddress": { + "type": "string", + "description": "virtual port MAC address" + }, + "vnicType": { + "type": "string", + "description": "vnicType: normal,direct,macvtap" + }, + "securityGroups": { + "type": "array", + "description": "list of securityGroups names", + "items": { + "type": "string" + } + }, + "vimId": { + "type": "string" + }, + "vimName": { + "type": "string" + }, + "tenantId": { + "type": "string", + "description": "tenant UUID" + }, + "returnCode": { + "type": "integer", + "description": "0: Already exist 1: Newly created" + } + } + } + } +} diff --git a/newton/newton/swagger/tests.py b/newton/newton/swagger/tests.py new file mode 100644 index 00000000..299f3ff9 --- /dev/null +++ b/newton/newton/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("/openoapi/multivim-newton/v1/swagger.json") + self.assertEqual(status.HTTP_200_OK, response.status_code, response.content) +# resp_data = json.loads(response.content) +# self.assertEqual({"status": "active"}, resp_data) diff --git a/newton/newton/swagger/urls.py b/newton/newton/swagger/urls.py new file mode 100644 index 00000000..279a430e --- /dev/null +++ b/newton/newton/swagger/urls.py @@ -0,0 +1,22 @@ +# 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 newton.swagger import views +from newton.swagger.views import SwaggerJsonView + +urlpatterns = [ + url(r'^openoapi/multivim-newton/v1/swagger.json$', SwaggerJsonView.as_view()), +] + +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/newton/newton/swagger/views.py b/newton/newton/swagger/views.py new file mode 100644 index 00000000..2e87bc74 --- /dev/null +++ b/newton/newton/swagger/views.py @@ -0,0 +1,89 @@ +# 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 + +logger = logging.getLogger(__name__) + + +class SwaggerJsonView(APIView): + def get(self, request): + json_file = os.path.join(os.path.dirname(__file__), 'multivim.flavor.swagger.json') + f = open(json_file) + json_data = json.JSONDecoder().decode(f.read()) + f.close() + json_file = os.path.join(os.path.dirname(__file__), 'multivim.image.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.network.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.subnet.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.server.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.volume.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.vport.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.tenant.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.host.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_file = os.path.join(os.path.dirname(__file__), 'multivim.limit.swagger.json') + f = open(json_file) + json_data_temp = json.JSONDecoder().decode(f.read()) + f.close() + json_data["paths"].update(json_data_temp["paths"]) + json_data["definitions"].update(json_data_temp["definitions"]) + json_data["basePath"] = "/openoapi/multivim-newton/v1/" + json_data["info"]["title"] = "MultiVIM driver of OpenStack Newton Service NBI" + return Response(json_data) + diff --git a/newton/newton/urls.py b/newton/newton/urls.py new file mode 100644 index 00000000..94ca0bc4 --- /dev/null +++ b/newton/newton/urls.py @@ -0,0 +1,25 @@ +# 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 newton.pub.config.config import REG_TO_MSB_WHEN_START, REG_TO_MSB_REG_URL, REG_TO_MSB_REG_PARAM + +urlpatterns = [ + url(r'^', include('newton.swagger.urls')), + url(r'^', include('newton.samples.urls')), +] +#url(r'^', include('newton.forward.urls')), + +# regist to MSB when startup +if REG_TO_MSB_WHEN_START: + import json + from newton.pub.utils.restcall import req_by_msb + req_by_msb(REG_TO_MSB_REG_URL, "POST", json.JSONEncoder().encode(REG_TO_MSB_REG_PARAM)) diff --git a/newton/newton/wsgi.py b/newton/newton/wsgi.py new file mode 100644 index 00000000..3ecaed9e --- /dev/null +++ b/newton/newton/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", "newton.settings") + +application = get_wsgi_application() diff --git a/newton/pom.xml b/newton/pom.xml new file mode 100644 index 00000000..0c8782ed --- /dev/null +++ b/newton/pom.xml @@ -0,0 +1,49 @@ +<?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.openo.multivimdriver.openstack</groupId> + <artifactId>multivimdriver-openstack-root</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.openo.multivimdriver.openstack</groupId> + <artifactId>multivimdriver-openstack-newton</artifactId> + <version>1.1.0-SNAPSHOT</version> + <packaging>pom</packaging> + <name>multivimdriver/openstack/newton</name> + <description>multivimdriver for openstack newton</description> + <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/newton/requirements.txt b/newton/requirements.txt new file mode 100644 index 00000000..25904796 --- /dev/null +++ b/newton/requirements.txt @@ -0,0 +1,26 @@ +# rest framework +Django==1.9.6 +djangorestframework==3.3.3 + +# for access MySQL +MySQL-python==1.2.5 + +# redis cache +redis==2.10.5 + +# for access redis cache +redisco==0.1.4 +django-redis-cache==0.13.1 + +# for call rest api +httplib2==0.9.2 + +# for call openstack api +python-keystoneclient==3.6.0 +python-glanceclient==2.5.0 +python-neutronclient==6.0.0 + +# for unit test +coverage==4.2 +mock==2.0.0 +unittest_xml_reporting==1.12.0 diff --git a/newton/run.sh b/newton/run.sh new file mode 100755 index 00000000..8b8b0890 --- /dev/null +++ b/newton/run.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. + +nohup python manage.py runserver 127.0.0.1:9003 > /dev/null & diff --git a/newton/stop.sh b/newton/stop.sh new file mode 100755 index 00000000..db6d7366 --- /dev/null +++ b/newton/stop.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. + +ps auxww | grep 'manage.py runserver 127.0.0.1:9003' | awk '{print $2}' | xargs kill -9 diff --git a/newton/tox.ini b/newton/tox.ini new file mode 100644 index 00000000..87aca481 --- /dev/null +++ b/newton/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py27 +skipsdist = true + +[tox:jenkins] +downloadcache = ~/cache/pip + +[testenv] +deps = -r{toxinidir}/requirements.txt +commands = coverage run --branch manage.py test newton |