diff --git a/.gitignore b/.gitignore index 372c13e..7a60b85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ __pycache__/ - +*.pyc diff --git a/commands.txt b/commands.txt index 8ad660f..00ae10d 100644 --- a/commands.txt +++ b/commands.txt @@ -36,6 +36,34 @@ $ python3 clientTopology.py == RESTCONF +=== YANG2SWAGGER + +$ cd /root/OFC_SC472/restconf +$ wget https://github.com/bartoszm/yang2swagger/releases/download/1.1.11/swagger-generator-cli-1.1.11-executable.jar +$ java -jar swagger-generator-cli-1.1.11-executable.jar -yang-dir ../yang/ -output topology.yaml topology +$ java -jar swagger-generator-cli-1.1.11-executable.jar -yang-dir ../yang/ -output connection.yaml connection + +=== SERVER +$ cd /root/OFC_SC472/restconf +$ wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.11/swagger-codegen-cli-3.0.11.jar -O swagger-codegen-cli.jar +Create the server: +$ java -jar swagger-codegen-cli.jar generate -i connection.yaml -l python-flask -o server/ +Run the server: +$ cd /root/OFC_SC472/restconf/server +$ pip3 install -r requirements.txt +(Open /root/OFC_SC472/restconfserver/swagger_server/swagger/swagger.yaml and modify all: "name: connection_id" for "name: connection-id") +RUN AUTOGENERATED SERVER +$ python3 -m swagger_server + +RUN CONNECTION SERVER +$ cd /root/OFC_SC472/restconf/connectionserver +$ python3 -m swagger_server + +RUN CURL AS CLIENT (In another window) +$ cd /root/OFC_SC472/restconf/ +$ curl -X POST -H "Content-Type: application/yang-data+json" http://127.0.0.1:8080/data/connection/ -d@conn1.json +$ curl -X GET -H "Content-Type: application/yang-data+json" http://127.0.0.1:8080/data/connection=0/ +$ curl -X DELETE -H "Content-Type: application/yang-data+json" http://127.0.0.1:8080/data/connection=0/ == RUN ONOS @@ -53,17 +81,73 @@ $ cd /root/OFC_SC472/onos_api/ $ python3 onos_topology.py == TAPI +RUN TAPI SERVER: +$ cd /root/OFC_SC472/tapi/server +$ python3 tapi_server.py + +RUN TAPI CLIENT (In a new window): +$ cd /root/OFC_SC472/tapi/client +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/service-interface-point/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/service-interface-point/sip-pe1-uni1/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-nwk/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-nwk/node/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-nwk/node/node-mul-pe-1/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-pe1/node/node-eth-pe-1/owned-node-edge-point/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-pe1/node/node-eth-pe-1/owned-node-edge-point/nep-pe1-eth-uni1/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-nwk/link/link-pe1-odu4-nni1-pi4-odu4-nni2/ +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/topology/topo-pe1/link/link-pe1-eth-pool-pe1-odu2-pool/ + +RUN TAPI_APP +$ cd /root/OFC_SC472/tapi/tapi_app +$ python3 tapi_app.py + +RUN TAPI CLIENT +$ cd /root/OFC_SC472/tapi/client +$ curl -X POST -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/connectivity-service/cs1/ -d @cs1.json +$ curl -X GET -H "Content-Type: application/json" http://127.0.0.1:8080/restconf/config/context/connection/cs1/ == GRPC +$ cd /root/OFC_SC472/grpc +COMPILE connection.proto: +$ python -m grpc_tools.protoc -I=. --python_out=connection/ connection.proto -== OPENCONFIG +RUN CREATE AND LIST CONNECTION +$ cd /root/OFC_SC472/grpc/connection +$ python3 create.py connection.txt +$ python3 list.py connection.txt + +COMPILE connectionService.proto +$ python -m grpc_tools.protoc -I=. --python_out=connectionService/ --grpc_python_out=connectionService/ connectionService.proto + +RUN SERVER +$ cd /root/OFC_SC472/grpc/connectionService +$ python3 connectionService_server.py + +RUN CLIENT (in another window) +$ cd /root/OFC_SC472/grpc/connectionService +$ python3 connectionService_client.py + +COMPILE connectionServiceWithNotif.proto +$ cd /root/OFC_SC472/grpc/ +$ python -m grpc_tools.protoc -I=. --python_out=connectionServiceWithNotif/ --grpc_python_out=connectionServiceWithNotif/ connectionServiceWithNotif.proto +RUN SERVER +$ cd /root/OFC_SC472/grpc/connectionServiceWithNotif +$ python3 connectionServiceWithNotif_server.py + +RUN CLIENT (in another window) +$ cd /root/OFC_SC472/grpc/connectionServiceWithNotif +$ python3 connectionServiceWithNotif_client.py + + +== OPENCONFIG -== APPENDICES -=== CONFD +== APPENDIX: CONFD $ cd /root/OFC_SC472/netconf $ unzip confd-basic-6.4.linux.x86_64.zip $ cd confd-basic-6.4.linux.x86_64/ @@ -93,7 +177,7 @@ $ ./confd_cli > exit > exit -== NETCONF EDIT-CONFIG +== APPENDIX: NETCONF EDIT-CONFIG Run server: $ cd /root/OFC_SC472/netconf/connection diff --git a/grpc/connection/connection.txt b/grpc/connection/connection.txt index c0a5f2d..2ca9bce 100644 --- a/grpc/connection/connection.txt +++ b/grpc/connection/connection.txt @@ -4,3 +4,8 @@ % conn2node2node1"portB*portA0 + + +conn3ab"1*20d + +con4fb"2*30o \ No newline at end of file diff --git a/grpc/connection/connection_pb2.py b/grpc/connection/connection_pb2.py index 6b2b1f7..e66b665 100644 --- a/grpc/connection/connection_pb2.py +++ b/grpc/connection/connection_pb2.py @@ -7,7 +7,6 @@ from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -19,9 +18,9 @@ name='connection.proto', package='connection', syntax='proto3', + serialized_options=None, serialized_pb=_b('\n\x10\x63onnection.proto\x12\nconnection\"\xf5\x01\n\nConnection\x12\x14\n\x0c\x63onnectionId\x18\x01 \x01(\t\x12\x12\n\nsourceNode\x18\x02 \x01(\t\x12\x12\n\ntargetNode\x18\x03 \x01(\t\x12\x12\n\nsourcePort\x18\x04 \x01(\t\x12\x12\n\ntargetPort\x18\x05 \x01(\t\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x43\n\x11layerProtocolName\x18\x07 \x01(\x0e\x32(.connection.Connection.LayerProtocolName\")\n\x11LayerProtocolName\x12\x07\n\x03\x45TH\x10\x00\x12\x0b\n\x07OPTICAL\x10\x01\"<\n\x0e\x43onnectionList\x12*\n\nconnection\x18\x01 \x03(\x0b\x32\x16.connection.Connectionb\x06proto3') ) -_sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -33,15 +32,15 @@ values=[ _descriptor.EnumValueDescriptor( name='ETH', index=0, number=0, - options=None, + serialized_options=None, type=None), _descriptor.EnumValueDescriptor( name='OPTICAL', index=1, number=1, - options=None, + serialized_options=None, type=None), ], containing_type=None, - options=None, + serialized_options=None, serialized_start=237, serialized_end=278, ) @@ -61,49 +60,49 @@ has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sourceNode', full_name='connection.Connection.sourceNode', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='targetNode', full_name='connection.Connection.targetNode', index=2, number=3, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='sourcePort', full_name='connection.Connection.sourcePort', index=3, number=4, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='targetPort', full_name='connection.Connection.targetPort', index=4, number=5, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='bandwidth', full_name='connection.Connection.bandwidth', index=5, number=6, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='layerProtocolName', full_name='connection.Connection.layerProtocolName', index=6, number=7, type=14, cpp_type=8, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -111,7 +110,7 @@ enum_types=[ _CONNECTION_LAYERPROTOCOLNAME, ], - options=None, + serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], @@ -135,14 +134,14 @@ has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], - options=None, + serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], @@ -157,6 +156,7 @@ _CONNECTIONLIST.fields_by_name['connection'].message_type = _CONNECTION DESCRIPTOR.message_types_by_name['Connection'] = _CONNECTION DESCRIPTOR.message_types_by_name['ConnectionList'] = _CONNECTIONLIST +_sym_db.RegisterFileDescriptor(DESCRIPTOR) Connection = _reflection.GeneratedProtocolMessageType('Connection', (_message.Message,), dict( DESCRIPTOR = _CONNECTION, diff --git a/grpc/connection/create.py b/grpc/connection/create.py old mode 100644 new mode 100755 index b8ea6e7..df5df77 --- a/grpc/connection/create.py +++ b/grpc/connection/create.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 import connection_pb2 import sys diff --git a/grpc/connection/list.py b/grpc/connection/list.py old mode 100644 new mode 100755 index 0249433..47b92cc --- a/grpc/connection/list.py +++ b/grpc/connection/list.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 from __future__ import print_function import connection_pb2 import sys @@ -30,4 +30,4 @@ def ListConnections(connectionList): with open(sys.argv[1], "rb") as f: connectionList.ParseFromString(f.read()) - ListConnections(connectionList) \ No newline at end of file + ListConnections(connectionList) diff --git a/grpc/connectionServiceWithNotif/connectionService_client.py b/grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py similarity index 100% rename from grpc/connectionServiceWithNotif/connectionService_client.py rename to grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py diff --git a/grpc/connectionServiceWithNotif/connectionService_server.py b/grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py similarity index 100% rename from grpc/connectionServiceWithNotif/connectionService_server.py rename to grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py diff --git a/restconf/connection.yaml b/restconf/connection.yaml index e67dde2..abc119f 100644 --- a/restconf/connection.yaml +++ b/restconf/connection.yaml @@ -29,13 +29,13 @@ paths: description: "Internal error" 409: description: "Object already exists" - /data/connection={connectionid}/: + /data/connection={connection-id}/: get: tags: - "connection" description: "returns connection.Connection" parameters: - - name: "connectionid" + - name: "connection-id" in: "path" description: "Id of connection" required: true diff --git a/restconf/connectionserver/.dockerignore b/restconf/connectionserver/.dockerignore new file mode 100644 index 0000000..cdd823e --- /dev/null +++ b/restconf/connectionserver/.dockerignore @@ -0,0 +1,72 @@ +.travis.yaml +.swagger-codegen-ignore +README.md +tox.ini +git_push.sh +test-requirements.txt +setup.py + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/restconf/connectionserver/.gitignore b/restconf/connectionserver/.gitignore new file mode 100644 index 0000000..a655050 --- /dev/null +++ b/restconf/connectionserver/.gitignore @@ -0,0 +1,64 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/restconf/connectionserver/.swagger-codegen-ignore b/restconf/connectionserver/.swagger-codegen-ignore new file mode 100644 index 0000000..c5fa491 --- /dev/null +++ b/restconf/connectionserver/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/restconf/connectionserver/.swagger-codegen/VERSION b/restconf/connectionserver/.swagger-codegen/VERSION new file mode 100644 index 0000000..e4a0720 --- /dev/null +++ b/restconf/connectionserver/.swagger-codegen/VERSION @@ -0,0 +1 @@ +3.0.11 \ No newline at end of file diff --git a/restconf/connectionserver/.travis.yml b/restconf/connectionserver/.travis.yml new file mode 100644 index 0000000..dd6c445 --- /dev/null +++ b/restconf/connectionserver/.travis.yml @@ -0,0 +1,13 @@ +# ref: https://docs.travis-ci.com/user/languages/python +language: python +python: + - "3.2" + - "3.3" + - "3.4" + - "3.5" + #- "3.5-dev" # 3.5 development branch + #- "nightly" # points to the latest development branch e.g. 3.6-dev +# command to install dependencies +install: "pip install -r requirements.txt" +# command to run tests +script: nosetests diff --git a/restconf/connectionserver/Dockerfile b/restconf/connectionserver/Dockerfile new file mode 100644 index 0000000..f9243a5 --- /dev/null +++ b/restconf/connectionserver/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.6-alpine + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY requirements.txt /usr/src/app/ + +RUN pip3 install --no-cache-dir -r requirements.txt + +COPY . /usr/src/app + +EXPOSE 8080 + +ENTRYPOINT ["python3"] + +CMD ["-m", "swagger_server"] \ No newline at end of file diff --git a/restconf/connectionserver/README.md b/restconf/connectionserver/README.md new file mode 100644 index 0000000..857c30a --- /dev/null +++ b/restconf/connectionserver/README.md @@ -0,0 +1,49 @@ +# Swagger generated server + +## Overview +This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This +is an example of building a swagger-enabled Flask server. + +This example uses the [Connexion](https://github.com/zalando/connexion) library on top of Flask. + +## Requirements +Python 3.5.2+ + +## Usage +To run the server, please execute the following from the root directory: + +``` +pip3 install -r requirements.txt +python3 -m swagger_server +``` + +and open your browser to here: + +``` +http://localhost:8080/ui/ +``` + +Your Swagger definition lives here: + +``` +http://localhost:8080/swagger.json +``` + +To launch the integration tests, use tox: +``` +sudo pip install tox +tox +``` + +## Running with Docker + +To run the server on a Docker container, please execute the following from the root directory: + +```bash +# building the image +docker build -t swagger_server . + +# starting up a container +docker run -p 8080:8080 swagger_server +``` \ No newline at end of file diff --git a/restconf/connectionserver/git_push.sh b/restconf/connectionserver/git_push.sh new file mode 100644 index 0000000..160f6f2 --- /dev/null +++ b/restconf/connectionserver/git_push.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/restconf/connectionserver/requirements.txt b/restconf/connectionserver/requirements.txt new file mode 100644 index 0000000..b5bc506 --- /dev/null +++ b/restconf/connectionserver/requirements.txt @@ -0,0 +1,3 @@ +connexion == 2.2.0 +python_dateutil == 2.6.0 +setuptools >= 21.0.0 diff --git a/restconf/connectionserver/setup.py b/restconf/connectionserver/setup.py new file mode 100644 index 0000000..ba555c8 --- /dev/null +++ b/restconf/connectionserver/setup.py @@ -0,0 +1,33 @@ +# coding: utf-8 + +import sys +from setuptools import setup, find_packages + +NAME = "swagger_server" +VERSION = "1.0.0" +# To install the library, run the following +# +# python setup.py install +# +# prerequisite: setuptools +# http://pypi.python.org/pypi/setuptools + +REQUIRES = ["connexion"] + +setup( + name=NAME, + version=VERSION, + description="connection API", + author_email="", + url="", + keywords=["Swagger", "connection API"], + install_requires=REQUIRES, + packages=find_packages(), + package_data={'': ['swagger/swagger.yaml']}, + include_package_data=True, + entry_points={ + 'console_scripts': ['swagger_server=swagger_server.__main__:main']}, + long_description="""\ + connection API generated from yang definitions + """ +) diff --git a/restconf/connectionserver/swagger_server/__init__.py b/restconf/connectionserver/swagger_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/restconf/connectionserver/swagger_server/__main__.py b/restconf/connectionserver/swagger_server/__main__.py new file mode 100644 index 0000000..db49e4d --- /dev/null +++ b/restconf/connectionserver/swagger_server/__main__.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import connexion + +from swagger_server import encoder + + +def main(): + app = connexion.App(__name__, specification_dir='./swagger/') + app.app.json_encoder = encoder.JSONEncoder + app.app.config['JSON_SORT_KEYS']=False + app.add_api('swagger.yaml', arguments={'title': 'connection API'}, pythonic_params=True) + app.run(port=8080) + + +if __name__ == '__main__': + main() diff --git a/restconf/connectionserver/swagger_server/controllers/__init__.py b/restconf/connectionserver/swagger_server/controllers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/restconf/connectionserver/swagger_server/controllers/authorization_controller.py b/restconf/connectionserver/swagger_server/controllers/authorization_controller.py new file mode 100644 index 0000000..2f7b0bb --- /dev/null +++ b/restconf/connectionserver/swagger_server/controllers/authorization_controller.py @@ -0,0 +1,6 @@ +from typing import List +""" +controller generated to handled auth operation described at: +https://connexion.readthedocs.io/en/latest/security.html +""" + diff --git a/restconf/connectionserver/swagger_server/controllers/connection_controller.py b/restconf/connectionserver/swagger_server/controllers/connection_controller.py new file mode 100644 index 0000000..8caa1e2 --- /dev/null +++ b/restconf/connectionserver/swagger_server/controllers/connection_controller.py @@ -0,0 +1,89 @@ +import connexion +import six +import swagger_server.database as database + +from swagger_server.models.connection_connection import ConnectionConnection # noqa: E501 +from swagger_server import util + + +def data_connection_post(body=None): # noqa: E501 + """data_connection_post + + creates connection.Connection # noqa: E501 + + :param body: connection.Connection to be added to list + :type body: dict | bytes + + :rtype: None + """ + if connexion.request.is_json: + body = ConnectionConnection.from_dict(connexion.request.get_json()) + body.connection_id=str(database.last_connection_id) + database.connection[str(database.last_connection_id)] = body + database.last_connection_id+=1 + return body + + +def data_connectionconnection_id_delete(connection_id): # noqa: E501 + """data_connectionconnection_id_delete + + removes connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + + :rtype: None + """ + del database.connection[connection_id] + return 'ok' + + + +def data_connectionconnection_id_get(connection_id): # noqa: E501 + """data_connectionconnection_id_get + + returns connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + + :rtype: ConnectionConnection + """ + print(database.connection) + if connection_id in database.connection: + return database.connection[connection_id] + return "Error", 400 + + +def data_connectionconnection_id_post(connection_id, body=None): # noqa: E501 + """data_connectionconnection_id_post + + creates connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + :param body: connection.Connection to be added to list + :type body: dict | bytes + + :rtype: None + """ + if connexion.request.is_json: + body = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 + return 'do some magic!' + + +def data_connectionconnection_id_put(connection_id, body=None): # noqa: E501 + """data_connectionconnection_id_put + + creates or updates connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + :param body: connection.Connection to be added or updated + :type body: dict | bytes + + :rtype: None + """ + if connexion.request.is_json: + body = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 + return 'do some magic!' diff --git a/restconf/server/swagger_server/database.py b/restconf/connectionserver/swagger_server/database.py similarity index 83% rename from restconf/server/swagger_server/database.py rename to restconf/connectionserver/swagger_server/database.py index 4d78a15..9a5ea9f 100644 --- a/restconf/server/swagger_server/database.py +++ b/restconf/connectionserver/swagger_server/database.py @@ -3,4 +3,5 @@ from swagger_server.models.connection_connection import ConnectionConnection connection = {} -last_connection_id = 0 \ No newline at end of file +last_connection_id = 0 + diff --git a/restconf/connectionserver/swagger_server/encoder.py b/restconf/connectionserver/swagger_server/encoder.py new file mode 100644 index 0000000..61ba472 --- /dev/null +++ b/restconf/connectionserver/swagger_server/encoder.py @@ -0,0 +1,20 @@ +from connexion.apps.flask_app import FlaskJSONEncoder +import six + +from swagger_server.models.base_model_ import Model + + +class JSONEncoder(FlaskJSONEncoder): + include_nulls = False + + def default(self, o): + if isinstance(o, Model): + dikt = {} + for attr, _ in six.iteritems(o.swagger_types): + value = getattr(o, attr) + if value is None and not self.include_nulls: + continue + attr = o.attribute_map[attr] + dikt[attr] = value + return dikt + return FlaskJSONEncoder.default(self, o) diff --git a/restconf/connectionserver/swagger_server/models/__init__.py b/restconf/connectionserver/swagger_server/models/__init__.py new file mode 100644 index 0000000..4df8464 --- /dev/null +++ b/restconf/connectionserver/swagger_server/models/__init__.py @@ -0,0 +1,7 @@ +# coding: utf-8 + +# flake8: noqa +from __future__ import absolute_import +# import models into model package +from swagger_server.models.connection_connection import ConnectionConnection +from swagger_server.models.topology_layer_protocol_name import TopologyLayerProtocolName diff --git a/restconf/connectionserver/swagger_server/models/base_model_.py b/restconf/connectionserver/swagger_server/models/base_model_.py new file mode 100644 index 0000000..97999c3 --- /dev/null +++ b/restconf/connectionserver/swagger_server/models/base_model_.py @@ -0,0 +1,69 @@ +import pprint + +import six +import typing + +from swagger_server import util + +T = typing.TypeVar('T') + + +class Model(object): + # swaggerTypes: The key is attribute name and the + # value is attribute type. + swagger_types = {} + + # attributeMap: The key is attribute name and the + # value is json key in definition. + attribute_map = {} + + @classmethod + def from_dict(cls: typing.Type[T], dikt) -> T: + """Returns the dict as a model""" + return util.deserialize_model(dikt, cls) + + def to_dict(self): + """Returns the model properties as a dict + + :rtype: dict + """ + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model + + :rtype: str + """ + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other diff --git a/restconf/connectionserver/swagger_server/models/connection_connection.py b/restconf/connectionserver/swagger_server/models/connection_connection.py new file mode 100644 index 0000000..6d6ab83 --- /dev/null +++ b/restconf/connectionserver/swagger_server/models/connection_connection.py @@ -0,0 +1,219 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from swagger_server.models.base_model_ import Model +from swagger_server.models.topology_layer_protocol_name import TopologyLayerProtocolName # noqa: F401,E501 +from swagger_server import util + + +class ConnectionConnection(Model): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + def __init__(self, target_port: str=None, source_port: str=None, target_node: str=None, connection_id: str=None, bandwidth: int=None, source_node: str=None, layer_protocol_name: TopologyLayerProtocolName=None): # noqa: E501 + """ConnectionConnection - a model defined in Swagger + + :param target_port: The target_port of this ConnectionConnection. # noqa: E501 + :type target_port: str + :param source_port: The source_port of this ConnectionConnection. # noqa: E501 + :type source_port: str + :param target_node: The target_node of this ConnectionConnection. # noqa: E501 + :type target_node: str + :param connection_id: The connection_id of this ConnectionConnection. # noqa: E501 + :type connection_id: str + :param bandwidth: The bandwidth of this ConnectionConnection. # noqa: E501 + :type bandwidth: int + :param source_node: The source_node of this ConnectionConnection. # noqa: E501 + :type source_node: str + :param layer_protocol_name: The layer_protocol_name of this ConnectionConnection. # noqa: E501 + :type layer_protocol_name: TopologyLayerProtocolName + """ + self.swagger_types = { + 'target_port': str, + 'source_port': str, + 'target_node': str, + 'connection_id': str, + 'bandwidth': int, + 'source_node': str, + 'layer_protocol_name': TopologyLayerProtocolName + } + + self.attribute_map = { + 'target_port': 'target-port', + 'source_port': 'source-port', + 'target_node': 'target-node', + 'connection_id': 'connection-id', + 'bandwidth': 'bandwidth', + 'source_node': 'source-node', + 'layer_protocol_name': 'layer-protocol-name' + } + self._target_port = target_port + self._source_port = source_port + self._target_node = target_node + self._connection_id = connection_id + self._bandwidth = bandwidth + self._source_node = source_node + self._layer_protocol_name = layer_protocol_name + + @classmethod + def from_dict(cls, dikt) -> 'ConnectionConnection': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The connection.Connection of this ConnectionConnection. # noqa: E501 + :rtype: ConnectionConnection + """ + return util.deserialize_model(dikt, cls) + + @property + def target_port(self) -> str: + """Gets the target_port of this ConnectionConnection. + + + :return: The target_port of this ConnectionConnection. + :rtype: str + """ + return self._target_port + + @target_port.setter + def target_port(self, target_port: str): + """Sets the target_port of this ConnectionConnection. + + + :param target_port: The target_port of this ConnectionConnection. + :type target_port: str + """ + + self._target_port = target_port + + @property + def source_port(self) -> str: + """Gets the source_port of this ConnectionConnection. + + + :return: The source_port of this ConnectionConnection. + :rtype: str + """ + return self._source_port + + @source_port.setter + def source_port(self, source_port: str): + """Sets the source_port of this ConnectionConnection. + + + :param source_port: The source_port of this ConnectionConnection. + :type source_port: str + """ + + self._source_port = source_port + + @property + def target_node(self) -> str: + """Gets the target_node of this ConnectionConnection. + + + :return: The target_node of this ConnectionConnection. + :rtype: str + """ + return self._target_node + + @target_node.setter + def target_node(self, target_node: str): + """Sets the target_node of this ConnectionConnection. + + + :param target_node: The target_node of this ConnectionConnection. + :type target_node: str + """ + + self._target_node = target_node + + @property + def connection_id(self) -> str: + """Gets the connection_id of this ConnectionConnection. + + + :return: The connection_id of this ConnectionConnection. + :rtype: str + """ + return self._connection_id + + @connection_id.setter + def connection_id(self, connection_id: str): + """Sets the connection_id of this ConnectionConnection. + + + :param connection_id: The connection_id of this ConnectionConnection. + :type connection_id: str + """ + + self._connection_id = connection_id + + @property + def bandwidth(self) -> int: + """Gets the bandwidth of this ConnectionConnection. + + + :return: The bandwidth of this ConnectionConnection. + :rtype: int + """ + return self._bandwidth + + @bandwidth.setter + def bandwidth(self, bandwidth: int): + """Sets the bandwidth of this ConnectionConnection. + + + :param bandwidth: The bandwidth of this ConnectionConnection. + :type bandwidth: int + """ + + self._bandwidth = bandwidth + + @property + def source_node(self) -> str: + """Gets the source_node of this ConnectionConnection. + + + :return: The source_node of this ConnectionConnection. + :rtype: str + """ + return self._source_node + + @source_node.setter + def source_node(self, source_node: str): + """Sets the source_node of this ConnectionConnection. + + + :param source_node: The source_node of this ConnectionConnection. + :type source_node: str + """ + + self._source_node = source_node + + @property + def layer_protocol_name(self) -> TopologyLayerProtocolName: + """Gets the layer_protocol_name of this ConnectionConnection. + + + :return: The layer_protocol_name of this ConnectionConnection. + :rtype: TopologyLayerProtocolName + """ + return self._layer_protocol_name + + @layer_protocol_name.setter + def layer_protocol_name(self, layer_protocol_name: TopologyLayerProtocolName): + """Sets the layer_protocol_name of this ConnectionConnection. + + + :param layer_protocol_name: The layer_protocol_name of this ConnectionConnection. + :type layer_protocol_name: TopologyLayerProtocolName + """ + + self._layer_protocol_name = layer_protocol_name diff --git a/restconf/connectionserver/swagger_server/models/topology_layer_protocol_name.py b/restconf/connectionserver/swagger_server/models/topology_layer_protocol_name.py new file mode 100644 index 0000000..2ea9bee --- /dev/null +++ b/restconf/connectionserver/swagger_server/models/topology_layer_protocol_name.py @@ -0,0 +1,42 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from swagger_server.models.base_model_ import Model +from swagger_server import util + + +class TopologyLayerProtocolName(Model): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """ + + """ + allowed enum values + """ + ETH = "ETH" + OPTICAL = "OPTICAL" + def __init__(self): # noqa: E501 + """TopologyLayerProtocolName - a model defined in Swagger + + """ + self.swagger_types = { + } + + self.attribute_map = { + } + + @classmethod + def from_dict(cls, dikt) -> 'TopologyLayerProtocolName': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The topology.LayerProtocolName of this TopologyLayerProtocolName. # noqa: E501 + :rtype: TopologyLayerProtocolName + """ + return util.deserialize_model(dikt, cls) diff --git a/restconf/connectionserver/swagger_server/swagger/swagger.yaml b/restconf/connectionserver/swagger_server/swagger/swagger.yaml new file mode 100644 index 0000000..85af552 --- /dev/null +++ b/restconf/connectionserver/swagger_server/swagger/swagger.yaml @@ -0,0 +1,174 @@ +openapi: 3.0.1 +info: + title: connection API + description: connection API generated from yang definitions + version: "1.0" +servers: +- url: //localhost:1234/ +paths: + /data/connection/: + post: + tags: + - connection + description: creates connection.Connection + operationId: data_connection_post + requestBody: + description: connection.Connection to be added to list + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + required: false + responses: + 201: + description: Object created + content: {} + 400: + description: Internal error + content: {} + 409: + description: Object already exists + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + /data/connection={connection-id}/: + get: + tags: + - connection + description: returns connection.Connection + operationId: data_connectionconnection_id_get + parameters: + - name: connection-id + in: path + description: Id of connection + required: true + schema: + type: string + responses: + 200: + description: connection.Connection + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + 400: + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + put: + tags: + - connection + description: creates or updates connection.Connection + operationId: data_connectionconnection_id_put + parameters: + - name: connection-id + in: path + description: Id of connection + required: true + schema: + type: string + requestBody: + description: connection.Connection to be added or updated + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + required: false + responses: + 201: + description: Object created + content: {} + 204: + description: Object modified + content: {} + 400: + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + post: + tags: + - connection + description: creates connection.Connection + operationId: data_connectionconnection_id_post + parameters: + - name: connection-id + in: path + description: Id of connection + required: true + schema: + type: string + requestBody: + description: connection.Connection to be added to list + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + required: false + responses: + 201: + description: Object created + content: {} + 400: + description: Internal error + content: {} + 409: + description: Object already exists + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + delete: + tags: + - connection + description: removes connection.Connection + operationId: data_connectionconnection_id_delete + parameters: + - name: connection-id + in: path + description: Id of connection + required: true + schema: + type: string + responses: + 204: + description: Object deleted + content: {} + 400: + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller +components: + schemas: + connection.Connection: + type: object + properties: + target-port: + type: string + x-path: /topology:topology/topology:node/topology:port/topology:port-id + source-port: + type: string + x-path: /topology:topology/topology:node/topology:port/topology:port-id + target-node: + type: string + x-path: /topology:topology/topology:node/topology:node-id + connection-id: + type: string + bandwidth: + type: integer + format: int64 + source-node: + type: string + x-path: /topology:topology/topology:node/topology:node-id + layer-protocol-name: + $ref: '#/components/schemas/topology.LayerProtocolName' + example: + target-port: target-port + source-port: source-port + target-node: target-node + connection-id: connection-id + bandwidth: 0 + source-node: source-node + layer-protocol-name: ETH + topology.LayerProtocolName: + type: string + enum: + - ETH + - OPTICAL + diff --git a/restconf/connectionserver/swagger_server/test/__init__.py b/restconf/connectionserver/swagger_server/test/__init__.py new file mode 100644 index 0000000..6445063 --- /dev/null +++ b/restconf/connectionserver/swagger_server/test/__init__.py @@ -0,0 +1,16 @@ +import logging + +import connexion +from flask_testing import TestCase + +from swagger_server.encoder import JSONEncoder + + +class BaseTestCase(TestCase): + + def create_app(self): + logging.getLogger('connexion.operation').setLevel('ERROR') + app = connexion.App(__name__, specification_dir='../swagger/') + app.app.json_encoder = JSONEncoder + app.add_api('swagger.yaml') + return app.app diff --git a/restconf/connectionserver/swagger_server/test/test_connection_controller.py b/restconf/connectionserver/swagger_server/test/test_connection_controller.py new file mode 100644 index 0000000..325dad4 --- /dev/null +++ b/restconf/connectionserver/swagger_server/test/test_connection_controller.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +from __future__ import absolute_import + +from flask import json +from six import BytesIO + +from swagger_server.models.connection_connection import ConnectionConnection # noqa: E501 +from swagger_server.test import BaseTestCase + + +class TestConnectionController(BaseTestCase): + """ConnectionController integration test stubs""" + + def test_data_connection_post(self): + """Test case for data_connection_post + + + """ + body = ConnectionConnection() + response = self.client.open( + '/data/connection/', + method='POST', + data=json.dumps(body), + content_type='application/yang-data+json') + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_data_connectionconnection_id_delete(self): + """Test case for data_connectionconnection_id_delete + + + """ + response = self.client.open( + '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), + method='DELETE') + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_data_connectionconnection_id_get(self): + """Test case for data_connectionconnection_id_get + + + """ + response = self.client.open( + '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), + method='GET') + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_data_connectionconnection_id_post(self): + """Test case for data_connectionconnection_id_post + + + """ + body = ConnectionConnection() + response = self.client.open( + '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), + method='POST', + data=json.dumps(body), + content_type='application/yang-data+json') + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_data_connectionconnection_id_put(self): + """Test case for data_connectionconnection_id_put + + + """ + body = ConnectionConnection() + response = self.client.open( + '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), + method='PUT', + data=json.dumps(body), + content_type='application/yang-data+json') + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + +if __name__ == '__main__': + import unittest + unittest.main() diff --git a/restconf/connectionserver/swagger_server/util.py b/restconf/connectionserver/swagger_server/util.py new file mode 100644 index 0000000..527d142 --- /dev/null +++ b/restconf/connectionserver/swagger_server/util.py @@ -0,0 +1,141 @@ +import datetime + +import six +import typing + + +def _deserialize(data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if klass in six.integer_types or klass in (float, str, bool): + return _deserialize_primitive(data, klass) + elif klass == object: + return _deserialize_object(data) + elif klass == datetime.date: + return deserialize_date(data) + elif klass == datetime.datetime: + return deserialize_datetime(data) + elif type(klass) == typing.GenericMeta: + if klass.__extra__ == list: + return _deserialize_list(data, klass.__args__[0]) + if klass.__extra__ == dict: + return _deserialize_dict(data, klass.__args__[1]) + else: + return deserialize_model(data, klass) + + +def _deserialize_primitive(data, klass): + """Deserializes to primitive type. + + :param data: data to deserialize. + :param klass: class literal. + + :return: int, long, float, str, bool. + :rtype: int | long | float | str | bool + """ + try: + value = klass(data) + except UnicodeEncodeError: + value = six.u(data) + except TypeError: + value = data + return value + + +def _deserialize_object(value): + """Return a original value. + + :return: object. + """ + return value + + +def deserialize_date(string): + """Deserializes string to date. + + :param string: str. + :type string: str + :return: date. + :rtype: date + """ + try: + from dateutil.parser import parse + return parse(string).date() + except ImportError: + return string + + +def deserialize_datetime(string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :type string: str + :return: datetime. + :rtype: datetime + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + + +def deserialize_model(data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :type data: dict | list + :param klass: class literal. + :return: model object. + """ + instance = klass() + + if not instance.swagger_types: + return data + + for attr, attr_type in six.iteritems(instance.swagger_types): + if data is not None \ + and instance.attribute_map[attr] in data \ + and isinstance(data, (list, dict)): + value = data[instance.attribute_map[attr]] + setattr(instance, attr, _deserialize(value, attr_type)) + + return instance + + +def _deserialize_list(data, boxed_type): + """Deserializes a list and its elements. + + :param data: list to deserialize. + :type data: list + :param boxed_type: class literal. + + :return: deserialized list. + :rtype: list + """ + return [_deserialize(sub_data, boxed_type) + for sub_data in data] + + +def _deserialize_dict(data, boxed_type): + """Deserializes a dict and its elements. + + :param data: dict to deserialize. + :type data: dict + :param boxed_type: class literal. + + :return: deserialized dict. + :rtype: dict + """ + return {k: _deserialize(v, boxed_type) + for k, v in six.iteritems(data)} diff --git a/restconf/connectionserver/test-requirements.txt b/restconf/connectionserver/test-requirements.txt new file mode 100644 index 0000000..7f8d96e --- /dev/null +++ b/restconf/connectionserver/test-requirements.txt @@ -0,0 +1,6 @@ +flask_testing==0.6.1 +coverage>=4.0.3 +nose>=1.3.7 +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 diff --git a/restconf/connectionserver/tox.ini b/restconf/connectionserver/tox.ini new file mode 100644 index 0000000..3e0b644 --- /dev/null +++ b/restconf/connectionserver/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py35 + +[testenv] +deps=-r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +commands= + nosetests \ + [] \ No newline at end of file diff --git a/restconf/server/.swagger-codegen/VERSION b/restconf/server/.swagger-codegen/VERSION index a625450..e4a0720 100644 --- a/restconf/server/.swagger-codegen/VERSION +++ b/restconf/server/.swagger-codegen/VERSION @@ -1 +1 @@ -2.3.1 \ No newline at end of file +3.0.11 \ No newline at end of file diff --git a/restconf/server/Dockerfile b/restconf/server/Dockerfile index eb5704f..f9243a5 100644 --- a/restconf/server/Dockerfile +++ b/restconf/server/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3-alpine +FROM python:3.6-alpine RUN mkdir -p /usr/src/app WORKDIR /usr/src/app diff --git a/restconf/server/requirements.txt b/restconf/server/requirements.txt index 1cf2462..b5bc506 100644 --- a/restconf/server/requirements.txt +++ b/restconf/server/requirements.txt @@ -1,3 +1,3 @@ -connexion == 1.1.15 +connexion == 2.2.0 python_dateutil == 2.6.0 setuptools >= 21.0.0 diff --git a/restconf/server/setup.py b/restconf/server/setup.py index 0515672..ba555c8 100644 --- a/restconf/server/setup.py +++ b/restconf/server/setup.py @@ -5,7 +5,6 @@ NAME = "swagger_server" VERSION = "1.0.0" - # To install the library, run the following # # python setup.py install @@ -32,4 +31,3 @@ connection API generated from yang definitions """ ) - diff --git a/restconf/server/swagger_server/__main__.py b/restconf/server/swagger_server/__main__.py index 8c168f2..0121e50 100644 --- a/restconf/server/swagger_server/__main__.py +++ b/restconf/server/swagger_server/__main__.py @@ -8,7 +8,7 @@ def main(): app = connexion.App(__name__, specification_dir='./swagger/') app.app.json_encoder = encoder.JSONEncoder - app.add_api('swagger.yaml', arguments={'title': 'connection API'}) + app.add_api('swagger.yaml', arguments={'title': 'connection API'}, pythonic_params=True) app.run(port=8080) diff --git a/restconf/server/swagger_server/controllers/authorization_controller.py b/restconf/server/swagger_server/controllers/authorization_controller.py new file mode 100644 index 0000000..2f7b0bb --- /dev/null +++ b/restconf/server/swagger_server/controllers/authorization_controller.py @@ -0,0 +1,6 @@ +from typing import List +""" +controller generated to handled auth operation described at: +https://connexion.readthedocs.io/en/latest/security.html +""" + diff --git a/restconf/server/swagger_server/controllers/connection_controller.py b/restconf/server/swagger_server/controllers/connection_controller.py index 55f012e..f8c82bd 100644 --- a/restconf/server/swagger_server/controllers/connection_controller.py +++ b/restconf/server/swagger_server/controllers/connection_controller.py @@ -1,59 +1,80 @@ import connexion import six -import swagger_server.database as database from swagger_server.models.connection_connection import ConnectionConnection # noqa: E501 from swagger_server import util -def data_connection_post(connection_Connection_body_param=None): # noqa: E501 +def data_connection_post(body=None): # noqa: E501 + """data_connection_post + + creates connection.Connection # noqa: E501 + + :param body: connection.Connection to be added to list + :type body: dict | bytes + + :rtype: None + """ if connexion.request.is_json: - connection_Connection_body_param = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 - connection_Connection_body_param.connection_id=str(database.last_connection_id) - database.connection[str(database.last_connection_id)] = connection_Connection_body_param - database.last_connection_id+=1 - return connection_Connection_body_param + body = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 + return 'do some magic!' def data_connectionconnection_id_delete(connection_id): # noqa: E501 - del database.connection[connection_id] - return 'ok' + """data_connectionconnection_id_delete + + removes connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + + :rtype: None + """ + return 'do some magic!' def data_connectionconnection_id_get(connection_id): # noqa: E501 - print(database.connection) - return database.connection[connection_id] + """data_connectionconnection_id_get + + returns connection.Connection # noqa: E501 + + :param connection_id: Id of connection + :type connection_id: str + + :rtype: ConnectionConnection + """ + return 'do some magic!' -def data_connectionconnection_id_post(connection_id, connection_Connection_body_param=None): # noqa: E501 +def data_connectionconnection_id_post(connection_id, body=None): # noqa: E501 """data_connectionconnection_id_post creates connection.Connection # noqa: E501 :param connection_id: Id of connection :type connection_id: str - :param connection_Connection_body_param: connection.Connection to be added to list - :type connection_Connection_body_param: dict | bytes + :param body: connection.Connection to be added to list + :type body: dict | bytes :rtype: None """ if connexion.request.is_json: - connection_Connection_body_param = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 + body = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' -def data_connectionconnection_id_put(connection_id, connection_Connection_body_param=None): # noqa: E501 +def data_connectionconnection_id_put(connection_id, body=None): # noqa: E501 """data_connectionconnection_id_put creates or updates connection.Connection # noqa: E501 :param connection_id: Id of connection :type connection_id: str - :param connection_Connection_body_param: connection.Connection to be added or updated - :type connection_Connection_body_param: dict | bytes + :param body: connection.Connection to be added or updated + :type body: dict | bytes :rtype: None """ if connexion.request.is_json: - connection_Connection_body_param = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 + body = ConnectionConnection.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' diff --git a/restconf/server/swagger_server/models/connection_connection.py b/restconf/server/swagger_server/models/connection_connection.py index 04af850..6d6ab83 100644 --- a/restconf/server/swagger_server/models/connection_connection.py +++ b/restconf/server/swagger_server/models/connection_connection.py @@ -15,7 +15,6 @@ class ConnectionConnection(Model): Do not edit the class manually. """ - def __init__(self, target_port: str=None, source_port: str=None, target_node: str=None, connection_id: str=None, bandwidth: int=None, source_node: str=None, layer_protocol_name: TopologyLayerProtocolName=None): # noqa: E501 """ConnectionConnection - a model defined in Swagger @@ -53,7 +52,6 @@ def __init__(self, target_port: str=None, source_port: str=None, target_node: st 'source_node': 'source-node', 'layer_protocol_name': 'layer-protocol-name' } - self._target_port = target_port self._source_port = source_port self._target_node = target_node diff --git a/restconf/server/swagger_server/models/topology_layer_protocol_name.py b/restconf/server/swagger_server/models/topology_layer_protocol_name.py index f884636..2ea9bee 100644 --- a/restconf/server/swagger_server/models/topology_layer_protocol_name.py +++ b/restconf/server/swagger_server/models/topology_layer_protocol_name.py @@ -20,7 +20,6 @@ class TopologyLayerProtocolName(Model): """ ETH = "ETH" OPTICAL = "OPTICAL" - def __init__(self): # noqa: E501 """TopologyLayerProtocolName - a model defined in Swagger diff --git a/restconf/server/swagger_server/swagger/swagger.yaml b/restconf/server/swagger_server/swagger/swagger.yaml index b1f954c..85af552 100644 --- a/restconf/server/swagger_server/swagger/swagger.yaml +++ b/restconf/server/swagger_server/swagger/swagger.yaml @@ -1,156 +1,174 @@ ---- -swagger: "2.0" +openapi: 3.0.1 info: - description: "connection API generated from yang definitions" + title: connection API + description: connection API generated from yang definitions version: "1.0" - title: "connection API" -host: "localhost:1234" -consumes: -- "application/yang-data+json" -produces: -- "application/yang-data+json" +servers: +- url: //localhost:1234/ paths: /data/connection/: post: tags: - - "connection" - description: "creates connection.Connection" - operationId: "data_connection_post" - parameters: - - in: "body" - name: "connection_Connection_body_param" - description: "connection.Connection to be added to list" + - connection + description: creates connection.Connection + operationId: data_connection_post + requestBody: + description: connection.Connection to be added to list + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' required: false - schema: - $ref: "#/definitions/connection.Connection" responses: 201: - description: "Object created" + description: Object created + content: {} 400: - description: "Internal error" + description: Internal error + content: {} 409: - description: "Object already exists" - x-swagger-router-controller: "swagger_server.controllers.connection_controller" - /data/connection={connection_id}/: + description: Object already exists + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + /data/connection={connection-id}/: get: tags: - - "connection" - description: "returns connection.Connection" - operationId: "data_connectionconnection_id_get" + - connection + description: returns connection.Connection + operationId: data_connectionconnection_id_get parameters: - - name: "connection_id" - in: "path" - description: "Id of connection" + - name: connection-id + in: path + description: Id of connection required: true - type: "string" + schema: + type: string responses: 200: - description: "connection.Connection" - schema: - $ref: "#/definitions/connection.Connection" + description: connection.Connection + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' 400: - description: "Internal error" - x-swagger-router-controller: "swagger_server.controllers.connection_controller" - post: + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + put: tags: - - "connection" - description: "creates connection.Connection" - operationId: "data_connectionconnection_id_post" + - connection + description: creates or updates connection.Connection + operationId: data_connectionconnection_id_put parameters: - - name: "connection_id" - in: "path" - description: "Id of connection" + - name: connection-id + in: path + description: Id of connection required: true - type: "string" - - in: "body" - name: "connection_Connection_body_param" - description: "connection.Connection to be added to list" - required: false schema: - $ref: "#/definitions/connection.Connection" + type: string + requestBody: + description: connection.Connection to be added or updated + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + required: false responses: 201: - description: "Object created" + description: Object created + content: {} + 204: + description: Object modified + content: {} 400: - description: "Internal error" - 409: - description: "Object already exists" - x-swagger-router-controller: "swagger_server.controllers.connection_controller" - put: + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller + post: tags: - - "connection" - description: "creates or updates connection.Connection" - operationId: "data_connectionconnection_id_put" + - connection + description: creates connection.Connection + operationId: data_connectionconnection_id_post parameters: - - name: "connection_id" - in: "path" - description: "Id of connection" + - name: connection-id + in: path + description: Id of connection required: true - type: "string" - - in: "body" - name: "connection_Connection_body_param" - description: "connection.Connection to be added or updated" - required: false schema: - $ref: "#/definitions/connection.Connection" + type: string + requestBody: + description: connection.Connection to be added to list + content: + application/yang-data+json: + schema: + $ref: '#/components/schemas/connection.Connection' + required: false responses: 201: - description: "Object created" - 204: - description: "Object modified" + description: Object created + content: {} 400: - description: "Internal error" - x-swagger-router-controller: "swagger_server.controllers.connection_controller" + description: Internal error + content: {} + 409: + description: Object already exists + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller delete: tags: - - "connection" - description: "removes connection.Connection" - operationId: "data_connectionconnection_id_delete" + - connection + description: removes connection.Connection + operationId: data_connectionconnection_id_delete parameters: - - name: "connection_id" - in: "path" - description: "Id of connection" + - name: connection-id + in: path + description: Id of connection required: true - type: "string" + schema: + type: string responses: 204: - description: "Object deleted" + description: Object deleted + content: {} 400: - description: "Internal error" - x-swagger-router-controller: "swagger_server.controllers.connection_controller" -definitions: - connection.Connection: - type: "object" - properties: - target-port: - type: "string" - x-path: "/topology:topology/topology:node/topology:port/topology:port-id" - source-port: - type: "string" - x-path: "/topology:topology/topology:node/topology:port/topology:port-id" - target-node: - type: "string" - x-path: "/topology:topology/topology:node/topology:node-id" - connection-id: - type: "string" - bandwidth: - type: "integer" - format: "int64" - source-node: - type: "string" - x-path: "/topology:topology/topology:node/topology:node-id" - layer-protocol-name: - $ref: "#/definitions/topology.LayerProtocolName" - example: - target-port: "target-port" - source-port: "source-port" - target-node: "target-node" - connection-id: "connection-id" - bandwidth: 0 - source-node: "source-node" - layer-protocol-name: {} - topology.LayerProtocolName: - type: "string" - enum: - - "ETH" - - "OPTICAL" + description: Internal error + content: {} + x-openapi-router-controller: swagger_server.controllers.connection_controller +components: + schemas: + connection.Connection: + type: object + properties: + target-port: + type: string + x-path: /topology:topology/topology:node/topology:port/topology:port-id + source-port: + type: string + x-path: /topology:topology/topology:node/topology:port/topology:port-id + target-node: + type: string + x-path: /topology:topology/topology:node/topology:node-id + connection-id: + type: string + bandwidth: + type: integer + format: int64 + source-node: + type: string + x-path: /topology:topology/topology:node/topology:node-id + layer-protocol-name: + $ref: '#/components/schemas/topology.LayerProtocolName' + example: + target-port: target-port + source-port: source-port + target-node: target-node + connection-id: connection-id + bandwidth: 0 + source-node: source-node + layer-protocol-name: ETH + topology.LayerProtocolName: + type: string + enum: + - ETH + - OPTICAL + diff --git a/restconf/server/swagger_server/test/test_connection_controller.py b/restconf/server/swagger_server/test/test_connection_controller.py index 85847ac..325dad4 100644 --- a/restconf/server/swagger_server/test/test_connection_controller.py +++ b/restconf/server/swagger_server/test/test_connection_controller.py @@ -17,11 +17,11 @@ def test_data_connection_post(self): """ - connection_Connection_body_param = ConnectionConnection() + body = ConnectionConnection() response = self.client.open( '/data/connection/', method='POST', - data=json.dumps(connection_Connection_body_param), + data=json.dumps(body), content_type='application/yang-data+json') self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) @@ -33,8 +33,7 @@ def test_data_connectionconnection_id_delete(self): """ response = self.client.open( '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), - method='DELETE', - content_type='application/yang-data+json') + method='DELETE') self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) @@ -45,8 +44,7 @@ def test_data_connectionconnection_id_get(self): """ response = self.client.open( '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), - method='GET', - content_type='application/yang-data+json') + method='GET') self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) @@ -55,11 +53,11 @@ def test_data_connectionconnection_id_post(self): """ - connection_Connection_body_param = ConnectionConnection() + body = ConnectionConnection() response = self.client.open( '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), method='POST', - data=json.dumps(connection_Connection_body_param), + data=json.dumps(body), content_type='application/yang-data+json') self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) @@ -69,11 +67,11 @@ def test_data_connectionconnection_id_put(self): """ - connection_Connection_body_param = ConnectionConnection() + body = ConnectionConnection() response = self.client.open( '/data/connection={connection-id}/'.format(connection_id='connection_id_example'), method='PUT', - data=json.dumps(connection_Connection_body_param), + data=json.dumps(body), content_type='application/yang-data+json') self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) diff --git a/restconf/swagger-codegen-cli.jar b/restconf/swagger-codegen-cli.jar index d0c6b16..25f1f6f 100644 Binary files a/restconf/swagger-codegen-cli.jar and b/restconf/swagger-codegen-cli.jar differ diff --git a/tapi/server/controllers/default_controller.py b/tapi/server/controllers/default_controller.py index 415e8f7..da65ad2 100644 --- a/tapi/server/controllers/default_controller.py +++ b/tapi/server/controllers/default_controller.py @@ -720,7 +720,7 @@ def retrieve_context_topology_node_node(uuid) -> str: return array_cs def retrieve_context_topology_node_node_by_id(uuid, node_uuid) -> str: - logging.info("retrieve_context_topology_node_node_by_id %s $s", uuid, node_uuid) + logging.info("retrieve_context_topology_node_node_by_id %s %s", uuid, node_uuid) for item in database.context['topology']: if item['uuid'] == uuid: for node in item['node']: @@ -913,11 +913,29 @@ def retrieve_context_topology_node_owned_node_edge_point_name_name(uuid, nodeUui def retrieve_context_topology_node_owned_node_edge_point_name_name_by_id(uuid, nodeUuid, ownedNodeEdgePointUuid, valueName) -> str: return 'do some magic!' -def retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point(uuid, nodeUuid) -> str: - return 'do some magic!' +def retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point(uuid, node_uuid) -> str: + logging.info("retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point %s %s", uuid, node_uuid) + for item in database.context['topology']: + if item['uuid'] == uuid: + for node in item['node']: + if node['uuid']==node_uuid: + array_cs=[] + for nep in node['owned-node-edge-point']: + uri="/restconf/config/context/topology/"+uuid+"/node/"+node_uuid+"/owned-node-edge-point/"+nep['uuid']+"/" + array_cs.append(uri) + #json = { 'itemlist' : array_cs } + return array_cs -def retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point_by_id(uuid, nodeUuid, ownedNodeEdgePointUuid) -> str: - return 'do some magic!' + +def retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point_by_id(uuid, node_uuid, owned_node_edge_point_uuid) -> str: + logging.info("retrieve_context_topology_node_owned_node_edge_point_owned_node_edge_point_by_id %s %s %s", uuid, node_uuid, owned_node_edge_point_uuid) + for item in database.context['topology']: + if item['uuid'] == uuid: + for node in item['node']: + if node['uuid'] == node_uuid: + for nep in node['owned-node-edge-point']: + if nep['uuid'] == owned_node_edge_point_uuid: + return nep def retrieve_context_topology_node_total_potential_capacity_bandwidth_profile_bandwidth_profile(uuid, nodeUuid) -> str: return 'do some magic!' diff --git a/tapi/server/swagger/swagger.yaml b/tapi/server/swagger/swagger.yaml index b0d79a0..a62ba72 100644 --- a/tapi/server/swagger/swagger.yaml +++ b/tapi/server/swagger/swagger.yaml @@ -8654,7 +8654,7 @@ paths: x-path: "/context/topology/{uuid}/node/{node_uuid}/owned-node-edge-point/{owned-node-edge-point_uuid}/" 400: description: "Internal Error" - /config/context/topology/{uuid}/node/{node_uuid}/owned-node-edge-point/{owned-node-edge-point_uuid}/: + /config/context/topology/{uuid}/node/{node_uuid}/owned-node-edge-point/{owned_node_edge_point_uuid}/: get: tags: - "default_controller" @@ -8676,7 +8676,7 @@ paths: description: "ID of node_uuid" required: true type: "string" - - name: "owned-node-edge-point_uuid" + - name: "owned_node_edge_point_uuid" in: "path" description: "ID of owned-node-edge-point_uuid" required: true