summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxinhuili <lxinhui@vmware.com>2017-03-08 23:35:40 -0800
committerxinhuili <lxinhui@vmware.com>2017-03-10 04:05:17 -0800
commit3ea554ca920a0a21e5dca667f366379ca9c146c4 (patch)
tree8f8871c6663f3df1cf6e389948c4ff7f94e684dc
parent2fbc2b268c8ef2c7329fb613ce1599084e2c91bb (diff)
Add basic VIM function into VIO NFVI
This patch is to add basic VIM function for VIO. Change-Id: I5867680ce3f6881fce55f10551368cc82ff1d592 Issue-ids: MULTIVIM-36 Signed-off-by: xinhuili <lxinhui@vmware.com>
-rw-r--r--vio/requirements.txt2
-rw-r--r--vio/vio/pub/config/config.py8
-rw-r--r--vio/vio/pub/vim/__init__.py0
-rw-r--r--vio/vio/pub/vim/const.py26
-rw-r--r--vio/vio/pub/vim/drivers/__init__.py0
-rw-r--r--vio/vio/pub/vim/drivers/base.py21
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/__init__.py0
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/cinder_v2.py51
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/compute.py95
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/image_v2.py67
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/keystone_v3.py34
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/neutron_v2_0.py87
-rw-r--r--vio/vio/pub/vim/drivers/openstacksdk/sdk.py132
-rw-r--r--vio/vio/pub/vim/drivers/vimdriver.py29
-rw-r--r--vio/vio/pub/vim/vimapi/__init__.py0
-rw-r--r--vio/vio/pub/vim/vimapi/baseclient.py60
-rw-r--r--vio/vio/pub/vim/vimapi/cinder/OperateVolume.py50
-rw-r--r--vio/vio/pub/vim/vimapi/cinder/__init__.py0
-rw-r--r--vio/vio/pub/vim/vimapi/glance/OperateImage.py100
-rw-r--r--vio/vio/pub/vim/vimapi/glance/__init__.py0
-rw-r--r--vio/vio/pub/vim/vimapi/keystone/OperateTenant.py38
-rw-r--r--vio/vio/pub/vim/vimapi/keystone/__init__.py0
-rw-r--r--vio/vio/pub/vim/vimapi/keystone/auth.py27
-rw-r--r--vio/vio/pub/vim/vimapi/network/OperateNetwork.py112
-rw-r--r--vio/vio/pub/vim/vimapi/network/OperatePort.py82
-rw-r--r--vio/vio/pub/vim/vimapi/network/OperateSubnet.py85
-rw-r--r--vio/vio/pub/vim/vimapi/network/__init__.py0
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateFlavors.py64
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateHypervisor.py31
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateLimits.py23
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateNova.py39
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateServers.py109
-rw-r--r--vio/vio/pub/vim/vimapi/nova/OperateService.py25
-rw-r--r--vio/vio/pub/vim/vimapi/nova/__init__.py12
-rw-r--r--vio/vio/swagger/image_utils.py55
-rw-r--r--vio/vio/swagger/nova_utils.py109
-rw-r--r--vio/vio/swagger/urls.py64
-rw-r--r--vio/vio/swagger/views/__init__.py11
-rw-r--r--vio/vio/swagger/views/flavor/__init__.py11
-rw-r--r--vio/vio/swagger/views/flavor/views.py99
-rw-r--r--vio/vio/swagger/views/hypervisor/__init__.py0
-rw-r--r--vio/vio/swagger/views/hypervisor/views.py45
-rw-r--r--vio/vio/swagger/views/image/__init__.py11
-rw-r--r--vio/vio/swagger/views/image/views.py95
-rw-r--r--vio/vio/swagger/views/limits/__init__.py0
-rw-r--r--vio/vio/swagger/views/limits/views.py42
-rw-r--r--vio/vio/swagger/views/multivim.flavor.swagger.json392
-rw-r--r--vio/vio/swagger/views/multivim.host.swagger.json233
-rw-r--r--vio/vio/swagger/views/multivim.image.swagger.json359
-rw-r--r--vio/vio/swagger/views/multivim.limit.swagger.json158
-rw-r--r--vio/vio/swagger/views/multivim.network.swagger.json349
-rw-r--r--vio/vio/swagger/views/multivim.server.swagger.json488
-rw-r--r--vio/vio/swagger/views/multivim.subnet.swagger.json417
-rw-r--r--vio/vio/swagger/views/multivim.tenant.swagger.json102
-rw-r--r--vio/vio/swagger/views/multivim.volume.swagger.json378
-rw-r--r--vio/vio/swagger/views/multivim.vport.swagger.json363
-rw-r--r--vio/vio/swagger/views/network/__init__.py0
-rw-r--r--vio/vio/swagger/views/network/views.py76
-rw-r--r--vio/vio/swagger/views/port/__init__.py0
-rw-r--r--vio/vio/swagger/views/port/views.py76
-rw-r--r--vio/vio/swagger/views/server/__init__.py11
-rw-r--r--vio/vio/swagger/views/server/views.py111
-rw-r--r--vio/vio/swagger/views/service/__init__.py0
-rw-r--r--vio/vio/swagger/views/service/views.py44
-rw-r--r--vio/vio/swagger/views/subnet/__init__.py0
-rw-r--r--vio/vio/swagger/views/subnet/views.py76
-rw-r--r--vio/vio/swagger/views/swagger_json.py87
-rw-r--r--vio/vio/swagger/views/tenant/__init__.py11
-rw-r--r--vio/vio/swagger/views/tenant/views.py51
-rw-r--r--vio/vio/swagger/views/volume/__init__.py11
-rw-r--r--vio/vio/swagger/views/volume/views.py106
-rw-r--r--vio/vio/swagger/volume_utils.py68
72 files changed, 5912 insertions, 6 deletions
diff --git a/vio/requirements.txt b/vio/requirements.txt
index fba25ad..ca74dbc 100644
--- a/vio/requirements.txt
+++ b/vio/requirements.txt
@@ -13,7 +13,7 @@ django-redis-cache==0.13.1
httplib2==0.9.2
# for call openstack api
-openstacksdk==0.8.1
+openstacksdk==0.9.14
# for unit test
coverage==4.2
diff --git a/vio/vio/pub/config/config.py b/vio/vio/pub/config/config.py
index 7b05698..71a44aa 100644
--- a/vio/vio/pub/config/config.py
+++ b/vio/vio/pub/config/config.py
@@ -25,11 +25,11 @@ REDIS_PORT = '6379'
REDIS_PASSWD = ''
# [mysql]
-DB_IP = "127.0.0.1"
+DB_IP = '127.0.0.1'
DB_PORT = 3306
-DB_NAME = "multivimvio"
-DB_USER = "root"
-DB_PASSWD = "password"
+DB_NAME = 'multivimvio'
+DB_USER = 'root'
+DB_PASSWD = 'password'
# [register]
REG_TO_MSB_WHEN_START = True
diff --git a/vio/vio/pub/vim/__init__.py b/vio/vio/pub/vim/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/__init__.py
diff --git a/vio/vio/pub/vim/const.py b/vio/vio/pub/vim/const.py
new file mode 100644
index 0000000..9580148
--- /dev/null
+++ b/vio/vio/pub/vim/const.py
@@ -0,0 +1,26 @@
+# Copyright 2016 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+VIM_OPENSTACK = "vmware"
+RES_TYPE_KEY = "res_type"
+RES_TYPE_NEW = 1
+RES_TYPE_EXIST = 0
+SHARED_NET = 1
+SUPPORT_VLAN_TRANSPARENT = 1
+DEFAULT_MTU = 1500
+IPV4 = 4
+IPV6 = 6
+ENABLE_DHCP = 1
+
diff --git a/vio/vio/pub/vim/drivers/__init__.py b/vio/vio/pub/vim/drivers/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/__init__.py
diff --git a/vio/vio/pub/vim/drivers/base.py b/vio/vio/pub/vim/drivers/base.py
new file mode 100644
index 0000000..22402c9
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/base.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2017 VMware, 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 copy
+
+
+
+class DriverBase(object):
+ '''Base class for all drivers.'''
+
+ def __init__(self, params):
+ self.conn_params = copy.deepcopy(params)
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/__init__.py b/vio/vio/pub/vim/drivers/openstacksdk/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/__init__.py
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/cinder_v2.py b/vio/vio/pub/vim/drivers/openstacksdk/cinder_v2.py
new file mode 100644
index 0000000..0e0c11c
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/cinder_v2.py
@@ -0,0 +1,51 @@
+# Copyright 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+from vio.pub.vim.drivers import base
+from vio.pub.vim.drivers.openstacksdk import sdk
+
+LOG = logging.getLogger(__name__)
+
+class CinderClient(base.DriverBase):
+ '''Cinder V2 driver.'''
+
+ def __init__(self, params):
+ super(CinderClient, self).__init__(params)
+ LOG.info("%s", str(params))
+ self.conn = sdk.create_connection(params)
+ self.session = self.conn.session
+
+ @sdk.translate_exception
+ def list_volumes(self, **query):
+ volumes = self.conn.block_store.volumes(**query)
+ return volumes
+
+
+ @sdk.translate_exception
+ def create_volume(self, **body):
+ volume_info = self.conn.block_store.create_volume(**body)
+ return volume_info
+
+
+ @sdk.translate_exception
+ def delete_volume(self, volumeid):
+ self.conn.block_store.delete_volume(volumeid)
+
+
+ @sdk.translate_exception
+ def get_volume(self, volumeid):
+ volume_info = self.conn.block_store.get_volume(volumeid)
+ return volume_info
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/compute.py b/vio/vio/pub/vim/drivers/openstacksdk/compute.py
new file mode 100644
index 0000000..cfe9461
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/compute.py
@@ -0,0 +1,95 @@
+# Copyright (c) 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+import base64
+import logging
+
+from vio.pub.vim.drivers import base
+from vio.pub.vim.drivers.openstacksdk import sdk
+
+LOG = logging.getLogger(__name__)
+
+
+class ComputeClient(base.DriverBase):
+ """Compute driver."""
+
+ def __init__(self, params):
+ super(ComputeClient, self).__init__(params)
+ self.conn = sdk.create_connection(params)
+ self.session = self.conn.session
+
+ @sdk.translate_exception
+ def create_server(self, **kwargs):
+ server = self.conn.compute.create_server(**kwargs)
+ return server
+
+ @sdk.translate_exception
+ def list_servers(self):
+ servers = self.conn.compute.servers()
+ return servers
+
+ @sdk.translate_exception
+ def get_server(self, server_id, **query):
+ server = self.conn.compute.get_server(server=server_id)
+ return server
+
+ @sdk.translate_exception
+ def delete_server(self, server_id, **query):
+ self.conn.compute.delete_server(server=server_id)
+
+ @sdk.translate_exception
+ def list_server_interfaces(self, server_id):
+ ifaces = self.conn.compute.server_interfaces(server_id)
+ return list(ifaces)
+
+ @sdk.translate_exception
+ def list_flavors(self, **query):
+ flavors = self.conn.compute.flavors()
+ return flavors
+
+ @sdk.translate_exception
+ def create_flavor(self, **kwargs):
+ return self.conn.compute.create_flavor(**kwargs)
+
+ @sdk.translate_exception
+ def get_flavor(self, flavor_id, **query):
+ return self.conn.compute.get_flavor(flavor=flavor_id)
+
+ @sdk.translate_exception
+ def find_flavor(self, flavor_id):
+ return self.conn.compute.find_flavor(flavor_id, ignore_missing=False)
+
+ @sdk.translate_exception
+ def delete_flavor(self, flavor_id, **query):
+ self.conn.compute.delete_flavor(flavor=flavor_id)
+
+ @sdk.translate_exception
+ def get_flavor_extra_specs(self, flavor_id, **query):
+ return None
+
+ @sdk.translate_exception
+ def find_image(self, image_id, ignore_missing=False):
+ return self.conn.compute.find_image(
+ image_id, ignore_missing=ignore_missing)
+
+ @sdk.translate_exception
+ def get_limits(self, **kwargs):
+ return self.conn.compute.get_limits()
+
+ @sdk.translate_exception
+ def list_services(self, **kwargs):
+ return self.conn.compute.services()
+
+ @sdk.translate_exception
+ def get_hypervisor(self, hypervisor, **kwargs):
+ return self.conn.compute.get_hypervisor(hypervisor=hypervisor)
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/image_v2.py b/vio/vio/pub/vim/drivers/openstacksdk/image_v2.py
new file mode 100644
index 0000000..79ccfba
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/image_v2.py
@@ -0,0 +1,67 @@
+# Copyright 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+from vio.pub.vim.drivers import base
+from vio.pub.vim.drivers.openstacksdk import sdk
+from openstack.image.v2 import image as _image
+
+LOG = logging.getLogger(__name__)
+
+
+class GlanceClient(base.DriverBase):
+
+ def __init__(self, params):
+ super(GlanceClient, self).__init__(params)
+ LOG.info("%s", str(params))
+ self.conn = sdk.create_connection(params)
+ self.session = self.conn.session
+ self._proxy = self.conn.image
+
+ @sdk.translate_exception
+ def list_images(self, **query):
+ images = self._proxy.images(**query)
+ return images
+
+ @sdk.translate_exception
+ def get_image(self, imageid):
+ image = self._proxy.get_image(imageid)
+ return image
+
+ @sdk.translate_exception
+ def delete_image(self, imageid):
+ self._proxy.delete_image(imageid)
+
+ @sdk.translate_exception
+ def create_image(self, **data):
+
+ disk_format = data.pop('disk_format')
+ container_format = data.pop('container_format')
+
+ if not all([container_format, disk_format]):
+ LOG.error( "Both container_format and disk_format are required")
+
+ try:
+ img = self._proxy._create(_image.Image, disk_format=disk_format,
+ container_format=container_format, **data)
+ except Exception as ex:
+ pass
+ return img
+
+ @sdk.translate_exception
+ def upload_image(self, data, image):
+ image.data = data
+ image.upload(self.session) \ No newline at end of file
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/keystone_v3.py b/vio/vio/pub/vim/drivers/openstacksdk/keystone_v3.py
new file mode 100644
index 0000000..7628477
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/keystone_v3.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging
+
+from vio.pub.vim.drivers import base
+from vio.pub.vim.drivers.openstacksdk import sdk
+
+LOG = logging.getLogger(__name__)
+
+
+class KeystoneClient(base.DriverBase):
+ '''Keystone V3 driver.'''
+
+ def __init__(self, params):
+ super(KeystoneClient, self).__init__(params)
+ self.conn = sdk.create_connection(params)
+ self.session = self.conn.session
+
+ @sdk.translate_exception
+ def project_list(self):
+ projects = self.conn.identity.projects()
+ return projects
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/neutron_v2_0.py b/vio/vio/pub/vim/drivers/openstacksdk/neutron_v2_0.py
new file mode 100644
index 0000000..6ab7535
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/neutron_v2_0.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from vio.pub.vim.drivers import base
+from vio.pub.vim.drivers.openstacksdk import sdk
+
+
+class NeutronClient(base.DriverBase):
+ '''Neutron V2.0 driver.'''
+
+ def __init__(self, params):
+ super(NeutronClient, self).__init__(params)
+ self.conn = sdk.create_connection(params)
+
+ @sdk.translate_exception
+ def subnet_create(self, **args):
+ network = self.conn.network.create_subnet(**args)
+ return network
+
+ @sdk.translate_exception
+ def network_create(self, **args):
+ network = self.conn.network.create_network(**args)
+ return network
+
+ @sdk.translate_exception
+ def network_get(self, name_or_id):
+ network = self.conn.network.find_network(name_or_id)
+ return network
+
+ @sdk.translate_exception
+ def network_delete(self, name_or_id):
+ res = self.conn.network.delete_network(name_or_id)
+ return res
+
+ @sdk.translate_exception
+ def networks_get(self, **kwargs):
+ network = self.conn.network.networks(**kwargs)
+ return network
+
+ @sdk.translate_exception
+ def subnets_get(self, **kwargs):
+ subnets = self.conn.network.subnets(**kwargs)
+ return subnets
+
+ @sdk.translate_exception
+ def subnet_delete(self, name_or_id):
+ res = self.conn.network.delete_subnet(name_or_id)
+ return res
+
+ @sdk.translate_exception
+ def port_find(self, name_or_id, ignore_missing=False):
+ port = self.conn.network.find_port(name_or_id, ignore_missing)
+ return port
+
+ @sdk.translate_exception
+ def subnet_get(self, name_or_id, ignore_missing=False):
+ subnet = self.conn.network.find_subnet(name_or_id, ignore_missing)
+ return subnet
+
+ @sdk.translate_exception
+ def port_create(self, **attr):
+ res = self.conn.network.create_port(**attr)
+ return res
+
+ @sdk.translate_exception
+ def port_delete(self, port, ignore_missing=True):
+ res = self.conn.network.delete_port(
+ port=port, ignore_missing=ignore_missing)
+ return res
+
+ @sdk.translate_exception
+ def ports_get(self, **kwargs):
+ ports = self.conn.network.ports(**kwargs)
+ return ports
+
+
diff --git a/vio/vio/pub/vim/drivers/openstacksdk/sdk.py b/vio/vio/pub/vim/drivers/openstacksdk/sdk.py
new file mode 100644
index 0000000..9f01a4d
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/openstacksdk/sdk.py
@@ -0,0 +1,132 @@
+# Copyright (c) 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+'''
+SDK Client
+'''
+import functools
+import json
+import logging
+import six
+
+from openstack import connection
+from openstack import exceptions as sdk_exc
+from openstack import profile
+from requests import exceptions as req_exc
+
+
+USER_AGENT = 'vimdriver-vio'
+exc = sdk_exc
+LOG = logging.getLogger(__name__)
+
+
+def parse_exception(ex):
+ '''Parse exception code and yield useful information.'''
+ code = 500
+
+ if isinstance(ex, sdk_exc.HttpException):
+ # some exceptions don't contain status_code
+ if ex.http_status is not None:
+ code = ex.http_status
+ message = ex.message
+ data = {}
+ if ex.details is None and ex.response is not None:
+ data = ex.response.json()
+ else:
+ try:
+ data = json.loads(ex.details)
+ except Exception:
+ # Some exceptions don't have details record or
+ # are not in JSON format
+ pass
+
+ # try dig more into the exception record
+ # usually 'data' has two types of format :
+ # type1: {"forbidden": {"message": "error message", "code": 403}
+ # type2: {"code": 404, "error": { "message": "not found"}}
+ if data:
+ code = data.get('code', code)
+ message = data.get('message', message)
+ error = data.get('error', None)
+ if error:
+ code = data.get('code', code)
+ message = data['error'].get('message', message)
+ else:
+ for value in data.values():
+ code = value.get('code', code)
+ message = value.get('message', message)
+
+ elif isinstance(ex, sdk_exc.SDKException):
+ # Besides HttpException there are some other exceptions like
+ # ResourceTimeout can be raised from SDK, handle them here.
+ message = ex.message
+ elif isinstance(ex, req_exc.RequestException):
+ # Exceptions that are not captured by SDK
+ code = ex.errno
+ message = six.text_type(ex)
+ else:
+ # This could be a generic exception or something we don't understand
+ message = six.text_type(ex)
+
+ import traceback
+ traceback.print_exc()
+ raise ex
+# raise senlin_exc.InternalError(code=code, message=message)
+
+
+def translate_exception(func):
+ """Decorator for exception translation."""
+
+ @functools.wraps(func)
+ def invoke_with_catch(driver, *args, **kwargs):
+ try:
+ return func(driver, *args, **kwargs)
+ except Exception as ex:
+ LOG.exception(ex)
+ raise parse_exception(ex)
+
+ return invoke_with_catch
+
+
+def create_connection(params=None):
+ if params is None:
+ params = {}
+
+ auth_plugin = 'password'
+
+ prof = profile.Profile()
+ prof.set_version('identity', 'v3')
+ prof.set_version('image', 'v2')
+
+ try:
+ conn = connection.Connection(profile=prof, verify=False, user_agent=USER_AGENT,
+ auth_plugin=auth_plugin, **params)
+ except Exception as ex:
+ raise parse_exception(ex)
+
+ return conn
+
+
+def authenticate(**kwargs):
+ '''Authenticate using openstack sdk based on user credential'''
+
+ conn = create_connection(kwargs)
+ access_info = {
+ 'token': conn.session.get_token(),
+ 'user_id': conn.session.get_user_id(),
+ 'project_id': conn.session.get_project_id()
+ }
+
+ return access_info
+
diff --git a/vio/vio/pub/vim/drivers/vimdriver.py b/vio/vio/pub/vim/drivers/vimdriver.py
new file mode 100644
index 0000000..3fb5bc0
--- /dev/null
+++ b/vio/vio/pub/vim/drivers/vimdriver.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+from vio.pub.vim.drivers.openstacksdk import image_v2
+from vio.pub.vim.drivers.openstacksdk import keystone_v3
+from vio.pub.vim.drivers.openstacksdk import cinder_v2
+from vio.pub.vim.drivers.openstacksdk import compute
+
+
+class VimDriver(object):
+ '''Generic driver class'''
+
+ def __init__(self):
+ self.identity = keystone_v3.KeystoneClient
+ self.glance = image_v2.GlanceClient
+ self.cinder = cinder_v2.CinderClient
+ self.compute = compute.ComputeClient
diff --git a/vio/vio/pub/vim/vimapi/__init__.py b/vio/vio/pub/vim/vimapi/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/__init__.py
diff --git a/vio/vio/pub/vim/vimapi/baseclient.py b/vio/vio/pub/vim/vimapi/baseclient.py
new file mode 100644
index 0000000..44b2739
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/baseclient.py
@@ -0,0 +1,60 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging
+
+from vio.pub.vim.drivers import vimdriver as driver_base
+
+LOG = logging.getLogger(__name__)
+
+
+class baseclient(object):
+
+ def __init__(self, **kwargs):
+ # initialize clients
+ self._identityclient = None
+ self._glanceclient = None
+ self._computeClient = None
+ self._cinderclient = None
+
+ def identity(self, data):
+ '''Construct compute client based on object.
+
+ :param obj: Object for which the client is created. It is expected to
+ be None when retrieving an existing client. When creating
+ a client, it contains the user and project to be used.
+ '''
+
+ if self._identityclient is not None:
+ return self._identityclient
+ self._identityclient = driver_base.VimDriver().identity(data)
+ return self._identityclient
+
+ def glance(self, data):
+ if self._glanceclient is not None:
+ return self._glanceclient
+ self._glanceclient = driver_base.VimDriver().glance(data)
+ return self._glanceclient
+
+ def compute(self, data):
+ if self._computeClient is not None:
+ return self._computeClient
+
+ self._computeClient = driver_base.VimDriver().compute(data)
+ return self._computeClient
+
+ def cinder(self, data):
+ if self._cinderclient is not None:
+ return self._cinderclient
+
+ self._cinderclient = driver_base.VimDriver().cinder(data)
+ return self._cinderclient
diff --git a/vio/vio/pub/vim/vimapi/cinder/OperateVolume.py b/vio/vio/pub/vim/vimapi/cinder/OperateVolume.py
new file mode 100644
index 0000000..4458309
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/cinder/OperateVolume.py
@@ -0,0 +1,50 @@
+# Copyright 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.baseclient import baseclient
+from vio.swagger import volume_utils
+
+logger = logging.getLogger(__name__)
+
+
+class OperateVolume(baseclient):
+
+ def __init__(self, params):
+ super(OperateVolume, self).__init__()
+ self.param = volume_utils.sdk_param_formatter(params)
+
+ def get_vim_volumes(self, **query):
+
+ volumes = self.cinder(self.param).list_volumes(**query)
+ return volumes
+
+ def create_vim_volume(self, **body):
+
+ volume = self.cinder(self.param).create_volume(**body)
+ return volume
+
+ def get_vim_volume(self, volume_id):
+
+ volume = self.cinder(self.param).get_volume(volume_id)
+ return volume
+
+ def delete_vim_volume(self, volume_id):
+
+ volume = self.cinder(self.param).delete_volume(volume_id)
+ return volume \ No newline at end of file
diff --git a/vio/vio/pub/vim/vimapi/cinder/__init__.py b/vio/vio/pub/vim/vimapi/cinder/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/cinder/__init__.py
diff --git a/vio/vio/pub/vim/vimapi/glance/OperateImage.py b/vio/vio/pub/vim/vimapi/glance/OperateImage.py
new file mode 100644
index 0000000..446f808
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/glance/OperateImage.py
@@ -0,0 +1,100 @@
+# Copyright 2017 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+import threading
+import urllib2
+
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.baseclient import baseclient
+from vio.swagger import image_utils
+
+logger = logging.getLogger(__name__)
+
+
+running_threads = {}
+running_thread_lock = threading.Lock()
+
+class imageThread(threading.Thread):
+ def __init__(self, vimid, tenantid, image, imagefd):
+
+ threading.Thread.__init__(self)
+ self.imageid = image.id
+ self.imagefd = imagefd
+ self.vimid = vimid
+ self.tenantid = tenantid
+ self.image = image
+
+
+ def run(self):
+
+ logger.debug("start imagethread")
+ self.transfer_image(self.vimid, self.tenantid, self.image, self.imagefd)
+ running_thread_lock.acquire()
+ running_threads.pop(self.imageid)
+ running_thread_lock.release()
+
+
+ def transfer_image(self, vimid, tenantid, image, imagefd):
+
+ logger.debug("Image----transfer_image")
+ vim_info = extsys.get_vim_by_id(vimid)
+
+ param = image_utils.sdk_param_formatter(vim_info)
+ data = imagefd.read()
+ client = baseclient()
+ client.glance(param).upload_image(data, image)
+
+
+class OperateImage(baseclient):
+
+ def __init__(self, params):
+
+ super(OperateImage, self).__init__()
+ self.param = image_utils.sdk_param_formatter(params)
+
+ def get_vim_images(self, **query):
+
+ images = self.glance(self.param).list_images(**query)
+ return images
+
+ def get_vim_image(self, imageid):
+
+ image = self.glance(self.param).get_image(imageid)
+ return image
+
+ def delete_vim_image(self, imageid):
+
+ image = self.glance(self.param).delete_image(imageid)
+ return image
+
+ def create_vim_image(self, vimid, tenantid, **req_body):
+
+ imageurl = req_body.pop('imagePath', None)
+ imagefd = urllib2.urlopen(imageurl)
+
+ image = self.glance(self.param).create_image(**req_body)
+
+ upload_image_thread = imageThread(vimid, tenantid, image, imagefd)
+ logger.debug("launch thread to upload image: %s" % image.id)
+ running_thread_lock.acquire()
+ running_threads[image.id] = image.id
+ running_thread_lock.release()
+ try:
+ upload_image_thread.start()
+ except Exception as ex:
+ pass
+ return image \ No newline at end of file
diff --git a/vio/vio/pub/vim/vimapi/glance/__init__.py b/vio/vio/pub/vim/vimapi/glance/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/glance/__init__.py
diff --git a/vio/vio/pub/vim/vimapi/keystone/OperateTenant.py b/vio/vio/pub/vim/vimapi/keystone/OperateTenant.py
new file mode 100644
index 0000000..31e1752
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/keystone/OperateTenant.py
@@ -0,0 +1,38 @@
+# Copyright 2016 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.baseclient import baseclient
+
+logger = logging.getLogger(__name__)
+
+
+
+class OperateTenant(baseclient):
+
+ def get_projects(self, data):
+ param = {}
+ param['username'] = data['username']
+ param['user_domain_name'] = 'default'
+ param['project_domain_name'] = 'default'
+ param['password'] = data['password']
+ param['auth_url'] = data['url']
+ param['project_name'] = data['project_name']
+ projects = self.identity(param).project_list()
+ return projects
+
diff --git a/vio/vio/pub/vim/vimapi/keystone/__init__.py b/vio/vio/pub/vim/vimapi/keystone/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/keystone/__init__.py
diff --git a/vio/vio/pub/vim/vimapi/keystone/auth.py b/vio/vio/pub/vim/vimapi/keystone/auth.py
new file mode 100644
index 0000000..86f03c2
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/keystone/auth.py
@@ -0,0 +1,27 @@
+# Copyright 2016 ZTE Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.drivers import base
+
+logger = logging.getLogger(__name__)
+
+def login(data):
+
+ print data
+
diff --git a/vio/vio/pub/vim/vimapi/network/OperateNetwork.py b/vio/vio/pub/vim/vimapi/network/OperateNetwork.py
new file mode 100644
index 0000000..848878e
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/network/OperateNetwork.py
@@ -0,0 +1,112 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+import logging
+
+from vio.pub.msapi.extsys import get_vim_by_id
+from vio.pub.vim.drivers.openstacksdk import neutron_v2_0
+
+
+logger = logging.getLogger(__name__)
+
+
+def translate(mapping, data, revert=True):
+ if revert:
+ for key in mapping:
+ if key in data:
+ data[mapping[key]] = data.pop(key)
+ else:
+ for key in mapping:
+ if mapping[key] in data:
+ data[key] = data.pop(mapping[key])
+ return data
+
+
+class BaseNet(object):
+ def get_vim_info(self, vimid):
+ return get_vim_by_id(vimid)
+
+ def auth(self, vim_info):
+ param = {}
+ param['username'] = vim_info['userName']
+ param['user_domain_name'] = 'default'
+ param['project_domain_name'] = 'default'
+ param['password'] = vim_info['password']
+ param['auth_url'] = vim_info['url']
+ param['project_name'] = vim_info['tenant']
+ return neutron_v2_0.NeutronClient(param)
+
+
+class OperateNetwork(BaseNet):
+ service = {'service_type': 'network',
+ 'interface': 'public',
+ 'region_name': 'RegionOne'}
+ keys_mapping = {"segmentationId": "provider:segmentation_id",
+ "physicalNetwork": "provider:physical_network",
+ "routerExternal": "router:external",
+ "networkType": "provider:network_type",
+ "vlanTransparent": "vlan_transparent",
+ "tenantId": "project_id"
+ }
+
+ def ___init__(self, params):
+ super(Network, self).__init__(params)
+
+ def _convert(self, network):
+ result = {}
+ result['status'] = network.status
+ result['id'] = network.id
+ result['name'] = network.name
+ result['tenantId'] = network.project_id
+ result['segmentationId'] = network.provider_segmentation_id
+ result['networkType'] = network.provider_network_type
+ result['physicalNetwork'] = network.provider_physical_network
+ result['vlanTransparent'] = True
+ result['shared'] = network.is_shared
+ result['routerExternal'] = network.is_router_external
+ return result
+
+ def create_network(self, vimid, tenantid, body):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ body = translate(self.keys_mapping, body)
+ net = network.network_create(**body)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(net)
+ resp.update(vim_dict)
+ return resp
+
+ def list_network(self, vimid, tenantid, networkid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ net = network.network_get(networkid)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(net)
+ resp.update(vim_dict)
+ return resp
+
+ def delete_network(self, vimid, tenantid, networkid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ return network.network_delete(networkid)
+
+ def list_networks(self, vimid, tenantid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ tenant = {"project_id": tenantid}
+ resp = network.networks_get(**tenant)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ networks = {'networks': []}
+ if resp:
+ for net in resp:
+ networks['networks'].append(self._convert(net))
+ networks.update(vim_dict)
+ return networks
diff --git a/vio/vio/pub/vim/vimapi/network/OperatePort.py b/vio/vio/pub/vim/vimapi/network/OperatePort.py
new file mode 100644
index 0000000..4ed0112
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/network/OperatePort.py
@@ -0,0 +1,82 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+import logging
+
+from vio.pub.msapi.extsys import get_vim_by_id
+from vio.pub.vim.drivers.openstacksdk import neutron_v2_0
+from vio.pub.vim.vimapi.network.OperateNetwork import BaseNet, translate
+
+
+logger = logging.getLogger(__name__)
+
+
+class OperatePort(BaseNet):
+ keys_mapping = {"tenantId": "project_id",
+ "networkId": "network_id",
+ "vnicType": "binding:vnic_type",
+ "securityGroups": "security_groups",
+ "macAddress": "mac_address",
+ "subnetId": "subnet_id",
+ "ip": "ip_address"
+ }
+
+ def ___init__(self, params):
+ super(OperatePort, self).__init__(params)
+
+ def _convert(self, port):
+ result = {}
+ result['status'] = 'ok'
+ result['id'] = port.id
+ result['networkId'] = port.network_id
+ result['name'] = port.name
+ result['vnicType'] = port.binding_vnic_type
+ result['macAddress'] = port.mac_address
+ result['subnetId'] = port.subnet_id
+ result['securityGroups'] = port.security_group_ids
+ return result
+
+ def create_port(self, vimid, tenantid, body):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ body = translate(self.keys_mapping, body)
+ port = network.port_create(**body)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(port)
+ resp.update(vim_dict)
+ return resp
+
+ def list_port(self, vimid, tenantid, portid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ port = network.port_find(portid)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(port)
+ resp.update(vim_dict)
+ return resp
+
+ def delete_port(self, vimid, tenantid, portid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ return network.port_delete(portid)
+
+ def list_ports(self, vimid, tenantid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ tenant = {"project_id": tenantid}
+ resp = network.ports_get(**tenant)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ ports = {'ports': []}
+ if resp:
+ for port in resp:
+ ports['ports'].append(self._convert(port))
+ ports.update(vim_dict)
+ return ports
diff --git a/vio/vio/pub/vim/vimapi/network/OperateSubnet.py b/vio/vio/pub/vim/vimapi/network/OperateSubnet.py
new file mode 100644
index 0000000..b9b4c27
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/network/OperateSubnet.py
@@ -0,0 +1,85 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+import logging
+
+from vio.pub.msapi.extsys import get_vim_by_id
+from vio.pub.vim.drivers.openstacksdk import neutron_v2_0
+from vio.pub.vim.vimapi.network.OperateNetwork import BaseNet,translate
+
+
+logger = logging.getLogger(__name__)
+
+
+class OperateSubnet(BaseNet):
+ keys_mapping = {"tenantId": "project_id",
+ "networkId": "network_id",
+ "ipVersion": "ip_version",
+ "gaetwayIp": "gateway_ip",
+ "dnsNameservers": "dns_nameservers",
+ "hostRoutes": "host_routes",
+ "allocationPools": "allocation_pools"
+ }
+
+ def ___init__(self, params):
+ super(OperateSubnet, self).__init__(params)
+
+ def _convert(self, subnet):
+ result = {}
+ result['status'] = 'ok'
+ result['id'] = subnet.id
+ result['networkId'] = subnet.network_id
+ result['name'] = subnet.name
+ result['allocationPools'] = subnet.allocation_pools
+ result['gatewayIp'] = subnet.gateway_ip
+ result['dnsNameServers'] = subnet.dns_nameservers
+ result['ipVersion'] = subnet.ip_version
+ result['enableDhcp'] = subnet.is_dhcp_enabled
+ result['hostRoutes'] = subnet.host_routes
+ result['cidr'] = subnet.cidr
+ return result
+
+ def create_subnet(self, vimid, tenantid, body):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ body = translate(self.keys_mapping, body)
+ subnet = network.subnet_create(**body)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(subnet)
+ resp.update(vim_dict)
+ return resp
+
+ def list_subnet(self, vimid, tenantid, subnetid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ subnet = network.subnet_get(subnetid)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ resp = self._convert(subnet)
+ resp.update(vim_dict)
+ return resp
+
+ def delete_subnet(self, vimid, tenantid, subnetid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ return network.subnet_delete(subnetid)
+
+ def list_subnets(self, vimid, tenantid):
+ vim_info = self.get_vim_info(vimid)
+ network = self.auth(vim_info)
+ tenant = {"project_id": tenantid}
+ resp = network.subnets_get(**tenant)
+ vim_dict = {"vimName": vim_info['name'], "vimId": vim_info['vimId']}
+ subnets = {'subnets': []}
+ if resp:
+ for subnet in resp:
+ subnets['subnets'].append(self._convert(subnet))
+ subnets.update(vim_dict)
+ return subnets
diff --git a/vio/vio/pub/vim/vimapi/network/__init__.py b/vio/vio/pub/vim/vimapi/network/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/network/__init__.py
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateFlavors.py b/vio/vio/pub/vim/vimapi/nova/OperateFlavors.py
new file mode 100644
index 0000000..92dfbbf
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateFlavors.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2017 VMware, 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 openstack import exceptions
+
+from vio.pub.vim.vimapi.nova.OperateNova import OperateNova
+
+logger = logging.getLogger(__name__)
+
+
+class OperateFlavors(OperateNova):
+
+ def __init__(self, **kwargs):
+ super(OperateFlavors, self).__init__(**kwargs)
+
+ def create_flavor(self, data, project_id, create_req):
+ req = {
+ "name": create_req.get('name'),
+ "vcpus": create_req.get('vcpu'),
+ "ram": create_req.get('memory'),
+ "disk": create_req.get('disk'),
+ "ephemeral": create_req.get('ephemeral', 0),
+ "swap": create_req.get('swap', 0),
+ "is_public": create_req.get('isPublic', True)
+ }
+ # TODO: support extraSpecs
+ return self.request('create_flavor', data,
+ project_id=project_id, **req), None
+
+ def list_flavors(self, data, project_id):
+ flavors = self.request('list_flavors', data, project_id=project_id)
+ flavors = list(flavors)
+ result = []
+ for flavor in flavors:
+ extra_specs = self.request('get_flavor_extra_specs', data,
+ project_id=project_id, flavor_id=flavor.id)
+ result.append((flavor, extra_specs))
+ return result
+
+ def get_flavor(self, data, project_id, flavor_id):
+ try:
+ flavor = self.request('get_flavor', data,
+ project_id=project_id, flavor_id=flavor_id)
+ extra_specs = self.request('get_flavor_extra_specs', data,
+ project_id=project_id, flavor_id=flavor_id)
+ return flavor, extra_specs
+
+ except exceptions.ResourceNotFound:
+ return None, None
+
+ def delete_flavor(self, data, project_id, flavor_id):
+ return self.request('delete_flavor', data, project_id=project_id,
+ flavor_id=flavor_id)
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateHypervisor.py b/vio/vio/pub/vim/vimapi/nova/OperateHypervisor.py
new file mode 100644
index 0000000..8b3de91
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateHypervisor.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2017 VMware, 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 openstack import exceptions
+
+from vio.pub.vim.vimapi.nova.OperateNova import OperateNova
+
+logger = logging.getLogger(__name__)
+
+
+class OperateHypervisor(OperateNova):
+
+ def get_hypervisor(self, data, hypervisor, **kwargs):
+ try:
+ return self.request('get_hypervisor', data,
+ project_name=data['project_name'],
+ hypervisor=hypervisor,
+ **kwargs)
+ except exceptions.ResourceNotFound:
+ return None
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateLimits.py b/vio/vio/pub/vim/vimapi/nova/OperateLimits.py
new file mode 100644
index 0000000..34e0584
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateLimits.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2017 VMware, 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 vio.pub.vim.vimapi.nova.OperateNova import OperateNova
+
+logger = logging.getLogger(__name__)
+
+
+class OperateLimits(OperateNova):
+
+ def get_limits(self, data, project_id, **kwargs):
+ return self.request('get_limits', data, **kwargs)
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateNova.py b/vio/vio/pub/vim/vimapi/nova/OperateNova.py
new file mode 100644
index 0000000..49461a2
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateNova.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2017 VMware, 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 vio.pub.vim.vimapi.baseclient import baseclient
+
+
+logger = logging.getLogger(__name__)
+
+
+class OperateNova(baseclient):
+
+ def __init__(self, **kwargs):
+ super(OperateNova, self).__init__(**kwargs)
+
+ def request(self, op, data, **kwargs):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url']}
+ project_id = kwargs.get('project_id')
+ if project_id:
+ param['project_id'] = project_id
+ else:
+ param['project_name'] = kwargs.get('project_name')
+ compute = self.compute(param)
+ func = getattr(compute, op)
+ return func(**kwargs)
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateServers.py b/vio/vio/pub/vim/vimapi/nova/OperateServers.py
new file mode 100644
index 0000000..eb44eb8
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateServers.py
@@ -0,0 +1,109 @@
+# Copyright (c) 2017 VMware, 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 base64
+import logging
+
+from openstack import exceptions
+
+from vio.pub.vim.vimapi.nova.OperateNova import OperateNova
+
+logger = logging.getLogger(__name__)
+
+
+class OperateServers(OperateNova):
+
+ def create_server(self, data, project_id, create_req):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url'],
+ 'project_id': project_id}
+ cc = self.compute(param)
+ req = {
+ "name": create_req.get('name'),
+ "flavorRef": cc.find_flavor(create_req.get('flavorId')).id
+ }
+ boot = create_req.get('boot')
+ boot_type = boot.get('type')
+ if boot_type == 1:
+ # boot from vol
+ req['block_device_mapping_v2'] = {
+ 'uuid': boot["volumeId"],
+ 'source_type': 'volume',
+ 'destination_type': 'volume',
+ 'delete_on_termination': False
+ }
+ elif boot_type == 2:
+ req['imageRef'] = cc.find_image(boot.get('imageId')).id
+ networks = create_req.get('nicArray', [])
+ if networks:
+ req['networks'] = [{'port': n['portId']} for n in networks]
+ az = create_req.get('availabilityZone', None)
+ if az:
+ req['availability_zone'] = az
+ md = create_req.get('metadata', [])
+ if md:
+ req['metadata'] = [{n['keyName']: n['Value']} for n in md]
+ userdata = create_req.get('userdata', None)
+ if userdata:
+ req['user_data'] = base64.encodestring(userdata)
+ sg = create_req.get('securityGroups', [])
+ if sg:
+ req['security_groups'] = sg
+ # todo attach volumes after server created
+ volumes = create_req.get('volumeArray', [])
+ return cc.create_server(**req)
+
+ def list_servers(self, data, project_id):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url'],
+ 'project_id': project_id}
+ projects = self.compute(param).list_servers()
+ return projects
+
+ def list_server_interfaces(self, data, project_id, server):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url'],
+ 'project_id': project_id}
+ interfaces = self.compute(param).list_server_interfaces(server)
+ return list(interfaces)
+
+ def get_server(self, data, project_id, server_id):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url'],
+ 'project_id': project_id}
+ try:
+ project = self.compute(param).get_server(server_id=server_id)
+ return project
+ except exceptions.ResourceNotFound:
+ return None
+
+ def delete_server(self, data, project_id, server_id):
+ param = {'username': data['username'],
+ 'user_domain_name': 'default',
+ 'project_domain_name': 'default',
+ 'password': data['password'],
+ 'auth_url': data['url'],
+ 'project_id': project_id}
+ project = self.compute(param).delete_server(server_id)
+ return project
diff --git a/vio/vio/pub/vim/vimapi/nova/OperateService.py b/vio/vio/pub/vim/vimapi/nova/OperateService.py
new file mode 100644
index 0000000..d29779a
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/OperateService.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2017 VMware, 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 openstack import exceptions
+
+from vio.pub.vim.vimapi.nova.OperateNova import OperateNova
+
+logger = logging.getLogger(__name__)
+
+
+class OperateService(OperateNova):
+
+ def list_services(self, data, project_id, **kwargs):
+ return self.request('list_services', data, **kwargs)
diff --git a/vio/vio/pub/vim/vimapi/nova/__init__.py b/vio/vio/pub/vim/vimapi/nova/__init__.py
new file mode 100644
index 0000000..8770c43
--- /dev/null
+++ b/vio/vio/pub/vim/vimapi/nova/__init__.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/image_utils.py b/vio/vio/swagger/image_utils.py
new file mode 100644
index 0000000..6380688
--- /dev/null
+++ b/vio/vio/swagger/image_utils.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2017 VMware, 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 image_formatter(image):
+
+ return {
+ 'id' : image.id,
+ 'name' : image.name,
+ 'imageType' : image.disk_format,
+ 'status' : image.status,
+ 'size' : image.size,
+ 'containerFormat' : image.container_format,
+ 'visibility' : image.visibility
+ }
+
+
+def vim_formatter(vim_info, tenantid):
+
+ rsp = {}
+ rsp['vimId'] = vim_info.get('vimId')
+ rsp['vimName'] = vim_info.get('name')
+ rsp['tenantId'] = tenantid
+ return rsp
+
+
+def sdk_param_formatter(data):
+
+ param = {}
+ param['username'] = data.get('userName')
+ param['password'] = data.get('password')
+ param['auth_url'] = data.get('url')
+ param['project_name'] = data.get('tenant')
+ param['user_domain_name'] = 'default'
+ param['project_domain_name'] = 'default'
+ return param
+
+def req_body_formatter(body):
+
+ param = {}
+ param['name'] = body.get('name')
+ param['disk_format'] = body.get('imageType')
+ param['container_format'] = body.get('containerFormat')
+ param['visibility'] = body.get('visibility')
+ param['imagePath'] = body.get('imagePath')
+ return param \ No newline at end of file
diff --git a/vio/vio/swagger/nova_utils.py b/vio/vio/swagger/nova_utils.py
new file mode 100644
index 0000000..6084317
--- /dev/null
+++ b/vio/vio/swagger/nova_utils.py
@@ -0,0 +1,109 @@
+# Copyright (c) 2017 VMware, 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 six
+
+
+def server_formatter(server, interfaces=[]):
+ r = {
+ "id": server.id,
+ "name": server.name,
+ "tenantId": server.project_id,
+ "availabilityZone": server.availability_zone,
+ "flavorId": server.flavor_id or server.flavor['id'],
+ "volumeArray": [],
+ "metadata": [],
+ "securityGroups": [],
+ # TODO finish following attributes
+ "serverGroup": "",
+ "contextArray": [],
+ "userdata": server.user_data,
+ "nicArray": [],
+ }
+ if interfaces:
+ r['nicArray'] = [{'portId': i.port_id} for i in interfaces]
+ elif server.networks:
+ r['nicArray'] = [{'portId': n['port']} for n in server.networks]
+ if server.attached_volumes:
+ r["volumeArray"] = [{'volumeId': v['id']} for v in server.attached_volumes]
+ if server.image_id or server.image:
+ r['boot'] = {
+ 'type': 2,
+ 'imageId': server.image_id or server.image['id']
+ }
+ else:
+ r['boot'] = {
+ 'type': 1,
+ 'volumeId': r['volumeArray'][0]['volumeId']
+ }
+ if server.metadata:
+ r["metadata"] = [{'keyName': k, 'value': v}
+ for k, v in six.iteritems(server.metadata)]
+ if server.security_groups:
+ r["securityGroups"] = [i['name'] for i in server.security_groups]
+ return r
+
+
+def flavor_formatter(flavor, extra_specs):
+ return {
+ "id": flavor.id,
+ "name": flavor.name,
+ "vcpu": flavor.vcpus,
+ "memory": flavor.ram,
+ "disk": flavor.disk,
+ "ephemeral": flavor.ephemeral,
+ "swap": flavor.swap,
+ "isPublic": flavor.is_public,
+ "extraSpecs": extra_specs_formatter(extra_specs)
+ }
+
+
+def extra_specs_formatter(extra_specs):
+ return {
+ }
+
+
+def server_limits_formatter(limits):
+ return {
+ # nova
+ 'maxPersonality': limits.absolute.personality,
+ 'maxPersonalitySize': limits.absolute.personality_size,
+ 'maxServerGroupMembers': limits.absolute.server_group_members,
+ 'maxServerGroups': limits.absolute.server_groups,
+ 'maxImageMeta': limits.absolute.image_meta,
+ 'maxTotalCores': limits.absolute.total_cores,
+ 'maxTotalInstances': limits.absolute.instances,
+ 'maxTotalKeypairs': limits.absolute.keypairs,
+ 'maxTotalRAMSize': limits.absolute.total_ram,
+ 'security_group_rules': limits.absolute.security_group_rules,
+ 'security_group': limits.absolute.security_groups,
+
+ # cinder
+ # neutron
+ }
+
+
+def service_formatter(service):
+ return {
+ 'service': service.binary,
+ 'name': service.host,
+ 'zone': service.zone,
+ }
+
+
+def hypervisor_formatter(hypervisor):
+ return {
+ 'name': hypervisor.name,
+ 'cpu': hypervisor.vcpus,
+ 'disk_gb': hypervisor.local_disk_size,
+ 'memory_mb': hypervisor.memory_size,
+ }
diff --git a/vio/vio/swagger/urls.py b/vio/vio/swagger/urls.py
index 824aea1..c058df0 100644
--- a/vio/vio/swagger/urls.py
+++ b/vio/vio/swagger/urls.py
@@ -13,10 +13,72 @@
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
-from vio.swagger.views import SwaggerJsonView
+from vio.swagger.views.hypervisor.views import HostView
+from vio.swagger.views.limits.views import LimitsView
+from vio.swagger.views.service.views import HostsView
+from vio.swagger.views.swagger_json import SwaggerJsonView
+from vio.swagger.views.tenant.views import ListTenantsView
+from vio.swagger.views.image.views import CreateListImagesView
+from vio.swagger.views.image.views import GetDeleteImageView
+from vio.swagger.views.volume.views import CreateListVolumeView
+from vio.swagger.views.volume.views import GetDeleteVolumeView
+from vio.swagger.views.server.views import ListServersView, GetServerView
+from vio.swagger.views.flavor.views import FlavorsView, FlavorView
+from vio.swagger.views.network.views import CreateNetworkView, DeleteNetworkView
+from vio.swagger.views.subnet.views import CreateSubnetView, DeleteSubnetView
+from vio.swagger.views.port.views import CreatePortView, DeletePortView
urlpatterns = [
url(r'^openoapi/multivim-vio/v1/swagger.json$', SwaggerJsonView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'tenants$', ListTenantsView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z_-]+)/images$',
+ CreateListImagesView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z_-]+)/images/(?P<imageid>[0-9a-zA-Z_-]+)$',
+ GetDeleteImageView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z_-]+)/volumes$',
+ CreateListVolumeView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z_-]+)/volumes/(?P<volumeid>[0-9a-zA-Z_-]+)$',
+ GetDeleteVolumeView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/servers$', ListServersView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/servers/(?P<serverid>[0-9a-zA-Z_-]+)$',
+ GetServerView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/flavors$',
+ FlavorsView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/flavors/(?P<flavorid>[0-9a-zA-Z_-]+)$',
+ FlavorView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/limits$',
+ LimitsView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/hosts$',
+ HostsView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z_-]+)/'
+ r'(?P<tenantid>[0-9a-zA-Z]+)/hosts/(?P<hostname>[0-9a-zA-Z_-]+)$',
+ HostView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/networks$',
+ CreateNetworkView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/networks/'
+ r'(?P<networkid>[0-9a-zA-Z\-\_]+)$',
+ DeleteNetworkView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/subnets$',
+ CreateSubnetView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/subnets/'
+ r'(?P<subnetid>[0-9a-zA-Z\-\_]+)$',
+ DeleteSubnetView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/ports$',
+ CreatePortView.as_view()),
+ url(r'^openoapi/multivim-vio/v1/(?P<vimid>[0-9a-zA-Z\-\_]+)/(?P<tenantid>[0-9a-zA-Z\-\_]+)/ports/'
+ r'(?P<portid>[0-9a-zA-Z\-\_]+)$',
+ DeletePortView.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/vio/vio/swagger/views/__init__.py b/vio/vio/swagger/views/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/flavor/__init__.py b/vio/vio/swagger/views/flavor/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/flavor/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/flavor/views.py b/vio/vio/swagger/views/flavor/views.py
new file mode 100644
index 0000000..ec22c65
--- /dev/null
+++ b/vio/vio/swagger/views/flavor/views.py
@@ -0,0 +1,99 @@
+# Copyright (c) 2017 VMware, 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
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.nova import OperateFlavors
+from vio.swagger import nova_utils
+
+
+class FlavorsView(APIView):
+
+ def post(self, request, vimid, tenantid):
+ create_req = json.loads(request.body)
+
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ flavors_op = OperateFlavors.OperateFlavors()
+ flavor, extra_specs = flavors_op.create_flavor(data, tenantid, create_req)
+ flavor_dict = nova_utils.flavor_formatter(flavor, extra_specs)
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid,
+ 'returnCode': 1}
+ rsp.update(flavor_dict)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ flavors_op = OperateFlavors.OperateFlavors()
+ flavors_result = flavors_op.list_flavors(data, tenantid)
+ flavors_dict = [nova_utils.flavor_formatter(flavor, extra)
+ for flavor, extra in flavors_result]
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'flavors': flavors_dict}
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+
+class FlavorView(APIView):
+
+ def get(self, request, vimid, tenantid, flavorid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ flavors_op = OperateFlavors.OperateFlavors()
+ flavor, extra_specs = flavors_op.get_flavor(data, tenantid, flavorid)
+ flavor_dict = nova_utils.flavor_formatter(flavor, extra_specs)
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid}
+ rsp.update(flavor_dict)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ def delete(self, request, vimid, tenantid, flavorid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+ flavors_op = OperateFlavors.OperateFlavors()
+ flavors_op.delete_flavor(data, tenantid, flavorid)
+ return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/vio/vio/swagger/views/hypervisor/__init__.py b/vio/vio/swagger/views/hypervisor/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/hypervisor/__init__.py
diff --git a/vio/vio/swagger/views/hypervisor/views.py b/vio/vio/swagger/views/hypervisor/views.py
new file mode 100644
index 0000000..9019047
--- /dev/null
+++ b/vio/vio/swagger/views/hypervisor/views.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.nova import OperateHypervisor
+from vio.pub.vim.vimapi.nova import OperateServers
+from vio.pub.vim.vimapi.nova import OperateService
+
+from vio.swagger import nova_utils
+
+
+class HostView(APIView):
+
+ def get(self, request, vimid, tenantid, hostname):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ hypervisor_op = OperateHypervisor.OperateHypervisor()
+ hv = hypervisor_op.get_hypervisor(data, hypervisor=hostname)
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid,
+ 'host': nova_utils.hypervisor_formatter(hv)}
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
diff --git a/vio/vio/swagger/views/image/__init__.py b/vio/vio/swagger/views/image/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/image/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/image/views.py b/vio/vio/swagger/views/image/views.py
new file mode 100644
index 0000000..7d909f3
--- /dev/null
+++ b/vio/vio/swagger/views/image/views.py
@@ -0,0 +1,95 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.glance import OperateImage
+from vio.swagger import image_utils
+
+
+class GetDeleteImageView(APIView):
+
+ def get(self, request, vimid, tenantid, imageid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ image_op = OperateImage.OperateImage(vim_info)
+
+ try:
+ image = image_op.get_vim_image(imageid)
+ vim_rsp = image_utils.vim_formatter(vim_info, tenantid)
+ rsp = image_utils.image_formatter(image)
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid, tenantid, imageid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ image_op = OperateImage.OperateImage(vim_info)
+
+ try:
+ image_op.delete_vim_image(imageid)
+ return Response(status=status.HTTP_204_NO_CONTENT)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+class CreateListImagesView(APIView):
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ query_data = dict(request.query_params)
+ image_instance = OperateImage.OperateImage(vim_info)
+
+ try:
+ images = image_instance.get_vim_images(**query_data)
+ rsp = {}
+ rsp['images'] = []
+ vim_rsp = image_utils.vim_formatter(vim_info, tenantid)
+ for image in images:
+ rsp['images'].append(image_utils.image_formatter(image))
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def post(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ req_body = json.loads(request.body)
+ vim_rsp = image_utils.vim_formatter(vim_info, tenantid)
+ image_instance = OperateImage.OperateImage(vim_info)
+
+ try:
+ images = image_instance.get_vim_images()
+ for image in images:
+ if image.name == req_body.get('name'):
+ image_info = image_instance.get_vim_image(image.id)
+ rsp = image_utils.image_formatter(image_info)
+ rsp['returnCode'] = '0'
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ param = image_utils.req_body_formatter(req_body)
+ image = image_instance.create_vim_image(vimid, tenantid, **param)
+
+ rsp = image_utils.image_formatter(image)
+ rsp.update(vim_rsp)
+ rsp['returnCode'] = '1'
+ return Response(data=rsp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file
diff --git a/vio/vio/swagger/views/limits/__init__.py b/vio/vio/swagger/views/limits/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/limits/__init__.py
diff --git a/vio/vio/swagger/views/limits/views.py b/vio/vio/swagger/views/limits/views.py
new file mode 100644
index 0000000..5122223
--- /dev/null
+++ b/vio/vio/swagger/views/limits/views.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.nova import OperateLimits
+from vio.swagger import nova_utils
+
+
+class LimitsView(APIView):
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ servers_op = OperateLimits.OperateLimits()
+ server_limits = servers_op.get_limits(data, tenantid)
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid}
+ rsp.update(nova_utils.server_limits_formatter(server_limits))
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
diff --git a/vio/vio/swagger/views/multivim.flavor.swagger.json b/vio/vio/swagger/views/multivim.flavor.swagger.json
new file mode 100644
index 0000000..ddc7045
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.flavor.swagger.json
@@ -0,0 +1,392 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "flavor name to filter list",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Requests a page size of items",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "marker",
+ "in": "query",
+ "description": "image ID of the last-seen item",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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/vio/vio/swagger/views/multivim.host.swagger.json b/vio/vio/swagger/views/multivim.host.swagger.json
new file mode 100644
index 0000000..ec797c0
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.host.swagger.json
@@ -0,0 +1,233 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ }
+ ],
+ "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/VimHostDetail"
+ }
+ },
+ "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"
+ }
+ }
+ },
+ "VimHostDetail": {
+ "type": "object",
+ "required": [
+ "vimId",
+ "tenantId",
+ "host"
+ ],
+ "properties": {
+ "host": {
+ "type": "array",
+ "description": "list of host information",
+ "items": {
+ "$ref": "#/definitions/VimHostResource"
+ }
+ },
+ "vimId": {
+ "type": "string"
+ },
+ "vimName": {
+ "type": "string"
+ },
+ "tenantId": {
+ "type": "string",
+ "description": "tenant UUID"
+ }
+ }
+ },
+ "VimHostResource": {
+ "type": "object",
+ "required": [
+ "name",
+ "cpu",
+ "memory_mb",
+ "disk_gb",
+ "project"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "host name"
+ },
+ "cpu": {
+ "type": "integer",
+ "description": "The cpu info on the host"
+ },
+ "memory_mb": {
+ "type": "integer",
+ "description": "The memory info on the host (in MB)"
+ },
+ "disk_gb": {
+ "type": "integer",
+ "description": "The disk info on the host (in GB)"
+ },
+ "project": {
+ "type": "string",
+ "description": "The project id (or special name like total, used_now, used_max)."
+ }
+ }
+ }
+ }
+}
diff --git a/vio/vio/swagger/views/multivim.image.swagger.json b/vio/vio/swagger/views/multivim.image.swagger.json
new file mode 100644
index 0000000..4604445
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.image.swagger.json
@@ -0,0 +1,359 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "images name to filter list",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Requests a page size of items",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "marker",
+ "in": "query",
+ "description": "image ID of the last-seen item",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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/vio/vio/swagger/views/multivim.limit.swagger.json b/vio/vio/swagger/views/multivim.limit.swagger.json
new file mode 100644
index 0000000..08008cf
--- /dev/null
+++ b/vio/vio/swagger/views/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 VIO services"
+ }
+ ],
+ "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/vio/vio/swagger/views/multivim.network.swagger.json b/vio/vio/swagger/views/multivim.network.swagger.json
new file mode 100644
index 0000000..6a76164
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.network.swagger.json
@@ -0,0 +1,349 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "network name to filter list",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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/vio/vio/swagger/views/multivim.server.swagger.json b/vio/vio/swagger/views/multivim.server.swagger.json
new file mode 100644
index 0000000..d598b48
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.server.swagger.json
@@ -0,0 +1,488 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "server name to filter list",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Requests a page size of items",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "marker",
+ "in": "query",
+ "description": "image ID of the last-seen item",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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/vio/vio/swagger/views/multivim.subnet.swagger.json b/vio/vio/swagger/views/multivim.subnet.swagger.json
new file mode 100644
index 0000000..4c18b13
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.subnet.swagger.json
@@ -0,0 +1,417 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "subnet name to filter list",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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/vio/vio/swagger/views/multivim.tenant.swagger.json b/vio/vio/swagger/views/multivim.tenant.swagger.json
new file mode 100644
index 0000000..75c2c40
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.tenant.swagger.json
@@ -0,0 +1,102 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "tenant name to filter tenant list",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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": {
+ "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"
+ }
+ }
+ }
+ }
+}
diff --git a/vio/vio/swagger/views/multivim.volume.swagger.json b/vio/vio/swagger/views/multivim.volume.swagger.json
new file mode 100644
index 0000000..6609c90
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.volume.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 VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "volumn name to filter list",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Requests a page size of items",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "marker",
+ "in": "query",
+ "description": "image ID of the last-seen item",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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"
+ }
+ }
+ },
+ "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"
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "volume status"
+ },
+ "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"
+ },
+ "device": {
+ "type": "string",
+ "description": "device to be attached"
+ },
+ "hostName": {
+ "type": "string",
+ "description": "host name"
+ }
+ }
+ }
+ }
+}
diff --git a/vio/vio/swagger/views/multivim.vport.swagger.json b/vio/vio/swagger/views/multivim.vport.swagger.json
new file mode 100644
index 0000000..c621150
--- /dev/null
+++ b/vio/vio/swagger/views/multivim.vport.swagger.json
@@ -0,0 +1,363 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0",
+ "title": "MultiVIM Service rest API"
+ },
+ "basePath": "/openoapi/multivim/v1/",
+ "tags": [
+ {
+ "name": "MultiVIM VIO services"
+ }
+ ],
+ "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"
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "virtual port name to filter list",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "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",
+ "name"
+ ],
+ "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"
+ }
+ }
+ }
+ },
+ "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"
+ ],
+ "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/vio/vio/swagger/views/network/__init__.py b/vio/vio/swagger/views/network/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/network/__init__.py
diff --git a/vio/vio/swagger/views/network/views.py b/vio/vio/swagger/views/network/views.py
new file mode 100644
index 0000000..cb7adfe
--- /dev/null
+++ b/vio/vio/swagger/views/network/views.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2017 VMware, 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
+import json
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.utils import syscomm
+from vio.pub.vim.vimapi.network import OperateNetwork
+
+logger = logging.getLogger(__name__)
+
+
+class CreateNetworkView(APIView):
+ def post(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ net = OperateNetwork.OperateNetwork()
+ body = json.loads(request.body)
+ try:
+ resp = net.create_network(vimid, tenantid, body)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def get(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ net = OperateNetwork.OperateNetwork()
+ try:
+ resp = net.list_networks(vimid, tenantid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class DeleteNetworkView(APIView):
+
+ def get(self, request, vimid, tenantid, networkid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ net = OperateNetwork.OperateNetwork()
+ try:
+ resp = net.list_network(vimid, tenantid, networkid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid, tenantid, networkid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ net = OperateNetwork.OperateNetwork()
+ try:
+ resp = net.delete_network(vimid, tenantid, networkid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+
diff --git a/vio/vio/swagger/views/port/__init__.py b/vio/vio/swagger/views/port/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/port/__init__.py
diff --git a/vio/vio/swagger/views/port/views.py b/vio/vio/swagger/views/port/views.py
new file mode 100644
index 0000000..9a4af3f
--- /dev/null
+++ b/vio/vio/swagger/views/port/views.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2017 VMware, 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
+import json
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.utils import syscomm
+from vio.pub.vim.vimapi.network import OperatePort
+
+logger = logging.getLogger(__name__)
+
+
+class CreatePortView(APIView):
+ def post(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ port = OperatePort.OperatePort()
+ body = json.loads(request.body)
+ try:
+ resp = port.create_port(vimid, tenantid, body)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def get(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ port = OperatePort.OperatePort()
+ try:
+ resp = port.list_ports(vimid, tenantid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class DeletePortView(APIView):
+
+ def get(self, request, vimid, tenantid, portid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ port = OperatePort.OperatePort()
+ try:
+ resp = port.list_port(vimid, tenantid, portid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid, tenantid, portid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ port = OperatePort.OperatePort()
+ try:
+ resp = port.delete_port(vimid, tenantid, portid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+
diff --git a/vio/vio/swagger/views/server/__init__.py b/vio/vio/swagger/views/server/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/server/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/server/views.py b/vio/vio/swagger/views/server/views.py
new file mode 100644
index 0000000..3348754
--- /dev/null
+++ b/vio/vio/swagger/views/server/views.py
@@ -0,0 +1,111 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.nova import OperateServers
+from vio.swagger import nova_utils
+
+logger = logging.getLogger(__name__)
+
+
+class ListServersView(APIView):
+
+ def post(self, request, vimid, tenantid):
+ create_req = json.loads(request.body)
+
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ servers_op = OperateServers.OperateServers()
+ try:
+ server = servers_op.create_server(data, tenantid, create_req)
+ except Exception as ex:
+ return Response(data=str(ex),
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ server_dict = nova_utils.server_formatter(server)
+
+ rsp = {'vimId': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid}
+ rsp.update(server_dict)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ servers_op = OperateServers.OperateServers()
+ servers = servers_op.list_servers(data, tenantid)
+
+ servers_resp = []
+ for server in servers:
+ intfs = servers_op.list_server_interfaces(data, tenantid, server)
+ servers_resp.append(nova_utils.server_formatter(
+ server, interfaces=intfs))
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'servers': servers_resp}
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+
+class GetServerView(APIView):
+
+ def get(self, request, vimid, tenantid, serverid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ servers_op = OperateServers.OperateServers()
+ server = servers_op.get_server(data, tenantid, serverid)
+ intfs = servers_op.list_server_interfaces(data, tenantid, server)
+ server_dict = nova_utils.server_formatter(server, interfaces=intfs)
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid}
+ rsp.update(server_dict)
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ def delete(self, request, vimid, tenantid, serverid):
+ servers_op = OperateServers.OperateServers()
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+ servers_op.delete_server(data, tenantid, serverid)
+ return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/vio/vio/swagger/views/service/__init__.py b/vio/vio/swagger/views/service/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/service/__init__.py
diff --git a/vio/vio/swagger/views/service/views.py b/vio/vio/swagger/views/service/views.py
new file mode 100644
index 0000000..535f2d2
--- /dev/null
+++ b/vio/vio/swagger/views/service/views.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.nova import OperateServers
+from vio.pub.vim.vimapi.nova import OperateService
+
+from vio.swagger import nova_utils
+
+
+class HostsView(APIView):
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ data = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'username': vim_info['userName'],
+ 'password': vim_info['password'],
+ 'url': vim_info['url'],
+ 'project_name': vim_info['tenant']}
+
+ services_op = OperateService.OperateService()
+
+ rsp = {'vimid': vim_info['vimId'],
+ 'vimName': vim_info['name'],
+ 'tenantId': tenantid,
+ 'hosts': [nova_utils.service_formatter(svc)
+ for svc in services_op.list_services(data, tenantid)]}
+
+ return Response(data=rsp, status=status.HTTP_200_OK)
diff --git a/vio/vio/swagger/views/subnet/__init__.py b/vio/vio/swagger/views/subnet/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vio/vio/swagger/views/subnet/__init__.py
diff --git a/vio/vio/swagger/views/subnet/views.py b/vio/vio/swagger/views/subnet/views.py
new file mode 100644
index 0000000..f95da54
--- /dev/null
+++ b/vio/vio/swagger/views/subnet/views.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2017 VMware, 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
+import json
+
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.utils import syscomm
+from vio.pub.vim.vimapi.network import OperateSubnet
+
+logger = logging.getLogger(__name__)
+
+
+class CreateSubnetView(APIView):
+ def post(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ subnet = OperateSubnet.OperateSubnet()
+ body = json.loads(request.body)
+ try:
+ resp = subnet.create_subnet(vimid, tenantid, body)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def get(self, request, vimid, tenantid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ subnet = OperateSubnet.OperateSubnet()
+ try:
+ resp = subnet.list_subnets(vimid, tenantid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class DeleteSubnetView(APIView):
+
+ def get(self, request, vimid, tenantid, subnetid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ subnet = OperateSubnet.OperateSubnet()
+ try:
+ resp = subnet.list_subnet(vimid, tenantid, subnetid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid, tenantid, subnetid):
+ logger.info("Enter %s, method is %s, vim_id is %s",
+ syscomm.fun_name(), request.method, vimid)
+ subnet = OperateSubnet.OperateSubnet()
+ try:
+ resp = subnet.delete_subnet(vimid, tenantid, subnetid)
+ return Response(data=resp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+
diff --git a/vio/vio/swagger/views/swagger_json.py b/vio/vio/swagger/views/swagger_json.py
new file mode 100644
index 0000000..cf401b5
--- /dev/null
+++ b/vio/vio/swagger/views/swagger_json.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2017 VMware, 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
+
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+
+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-vio/v1/"
+ json_data["info"]["title"] = "MultiVIM driver of OpenStack VIO Service NBI"
+ return Response(json_data)
diff --git a/vio/vio/swagger/views/tenant/__init__.py b/vio/vio/swagger/views/tenant/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/tenant/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/tenant/views.py b/vio/vio/swagger/views/tenant/views.py
new file mode 100644
index 0000000..13bce23
--- /dev/null
+++ b/vio/vio/swagger/views/tenant/views.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2017 VMware, 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 import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.keystone import OperateTenant
+
+logger = logging.getLogger(__name__)
+
+
+class ListTenantsView(APIView):
+ def get(self, request, vimid):
+ vim_info = extsys.get_vim_by_id(vimid)
+
+ data = {}
+ data['vimid'] = vim_info['vimId']
+ data['vimName'] = vim_info['name']
+ data['username'] = vim_info['userName']
+ data['password'] = vim_info['password']
+ data['url'] = vim_info['url']
+ data['project_name'] = vim_info['tenant']
+
+ tenant_instance = OperateTenant.OperateTenant()
+ projects = tenant_instance.get_projects(data)
+
+ rsp = {}
+ rsp['vimid'] = vim_info['vimId']
+ rsp['vimName'] = vim_info['name']
+ rsp['tenants'] = []
+
+ for project in projects:
+ tenant = {}
+ tenant['id'] = project.id
+ tenant['name'] = project.name
+ rsp['tenants'].append(tenant)
+ return Response(data=rsp, status=status.HTTP_200_OK)
diff --git a/vio/vio/swagger/views/volume/__init__.py b/vio/vio/swagger/views/volume/__init__.py
new file mode 100644
index 0000000..a8fe66a
--- /dev/null
+++ b/vio/vio/swagger/views/volume/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017 VMware, 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/vio/vio/swagger/views/volume/views.py b/vio/vio/swagger/views/volume/views.py
new file mode 100644
index 0000000..91f79f0
--- /dev/null
+++ b/vio/vio/swagger/views/volume/views.py
@@ -0,0 +1,106 @@
+# Copyright (c) 2017 VMware, 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 rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from vio.pub.msapi import extsys
+from vio.pub.vim.vimapi.cinder import OperateVolume
+
+from vio.swagger import volume_utils
+
+logger = logging.getLogger(__name__)
+
+
+class GetDeleteVolumeView(APIView):
+
+ def get(self, request, vimid, tenantid, volumeid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ volume_op = OperateVolume.OperateVolume(vim_info)
+
+ try:
+ volume = volume_op.get_vim_volume(volumeid)
+ vim_rsp = volume_utils.vim_formatter(vim_info, tenantid)
+ rsp = volume_utils.volume_formatter(volume)
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def delete(self, request, vimid, tenantid, volumeid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ volume_op = OperateVolume.OperateVolume(vim_info)
+
+ try:
+ volume_op.delete_vim_volume(volumeid)
+ return Response(status=status.HTTP_204_NO_CONTENT)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class CreateListVolumeView(APIView):
+
+ def get(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ query_data = dict(request.query_params)
+ volume_op = OperateVolume.OperateVolume(vim_info)
+
+ try:
+ volumes = volume_op.get_vim_volumes(**query_data)
+ rsp = {}
+ rsp['volumes'] = []
+
+ vim_rsp = volume_utils.vim_formatter(vim_info, tenantid)
+ for volume in volumes:
+ volume_info = volume_op.get_vim_volume(volume.id)
+ rsp['volumes'].append(volume_utils.volume_formatter(volume_info))
+
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+ def post(self, request, vimid, tenantid):
+ vim_info = extsys.get_vim_by_id(vimid)
+ volume_op = OperateVolume.OperateVolume(vim_info)
+
+ try:
+ volumes_detail = volume_op.get_vim_volumes()
+ json_body = json.loads(request.body)
+
+ vim_rsp = volume_utils.vim_formatter(vim_info, tenantid)
+ for volume in volumes_detail:
+ if volume.name == json_body.get('name'):
+ volume_info = volume_op.get_vim_volume(volume.id)
+ rsp = volume_utils.volume_formatter(volume_info)
+ rsp['returnCode'] = 0
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_200_OK)
+
+ param = volume_utils.req_body_formatter(json_body)
+ volume_info = volume_op.create_vim_volume(**param)
+ rsp = volume_utils.volume_formatter(volume_info)
+ rsp['returnCode'] = 1
+ rsp.update(vim_rsp)
+ return Response(data=rsp, status=status.HTTP_202_ACCEPTED)
+ except Exception as e:
+ return Response(data={'error': str(e)},
+ status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file
diff --git a/vio/vio/swagger/volume_utils.py b/vio/vio/swagger/volume_utils.py
new file mode 100644
index 0000000..562a381
--- /dev/null
+++ b/vio/vio/swagger/volume_utils.py
@@ -0,0 +1,68 @@
+# Copyright (c) 2017 VMware, 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 volume_formatter(volume):
+
+ attachments = []
+ for attach in volume.attachments:
+ vim_attach = {
+ 'device' : attach['device'],
+ 'volumeId' : attach['volume_id'],
+ 'hostName' : attach['host_name'],
+ 'Id' : attach['attachment_id'],
+ 'serverId' : attach['server_id']
+ }
+ attachments.append(vim_attach)
+
+ return {
+ 'id' : volume.id,
+ 'name' : volume.name,
+ 'createTime' : volume.created_at,
+ 'status' : volume.status,
+ 'type' : volume.volume_type,
+ 'size' : volume.size,
+ 'availabilityZone' : volume.availability_zone,
+ 'attachments' : attachments
+ }
+
+
+def vim_formatter(vim_info, tenantid):
+
+ rsp = {}
+ rsp['vimId'] = vim_info.get('vimId')
+ rsp['vimName'] = vim_info.get('name')
+ rsp['tenantId'] = tenantid
+ return rsp
+
+
+def sdk_param_formatter(data):
+
+ param = {}
+ param['username'] = data.get('userName')
+ param['password'] = data.get('password')
+ param['auth_url'] = data.get('url')
+ param['project_name'] = data.get('tenant')
+ param['user_domain_name'] = 'default'
+ param['project_domain_name'] = 'default'
+ return param
+
+
+def req_body_formatter(body):
+
+ param = {}
+ param['size'] = body.get('volumeSize')
+ param['volume_type'] = body.get('volumeType')
+ param['name'] = body.get('name')
+ param['availability_zone'] = body.get('availabilityZone')
+ param['image_id'] = body.get('imageName')
+ return param