summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vio/docker/Dockerfile2
-rwxr-xr-xvio/run.sh4
-rw-r--r--vio/vio/api_v2/api_definition/ports.yaml83
-rw-r--r--vio/vio/api_v2/api_definition/subnets.yaml88
-rw-r--r--vio/vio/api_v2/api_router/controller_builder.py77
-rw-r--r--vio/vio/api_v2/service.py4
-rwxr-xr-xvio/vio/event_listener/.gitignore1
-rwxr-xr-xvio/vio/event_listener/__init__.py13
-rwxr-xr-xvio/vio/event_listener/i18n.py27
-rwxr-xr-xvio/vio/event_listener/listener.conf3
-rwxr-xr-xvio/vio/event_listener/server.py113
-rw-r--r--vio/vio/pub/config/config.py7
-rw-r--r--vio/vio/scripts/api.py4
13 files changed, 391 insertions, 35 deletions
diff --git a/vio/docker/Dockerfile b/vio/docker/Dockerfile
index 3879b1c..9c67741 100644
--- a/vio/docker/Dockerfile
+++ b/vio/docker/Dockerfile
@@ -7,6 +7,8 @@ ENV AAI_PORT "8443"
ENV AAI_SCHEMA_VERSION "v11"
ENV AAI_USERNAME "AAI"
ENV AAI_PASSWORD "AAI"
+ENV MR_ADDR “127.0.0.1”
+ENV MR_PORT “3904”
EXPOSE 9004
diff --git a/vio/run.sh b/vio/run.sh
index 1c392e4..f3ba7a1 100755
--- a/vio/run.sh
+++ b/vio/run.sh
@@ -20,12 +20,14 @@ sed -i "s/AAI_PORT =.*/AAI_PORT = \"${AAI_PORT}\"/g" vio/pub/config/config.py
sed -i "s/AAI_SCHEMA_VERSION =.*/AAI_SCHEMA_VERSION = \"${AAI_SCHEMA_VERSION}\"/g" vio/pub/config/config.py
sed -i "s/AAI_USERNAME =.*/AAI_USERNAME = \"${AAI_USERNAME}\"/g" vio/pub/config/config.py
sed -i "s/AAI_PASSWORD =.*/AAI_PASSWORD = \"${AAI_PASSWORD}\"/g" vio/pub/config/config.py
-
+sed -i "s/MR_ADDR =.*/MR_ADDR = \"${MR_ADDR}\"/g" vio/pub/config/config.py
+sed -i "s/MR_PORT =.*/MR_PORT = \"${MR_PORT}\"/g" vio/pub/config/config.py
logDir="/var/log/onap/multicloud/vio"
nohup python manage.py runserver 0.0.0.0:9004 2>&1 &
+nohup python vio/event_listener/server.py 2>&1 &
while [ ! -f $logDir/vio.log ]; do
sleep 1
diff --git a/vio/vio/api_v2/api_definition/ports.yaml b/vio/vio/api_v2/api_definition/ports.yaml
new file mode 100644
index 0000000..0599ae2
--- /dev/null
+++ b/vio/vio/api_v2/api_definition/ports.yaml
@@ -0,0 +1,83 @@
+---
+ info:
+ version: "1.0.0"
+ title: "Multi Cloud Port"
+ description: "Definition of Port API"
+ termsOfService: "http://swagger.io/terms/"
+ schemes:
+ - "http"
+ produces:
+ - "application/json"
+ paths:
+ /{vimid}/{tenantid}/ports/{portid}:
+ parameters:
+ - type: string
+ name: vimid
+ - type: string
+ format: uuid
+ name: tenantid
+ - type: string
+ name: portid
+ in: path
+ required: true
+ get:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/port"
+ get_all:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ type: "array"
+ items:
+ $ref: "#/definitions/port"
+ post:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/port"
+ delete:
+ responses: "204"
+ vim_path: "/network/v2.0/ports"
+ definitions:
+ port:
+ plural_vim_resource: "ports"
+ vim_resource: "port"
+ plural: "port"
+ properties:
+ name:
+ type: string
+ required: true
+ source: port.name
+ id:
+ type: string
+ source: port.id
+ status:
+ type: string
+ source: port.status
+ networkId:
+ type: string
+ source: port.network_id
+ required: true
+ vnicType:
+ source: port.binding:vnic_type
+ securityGroups:
+ type: string
+ source: port.security_groups
+ tenantId:
+ type: string
+ source: port.tenant_id
+ macAddress:
+ type: string
+ source: port.mac_address
+ subnetId:
+ source: port.fixed_ips[0].subnet_id
+ ip:
+ source: port.fixed_ips[0].ip_address
diff --git a/vio/vio/api_v2/api_definition/subnets.yaml b/vio/vio/api_v2/api_definition/subnets.yaml
new file mode 100644
index 0000000..bbe35c0
--- /dev/null
+++ b/vio/vio/api_v2/api_definition/subnets.yaml
@@ -0,0 +1,88 @@
+---
+ info:
+ version: "1.0.0"
+ title: "Multi Cloud Subnet"
+ description: "Definition of Subnet API"
+ termsOfService: "http://swagger.io/terms/"
+ schemes:
+ - "http"
+ produces:
+ - "application/json"
+ paths:
+ /{vimid}/{tenantid}/subnets/{subnetid}:
+ parameters:
+ - type: string
+ name: vimid
+ - type: string
+ format: uuid
+ name: tenantid
+ - type: string
+ name: subnetid
+ in: path
+ required: true
+ get:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/subnet"
+ get_all:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ type: "array"
+ items:
+ $ref: "#/definitions/subnet"
+ post:
+ produces:
+ - "application/json"
+ responses:
+ "200":
+ schema:
+ $ref: "#/definitions/subnet"
+ delete:
+ responses: "204"
+ vim_path: "/network/v2.0/subnets"
+ definitions:
+ subnet:
+ plural_vim_resource: "subnets"
+ vim_resource: "subnet"
+ plural: "subnets"
+ properties:
+ name:
+ type: string
+ required: true
+ source: subnet.name
+ id:
+ type: string
+ source: subnet.id
+ status:
+ type: string
+ source: subnet.status
+ networkId:
+ type: string
+ source: subnet.network_id
+ required: true
+ allocationPools:
+ source: subnet.allocation_pools
+ gatewayIp:
+ type: string
+ source: subnet.gateway_ip
+ default: None
+ tenantId:
+ type: string
+ source: subnet.tenant_id
+ enableDhcp:
+ type: boolean
+ source: subnet.enable_dhcp
+ ipVersion:
+ source: subnet.ip_version
+ dnsNameServers:
+ source: subnet.dns_nameservers
+ cidr:
+ source: subnet.cidr
+ hostRoutes:
+ source: subnet.host_routes
diff --git a/vio/vio/api_v2/api_router/controller_builder.py b/vio/vio/api_v2/api_router/controller_builder.py
index 4e6d39d..a3c70b2 100644
--- a/vio/vio/api_v2/api_router/controller_builder.py
+++ b/vio/vio/api_v2/api_router/controller_builder.py
@@ -16,12 +16,16 @@ from keystoneauth1.identity import v3 as keystone_v3
from keystoneauth1 import session
import pecan
from pecan import rest
+import re
from vio.api_v2.api_definition import utils
from vio.pub import exceptions
from vio.pub.msapi import extsys
+OBJ_IN_ARRAY = "(\w+)\[(\d+)\]\.(\w+)"
+
+
def _get_vim_auth_session(vim_id, tenant_id):
""" Get the auth session to backend VIM """
@@ -67,48 +71,56 @@ def _convert_default_value(default):
return default
+def _property_exists(resource, attr, required=False):
+ if attr not in resource:
+ if required:
+ raise Exception("Required field %s is missed in VIM "
+ "resource %s", (attr, resource))
+ else:
+ return False
+
+ return True
+
+
def _convert_vim_res_to_mc_res(vim_resource, res_properties):
mc_resource = {}
for key in res_properties:
- vim_res, attr = res_properties[key]["source"].split('.')
-
- if attr not in vim_resource[vim_res]:
- if res_properties[key].get("required"):
- raise Exception("Required field %s is missed in VIM "
- "resource %s", (attr, vim_resource))
+ vim_res, attr = res_properties[key]["source"].split('.', 1)
+ # action = res_properties[key].get("action", "copy")
+ if re.match(OBJ_IN_ARRAY, attr):
+ attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups()
+ if _property_exists(vim_resource[vim_res], attr):
+ mc_resource[key] = (
+ vim_resource[vim_res][attr][int(index)][sub_attr])
+ else:
+ if _property_exists(vim_resource[vim_res], attr,
+ res_properties[key].get("required")):
+ mc_resource[key] = vim_resource[vim_res][attr]
else:
if "default" in res_properties[key]:
mc_resource[key] = _convert_default_value(
res_properties[key]["default"])
- # None required fields missed, just skip.
- continue
-
- action = res_properties[key].get("action", "copy")
- # TODO(xiaohhui): Actions should be in constants.
- if action == "copy":
- mc_resource[key] = vim_resource[vim_res][attr]
-
return mc_resource
def _convert_mc_res_to_vim_res(mc_resource, res_properties):
vim_resource = {}
for key in res_properties:
- vim_res, attr = res_properties[key]["source"].split('.')
-
- if key not in mc_resource:
- if res_properties[key].get("required"):
- raise Exception("Required field %s is missed in MultiCloud "
- "resource %s", (key, mc_resource))
- else:
- # None required fields missed, just skip.
- continue
-
- action = res_properties[key].get("action", "copy")
- # TODO(xiaohhui): Actions should be in constants.
- if action == "copy":
- vim_resource[attr] = mc_resource[key]
+ vim_res, attr = res_properties[key]["source"].split('.', 1)
+ # action = res_properties[key].get("action", "copy")
+ if re.match(OBJ_IN_ARRAY, attr):
+ attr, index, sub_attr = re.match(OBJ_IN_ARRAY, attr).groups()
+ if _property_exists(mc_resource, key):
+ vim_resource[attr] = vim_resource.get(attr, [])
+ if vim_resource[attr]:
+ vim_resource[attr][0].update({sub_attr: mc_resource[key]})
+ else:
+ vim_resource[attr].append({sub_attr: mc_resource[key]})
+ else:
+ if _property_exists(mc_resource, key,
+ res_properties[key].get("required")):
+ vim_resource[attr] = mc_resource[key]
return vim_resource
@@ -141,10 +153,11 @@ def _build_api_controller(api_meta):
resp = session.get(full_url, endpoint_filter=service)
mc_res = _convert_vim_res_to_mc_res(resp.json(),
resource_properties)
- return {"vimName": vim_id,
- name: mc_res,
- "tenantId": tenant_id,
- "vimid": vim_id}
+ mc_res.update({"vimName": vim_id,
+ "vimId": vim_id,
+ "tenantId": tenant_id,
+ "returnCode": 0})
+ return mc_res
controller_meta["get"] = _get
diff --git a/vio/vio/api_v2/service.py b/vio/vio/api_v2/service.py
index a9473c3..60fb991 100644
--- a/vio/vio/api_v2/service.py
+++ b/vio/vio/api_v2/service.py
@@ -16,6 +16,7 @@ from oslo_service import service
from oslo_service import wsgi
from vio.api_v2 import app
+from vio.pub.config import config as mc_cfg
CONF = cfg.CONF
@@ -33,9 +34,8 @@ class WSGIService(service.ServiceBase):
CONF,
"vio",
self.app,
- # TODO(xiaohhui): these should be configurable.
host="0.0.0.0",
- port="9004",
+ port=mc_cfg.API_SERVER_PORT,
use_ssl=False
)
diff --git a/vio/vio/event_listener/.gitignore b/vio/vio/event_listener/.gitignore
new file mode 100755
index 0000000..0d20b64
--- /dev/null
+++ b/vio/vio/event_listener/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/vio/vio/event_listener/__init__.py b/vio/vio/event_listener/__init__.py
new file mode 100755
index 0000000..012fba8
--- /dev/null
+++ b/vio/vio/event_listener/__init__.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017-2018 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/event_listener/i18n.py b/vio/vio/event_listener/i18n.py
new file mode 100755
index 0000000..772f4cd
--- /dev/null
+++ b/vio/vio/event_listener/i18n.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import oslo_i18n
+
+DOMAIN = "test_oslo"
+
+_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
+
+# The primary translation function using the well-known name "_"
+_ = _translators.primary
+
+# The contextual translation function using the name "_C"
+_C = _translators.contextual_form
+
+# The plural translation function using the name "_P"
+_P = _translators.plural_form
+
+# Translators for log levels.
+#
+# The abbreviated names are meant to reflect the usual use of a short
+# name like '_'. The "L" is for "log" and the other letter comes from
+# the level.
+_LI = _translators.log_info
+_LW = _translators.log_warning
+_LE = _translators.log_error
+_LC = _translators.log_critical
diff --git a/vio/vio/event_listener/listener.conf b/vio/vio/event_listener/listener.conf
new file mode 100755
index 0000000..e57614f
--- /dev/null
+++ b/vio/vio/event_listener/listener.conf
@@ -0,0 +1,3 @@
+[Listener]
+rabbit_ip=10.154.9.172
+rabbit_passwd=6C2B96AsbinmFf1a9c6a \ No newline at end of file
diff --git a/vio/vio/event_listener/server.py b/vio/vio/event_listener/server.py
new file mode 100755
index 0000000..83b9e6f
--- /dev/null
+++ b/vio/vio/event_listener/server.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from oslo_config import cfg
+from oslo_log import log as logging
+from i18n import _LI
+import oslo_messaging
+import ConfigParser
+import json
+import os
+import requests
+from vio.pub.config.config import MR_ADDR
+from vio.pub.config.config import MR_PORT
+
+LOG = logging.getLogger(__name__)
+
+
+def prepare():
+
+ product_name = "oslo_server"
+ logging.register_options(cfg.CONF)
+ logging.setup(cfg.CONF, product_name)
+
+
+'''
+below items must be added into vio nova.conf then restart nova services:
+notification_driver=messaging
+notification_topics= notifications_test
+notify_on_state_change=vm_and_task_state
+notify_on_any_change=True
+instance_usage_audit=True
+instance_usage_audit_period=hour
+'''
+
+
+def getConfig(section, key):
+
+ config = ConfigParser.ConfigParser()
+ path = os.path.split(os.path.realpath(__file__))[0] + '/listener.conf'
+ config.read(path)
+ return config.get(section, key)
+
+
+class NotificationEndPoint():
+
+ filter_rule = oslo_messaging.NotificationFilter(
+ publisher_id='^compute.*')
+
+ def info(self, ctxt, publisher_id, event_type, payload, metadata):
+
+ VM_EVENTS = {
+ 'compute.instance.unpause.start',
+ 'compute.instance.pause.start',
+ 'compute.instance.power_off.start',
+ 'compute.instance.reboot.start',
+ 'compute.instance.create.start'
+ }
+
+ status = payload.get('state_description')
+ if status != '' and event_type in VM_EVENTS:
+ url = 'http://%s:%s/events/test' % (MR_ADDR, MR_PORT)
+ headers = {'Content-type': 'application/json'}
+ requests.post(url, json.dumps(payload), headers=headers)
+
+ LOG.info(event_type)
+ self.action(payload)
+
+ def action(self, data):
+ LOG.info(_LI(json.dumps(data)))
+
+
+class Server(object):
+
+ def __init__(self):
+ self.topic = 'notifications_test'
+ self.server = None
+ prepare()
+
+
+class NotificationServer(Server):
+
+ def __init__(self):
+ super(NotificationServer, self).__init__()
+ # rabbit IP and password come from listener.conf
+ url = 'rabbit://test:%s@%s:5672/' % (
+ getConfig('Listener', 'rabbit_passwd'),
+ getConfig('Listener', 'rabbit_ip')
+ )
+ self.transport = oslo_messaging.get_notification_transport(
+ cfg.CONF,
+ url=url)
+ # The exchange must be the same as
+ # control_exchange in transport setting in client.
+ self.targets = [oslo_messaging.Target(
+ topic=self.topic,
+ exchange='nova')]
+ self.endpoints = [NotificationEndPoint()]
+
+ def start(self):
+ LOG.info(_LI("Start Notification server..."))
+ self.server = oslo_messaging.get_notification_listener(
+ self.transport,
+ self.targets,
+ self.endpoints,
+ executor='threading')
+ self.server.start()
+ self.server.wait()
+
+
+if __name__ == '__main__':
+
+ notification_server = NotificationServer()
+ notification_server.start()
diff --git a/vio/vio/pub/config/config.py b/vio/vio/pub/config/config.py
index 9b4d6c8..757ba28 100644
--- a/vio/vio/pub/config/config.py
+++ b/vio/vio/pub/config/config.py
@@ -28,7 +28,14 @@ AAI_SCHEMA_VERSION = "v13"
AAI_USERNAME = 'AAI'
AAI_PASSWORD = 'AAI'
+# [DMaaP]
+MR_ADDR = "127.0.0.1"
+MR_PORT = "3904"
+
# [MDC]
SERVICE_NAME = "multicloud-vio"
FORWARDED_FOR_FIELDS = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST",
"HTTP_X_FORWARDED_SERVER"]
+
+# [Local Config]
+API_SERVER_PORT = 9004
diff --git a/vio/vio/scripts/api.py b/vio/vio/scripts/api.py
index c3bd1a7..5ba83c9 100644
--- a/vio/vio/scripts/api.py
+++ b/vio/vio/scripts/api.py
@@ -12,9 +12,13 @@
import eventlet
eventlet.monkey_patch()
+import os # noqa
from oslo_config import cfg # noqa
from oslo_service import service # noqa
import sys # noqa
+# FIXME: Since there is no explicitly setup process for the project. Hack the
+# python here.
+sys.path.append(os.path.abspath('.'))
from vio.api_v2 import service as api_service # noqa