Notifications resource support, helpers.py link functions
Change-Id: I09e69529fe1cd09f824b837887251921f060f640
This commit is contained in:
parent
c6802b8816
commit
4c585dc46e
@ -39,6 +39,9 @@ events_driver = none
|
|||||||
# The driver to use for the transforms repository
|
# The driver to use for the transforms repository
|
||||||
transforms_driver = mysql_transforms_repo
|
transforms_driver = mysql_transforms_repo
|
||||||
|
|
||||||
|
# The driver to use for the notifications repository
|
||||||
|
notifications_driver = mysql_notifications_repo
|
||||||
|
|
||||||
[dispatcher]
|
[dispatcher]
|
||||||
driver = v2_reference
|
driver = v2_reference
|
||||||
|
|
||||||
|
@ -46,33 +46,17 @@ class V2API(object):
|
|||||||
def do_get_statistics(self, req, res):
|
def do_get_statistics(self, req, res):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/notification-methods', method='post')
|
|
||||||
def do_post_notification_methods(self, req, res):
|
|
||||||
res.status = '501 Not Implemented'
|
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/notification-methods/{id}', method='put')
|
|
||||||
def do_put_notification_methods(self, req, res, id):
|
|
||||||
res.status = '501 Not Implemented'
|
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/notification-methods/{id}', method='delete')
|
|
||||||
def do_delete_notification_methods(self, req, res, id):
|
|
||||||
res.status = '501 Not Implemented'
|
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/notification-methods/{id}', method='get')
|
|
||||||
def do_get_notification_methods(self, req, res, id):
|
|
||||||
res.status = '501 Not Implemented'
|
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/alarm-definitions', method='post')
|
@resource_api.Restify('/v2.0/alarm-definitions', method='post')
|
||||||
def do_post_alarm_definitions(self, req, res):
|
def do_post_alarm_definitions(self, req, res):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/alarm-definitions/{id}', method='get')
|
@resource_api.Restify('/v2.0/alarm-definitions/{id}', method='get')
|
||||||
def do_get_alarm_definition(self, req, res, id):
|
def do_get_alarm_definition(self, req, res, id):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/alarm-definitions/{id}', method='put')
|
@resource_api.Restify('/v2.0/alarm-definitions/{id}', method='put')
|
||||||
def do_put_alarm_definitions(self, req, res, id):
|
def do_put_alarm_definitions(self, req, res, id):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
@resource_api.Restify('/v2.0/alarm-definitions', method='get')
|
@resource_api.Restify('/v2.0/alarm-definitions', method='get')
|
||||||
def do_get_alarm_definitions(self, req, res):
|
def do_get_alarm_definitions(self, req, res):
|
||||||
@ -112,4 +96,4 @@ class V2API(object):
|
|||||||
|
|
||||||
@resource_api.Restify('/v2.0/alarms/{id}/state-history', method='get')
|
@resource_api.Restify('/v2.0/alarms/{id}/state-history', method='get')
|
||||||
def do_get_alarm_state_history(self, req, res, id):
|
def do_get_alarm_state_history(self, req, res, id):
|
||||||
res.status = '501 Not Implemented'
|
res.status = '501 Not Implemented'
|
||||||
|
46
monasca/api/monasca_notifications_api_v2.py
Normal file
46
monasca/api/monasca_notifications_api_v2.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard
|
||||||
|
#
|
||||||
|
# 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 monasca.common import resource_api
|
||||||
|
from monasca.openstack.common import log
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationsV2API(object):
|
||||||
|
|
||||||
|
def __init__(self, global_conf):
|
||||||
|
LOG.debug('initializing V2API!')
|
||||||
|
self.global_conf = global_conf
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods', method='post')
|
||||||
|
def do_post_notification_methods(self, req, res):
|
||||||
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='delete')
|
||||||
|
def do_delete_notification_methods(self, req, res, id):
|
||||||
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods', method='get')
|
||||||
|
def do_get_notification_methods(self, req, res):
|
||||||
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='get')
|
||||||
|
def do_get_notification_method(self, req, res, id):
|
||||||
|
res.status = '501 Not Implemented'
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='put')
|
||||||
|
def do_put_notification_methods(self, req, res, id):
|
||||||
|
res.status = '501 Not Implemented'
|
@ -26,6 +26,7 @@ from wsgiref import simple_server
|
|||||||
METRICS_DISPATCHER_NAMESPACE = 'monasca.metrics_dispatcher'
|
METRICS_DISPATCHER_NAMESPACE = 'monasca.metrics_dispatcher'
|
||||||
EVENTS_DISPATCHER_NAMESPACE = 'monasca.events_dispatcher'
|
EVENTS_DISPATCHER_NAMESPACE = 'monasca.events_dispatcher'
|
||||||
TRANSFORMS_DISPATCHER_NAMESPACE = 'monasca.transforms_dispatcher'
|
TRANSFORMS_DISPATCHER_NAMESPACE = 'monasca.transforms_dispatcher'
|
||||||
|
NOTIFICATIONS_DISPATCHER_NAMESPACE = 'monasca.notifications_dispatcher'
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -63,7 +64,8 @@ cfg.CONF.register_opts(messaging_opts, messaging_group)
|
|||||||
repositories_opts = [
|
repositories_opts = [
|
||||||
cfg.StrOpt('metrics_driver', default='influxdb_metrics_repo', help='The repository driver to use for metrics'),
|
cfg.StrOpt('metrics_driver', default='influxdb_metrics_repo', help='The repository driver to use for metrics'),
|
||||||
cfg.StrOpt('events_driver', default='fake_events_repo', help='The repository driver to use for events'),
|
cfg.StrOpt('events_driver', default='fake_events_repo', help='The repository driver to use for events'),
|
||||||
cfg.StrOpt('transforms_driver', default='mysql_transforms_repo', help='The repository driver to use for transforms')
|
cfg.StrOpt('transforms_driver', default='mysql_transforms_repo', help='The repository driver to use for transforms'),
|
||||||
|
cfg.StrOpt('notifications_driver', default='mysql_notifications_repo', help='The repository driver to use for notifications')
|
||||||
]
|
]
|
||||||
|
|
||||||
repositories_group = cfg.OptGroup(name='repositories', title='repositories')
|
repositories_group = cfg.OptGroup(name='repositories', title='repositories')
|
||||||
@ -161,45 +163,21 @@ def api_app(conf):
|
|||||||
# Create the application
|
# Create the application
|
||||||
app = resource_api.ResourceAPI()
|
app = resource_api.ResourceAPI()
|
||||||
|
|
||||||
# load the metrics driver specified by dispatcher in the monasca.ini file
|
# add the metrics resource
|
||||||
metrics_manager = driver.DriverManager(namespace=METRICS_DISPATCHER_NAMESPACE,
|
app.add_resource('metrics', METRICS_DISPATCHER_NAMESPACE,
|
||||||
name=cfg.CONF.dispatcher.driver,
|
cfg.CONF.dispatcher.driver, [conf])
|
||||||
invoke_on_load=True,
|
|
||||||
invoke_args=[conf])
|
|
||||||
|
|
||||||
LOG.debug('Metrics dispatcher driver %s is loaded.' % cfg.CONF.dispatcher.driver)
|
# add the events resource
|
||||||
|
app.add_resource('events', EVENTS_DISPATCHER_NAMESPACE,
|
||||||
|
cfg.CONF.dispatcher.driver, [conf])
|
||||||
|
|
||||||
# add the driver to the application
|
# add the transforms resource
|
||||||
app.add_route(None, metrics_manager.driver)
|
app.add_resource('transforms', TRANSFORMS_DISPATCHER_NAMESPACE,
|
||||||
|
cfg.CONF.dispatcher.driver, [conf])
|
||||||
|
|
||||||
LOG.debug('Metrics dispatcher driver has been added to the routes!')
|
# add the notifications resource
|
||||||
|
app.add_resource('notifications', NOTIFICATIONS_DISPATCHER_NAMESPACE,
|
||||||
|
cfg.CONF.dispatcher.driver, [conf])
|
||||||
# load the events driver specified by dispatcher in the monasca.ini file
|
|
||||||
events_manager = driver.DriverManager(namespace=EVENTS_DISPATCHER_NAMESPACE,
|
|
||||||
name=cfg.CONF.dispatcher.driver,
|
|
||||||
invoke_on_load=True,
|
|
||||||
invoke_args=[conf])
|
|
||||||
|
|
||||||
LOG.debug('Events dispatcher driver %s is loaded.' % cfg.CONF.dispatcher.driver)
|
|
||||||
|
|
||||||
# add the driver to the application
|
|
||||||
app.add_route(None, events_manager.driver)
|
|
||||||
|
|
||||||
LOG.debug('Events dispatcher driver has been added to the routes!')
|
|
||||||
|
|
||||||
# load the events driver specified by dispatcher in the monasca.ini file
|
|
||||||
transforms_manager = driver.DriverManager(namespace=TRANSFORMS_DISPATCHER_NAMESPACE,
|
|
||||||
name=cfg.CONF.dispatcher.driver,
|
|
||||||
invoke_on_load=True,
|
|
||||||
invoke_args=[conf])
|
|
||||||
|
|
||||||
LOG.debug('Transforms dispatcher driver %s is loaded.' % cfg.CONF.dispatcher.driver)
|
|
||||||
|
|
||||||
# add the driver to the application
|
|
||||||
app.add_route(None, transforms_manager.driver)
|
|
||||||
|
|
||||||
LOG.debug('Transforms dispatcher driver has been added to the routes!')
|
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
@ -207,4 +185,4 @@ def api_app(conf):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
wsgi_app = loadapp('config:etc/monasca.ini', relative_to=os.getcwd())
|
wsgi_app = loadapp('config:etc/monasca.ini', relative_to=os.getcwd())
|
||||||
httpd = simple_server.make_server('127.0.0.1', 9000, wsgi_app)
|
httpd = simple_server.make_server('127.0.0.1', 9000, wsgi_app)
|
||||||
httpd.serve_forever()
|
httpd.serve_forever()
|
||||||
|
133
monasca/common/repositories/mysql/notifications_repository.py
Normal file
133
monasca/common/repositories/mysql/notifications_repository.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard
|
||||||
|
#
|
||||||
|
# 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 datetime
|
||||||
|
from monasca.common.repositories import notifications_repository
|
||||||
|
from monasca.common.repositories import exceptions
|
||||||
|
from monasca.openstack.common import log
|
||||||
|
import peewee
|
||||||
|
import model
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Notification_Method(model.Model):
|
||||||
|
id = peewee.TextField(36)
|
||||||
|
tenant_id = peewee.TextField(36)
|
||||||
|
name = peewee.TextField()
|
||||||
|
type = peewee.TextField()
|
||||||
|
address = peewee.TextField()
|
||||||
|
created_at = peewee.DateTimeField()
|
||||||
|
updated_at = peewee.DateTimeField()
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationsRepository(
|
||||||
|
notifications_repository.NotificationsRepository):
|
||||||
|
|
||||||
|
def notification_from_result(self, result):
|
||||||
|
notification = dict(id=result.id,
|
||||||
|
name=result.name,
|
||||||
|
type=result.type,
|
||||||
|
address=result.address)
|
||||||
|
return notification
|
||||||
|
|
||||||
|
def exists(self, tenant_id, name):
|
||||||
|
try:
|
||||||
|
return (Notification_Method.select().where(
|
||||||
|
(Notification_Method.tenant_id == tenant_id) & (
|
||||||
|
Notification_Method.name == name)).count() > 0)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
|
def create_notification(
|
||||||
|
self, id, tenant_id, name, notification_type, address):
|
||||||
|
try:
|
||||||
|
now = datetime.datetime.utcnow()
|
||||||
|
q = Notification_Method.create(
|
||||||
|
id=id,
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
name=name,
|
||||||
|
notification_type=notification_type,
|
||||||
|
address=address,
|
||||||
|
created_at=now,
|
||||||
|
updated_at=now)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
|
def list_notifications(self, tenant_id):
|
||||||
|
try:
|
||||||
|
q = Notification_Method.select().where(
|
||||||
|
Notification_Method.tenant_id == tenant_id)
|
||||||
|
results = q.execute()
|
||||||
|
|
||||||
|
notifications = []
|
||||||
|
notifications = [
|
||||||
|
self.notification_from_result(result) for result in results]
|
||||||
|
return notifications
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
|
def delete_notification(self, tenant_id, notification_id):
|
||||||
|
num_rows_deleted = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
q = Notification_Method.delete().where(
|
||||||
|
(Notification_Method.tenant_id == tenant_id) & (
|
||||||
|
Notification_Method.id == notification_id))
|
||||||
|
num_rows_deleted = q.execute()
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
|
if num_rows_deleted < 1:
|
||||||
|
raise exceptions.DoesNotExistException()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def list_notification(self, tenant_id, notification_id):
|
||||||
|
try:
|
||||||
|
result = Notification_Method.get(
|
||||||
|
(Notification_Method.tenant_id == tenant_id) & (
|
||||||
|
Notification_Method.id == notification_id))
|
||||||
|
return (self.notification_from_result(result))
|
||||||
|
except Notification_Method.DoesNotExist as e:
|
||||||
|
raise exceptions.DoesNotExistException(str(e))
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
|
||||||
|
def update_notification(
|
||||||
|
self, id, tenant_id, name, notification_type, address):
|
||||||
|
now = datetime.datetime.utcnow()
|
||||||
|
num_rows_updated = 0
|
||||||
|
try:
|
||||||
|
q = Notification_Method.update(
|
||||||
|
name=name,
|
||||||
|
type=notification_type,
|
||||||
|
address=address,
|
||||||
|
created_at=now,
|
||||||
|
updated_at=now).where(
|
||||||
|
(Notification_Method.tenant_id == tenant_id) & (
|
||||||
|
Notification_Method.id == id))
|
||||||
|
# Execute the query, updating the database.
|
||||||
|
num_rows_updated = q.execute()
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.exception(ex)
|
||||||
|
raise exceptions.RepositoryException(ex)
|
||||||
|
else:
|
||||||
|
if num_rows_updated == 0:
|
||||||
|
raise exceptions.DoesNotExistException('Not Found')
|
42
monasca/common/repositories/notifications_repository.py
Normal file
42
monasca/common/repositories/notifications_repository.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard
|
||||||
|
#
|
||||||
|
# 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 abc
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class NotificationsRepository(object):
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_notification(self, id, tenant_id, name, notification_type,
|
||||||
|
address):
|
||||||
|
return
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def list_notifications(self, tenant_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_notification(self, tenant_id, notification_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def list_notification(self, tenant_id, notification_id):
|
||||||
|
return
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_notification(self, id, tenant_id, name, notification_type,
|
||||||
|
address):
|
||||||
|
return
|
@ -18,13 +18,32 @@ import falcon
|
|||||||
from falcon import api_helpers
|
from falcon import api_helpers
|
||||||
|
|
||||||
from monasca.openstack.common import log
|
from monasca.openstack.common import log
|
||||||
|
from stevedore import driver
|
||||||
|
|
||||||
RESOURCE_METHOD_FLAG = 'fab05a04-b861-4651-bd0c-9cb3eb9a6088'
|
RESOURCE_METHOD_FLAG = 'fab05a04-b861-4651-bd0c-9cb3eb9a6088'
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def init_driver(namespace, driver_name, drv_invoke_args=None):
|
||||||
|
"""Initialize the resource driver and returns it.
|
||||||
|
|
||||||
|
:param namespace: the resource namespace (in setup.cfg).
|
||||||
|
:param driver_name: the driver name (in monasca.conf)
|
||||||
|
:param invoke_args: args to pass to the driver (a tuple)
|
||||||
|
"""
|
||||||
|
invoke_args_tuple = ()
|
||||||
|
if drv_invoke_args:
|
||||||
|
invoke_args_tuple = drv_invoke_args
|
||||||
|
mgr = driver.DriverManager(
|
||||||
|
namespace = namespace,
|
||||||
|
name = driver_name,
|
||||||
|
invoke_on_load = True,
|
||||||
|
invoke_args = invoke_args_tuple
|
||||||
|
)
|
||||||
|
return mgr.driver
|
||||||
|
|
||||||
|
|
||||||
class Restify(object):
|
class Restify(object):
|
||||||
def __init__(self, path='', method='GET'):
|
def __init__(self, path='', method='GET'):
|
||||||
if not path:
|
if not path:
|
||||||
@ -41,7 +60,6 @@ class Restify(object):
|
|||||||
|
|
||||||
|
|
||||||
class ResourceAPI(falcon.API):
|
class ResourceAPI(falcon.API):
|
||||||
|
|
||||||
def add_route(self, uri_template, resource):
|
def add_route(self, uri_template, resource):
|
||||||
"""Associates uri patterns with resource methods.
|
"""Associates uri patterns with resource methods.
|
||||||
|
|
||||||
@ -114,4 +132,21 @@ class ResourceAPI(falcon.API):
|
|||||||
path_maps[item][1]))
|
path_maps[item][1]))
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception('Error occurred while adding the resource')
|
LOG.exception('Error occurred while adding the resource')
|
||||||
LOG.debug(self._routes)
|
LOG.debug(self._routes)
|
||||||
|
|
||||||
|
def add_resource(self, resource_name, namespace, driver_name,
|
||||||
|
invoke_args=None, uri=None):
|
||||||
|
"""Loads the resource driver, and adds it to the routes.
|
||||||
|
|
||||||
|
:param resource_name: the name of the resource.
|
||||||
|
:param namespace: the resource namespace (in setup.cfg).
|
||||||
|
:param driver_name: the driver name (in monasca.conf)
|
||||||
|
:param invoke_args: args to pass to the driver (a tuple)
|
||||||
|
:param uri: the uri to associate with the resource
|
||||||
|
"""
|
||||||
|
resource_driver = init_driver(namespace, driver_name, invoke_args)
|
||||||
|
LOG.debug('%s dispatcher driver %s is loaded.' %
|
||||||
|
(resource_name, driver_name))
|
||||||
|
self.add_route(uri, resource_driver)
|
||||||
|
LOG.debug('%s dispatcher driver has been added to the routes!' %
|
||||||
|
(resource_name))
|
@ -0,0 +1,36 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard
|
||||||
|
#
|
||||||
|
# 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 voluptuous import Schema
|
||||||
|
from voluptuous import Optional, Required, Any, All, Length
|
||||||
|
from monasca.openstack.common import log
|
||||||
|
from monasca.v2.common.schemas import exceptions
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
notification_schema = {
|
||||||
|
Required('name'): Schema(All(Any(str, unicode), Length(max=250))),
|
||||||
|
Required('type'): Schema(Any("EMAIL", "email")),
|
||||||
|
Required('address'): Schema(All(Any(str, unicode), Length(max=100)))
|
||||||
|
}
|
||||||
|
|
||||||
|
request_body_schema = Schema(Any(notification_schema))
|
||||||
|
|
||||||
|
|
||||||
|
def validate(msg):
|
||||||
|
try:
|
||||||
|
request_body_schema(msg)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.debug(ex)
|
||||||
|
raise exceptions.ValidationException(str(ex))
|
@ -20,7 +20,7 @@ from monasca.openstack.common import log
|
|||||||
from monasca.v2.common.schemas import exceptions as schemas_exceptions
|
from monasca.v2.common.schemas import exceptions as schemas_exceptions
|
||||||
from monasca.v2.common.schemas import metric_name_schema
|
from monasca.v2.common.schemas import metric_name_schema
|
||||||
from monasca.v2.common.schemas import dimensions_schema
|
from monasca.v2.common.schemas import dimensions_schema
|
||||||
|
import simplejson
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -32,16 +32,16 @@ def validate_json_content_type(req):
|
|||||||
|
|
||||||
|
|
||||||
def is_in_role(req, authorized_roles):
|
def is_in_role(req, authorized_roles):
|
||||||
'''
|
"""Determines if one or more of the X-ROLES is in the supplied
|
||||||
Determines if one or more of the X-ROLES is in the supplied
|
|
||||||
authorized_roles.
|
authorized_roles.
|
||||||
|
|
||||||
:param req: HTTP request object. Must contain "X-ROLES" in the HTTP
|
:param req: HTTP request object. Must contain "X-ROLES" in the HTTP
|
||||||
request header.
|
request header.
|
||||||
:param authorized_roles: List of authorized roles to check against.
|
:param authorized_roles: List of authorized roles to check against.
|
||||||
:return: Returns True if in the list of authorized roles, otherwise False.
|
:return: Returns True if in the list of authorized roles, otherwise False.
|
||||||
'''
|
"""
|
||||||
str_roles = req.get_header('X-ROLES')
|
str_roles = req.get_header('X-ROLES')
|
||||||
if str_roles == None:
|
if str_roles is None:
|
||||||
return False
|
return False
|
||||||
roles = str_roles.lower().split(',')
|
roles = str_roles.lower().split(',')
|
||||||
for role in roles:
|
for role in roles:
|
||||||
@ -51,15 +51,15 @@ def is_in_role(req, authorized_roles):
|
|||||||
|
|
||||||
|
|
||||||
def validate_authorization(req, authorized_roles):
|
def validate_authorization(req, authorized_roles):
|
||||||
'''
|
"""Validates whether one or more X-ROLES in the HTTP header is authorized.
|
||||||
Validates whether one or more X-ROLES in the HTTP header is authorized.
|
|
||||||
:param req: HTTP request object. Must contain "X-ROLES" in the HTTP
|
:param req: HTTP request object. Must contain "X-ROLES" in the HTTP
|
||||||
request header.
|
request header.
|
||||||
:param authorized_roles: List of authorized roles to check against.
|
:param authorized_roles: List of authorized roles to check against.
|
||||||
:raises falcon.HTTPUnauthorized:
|
:raises falcon.HTTPUnauthorized
|
||||||
'''
|
"""
|
||||||
str_roles = req.get_header('X-ROLES')
|
str_roles = req.get_header('X-ROLES')
|
||||||
if str_roles == None:
|
if str_roles is None:
|
||||||
raise falcon.HTTPUnauthorized('Forbidden',
|
raise falcon.HTTPUnauthorized('Forbidden',
|
||||||
'Tenant does not have any roles', '')
|
'Tenant does not have any roles', '')
|
||||||
roles = str_roles.lower().split(',')
|
roles = str_roles.lower().split(',')
|
||||||
@ -72,21 +72,21 @@ def validate_authorization(req, authorized_roles):
|
|||||||
|
|
||||||
|
|
||||||
def get_tenant_id(req):
|
def get_tenant_id(req):
|
||||||
'''
|
"""Returns the tenant ID in the HTTP request header.
|
||||||
Returns the tenant ID in the HTTP request header.
|
|
||||||
:param req: HTTP request object.
|
:param req: HTTP request object.
|
||||||
'''
|
"""
|
||||||
return req.get_header('X-TENANT-ID')
|
return req.get_header('X-TENANT-ID')
|
||||||
|
|
||||||
|
|
||||||
def get_cross_tenant_or_tenant_id(req, delegate_authorized_roles):
|
def get_cross_tenant_or_tenant_id(req, delegate_authorized_roles):
|
||||||
'''
|
"""Evaluates whether the tenant ID or cross tenant ID should be returned.
|
||||||
Evaluates whether the tenant ID or cross tenant ID should be returned.
|
|
||||||
:param req: HTTP request object.
|
:param req: HTTP request object.
|
||||||
:param delegate_authorized_roles: List of authorized roles that have
|
:param delegate_authorized_roles: List of authorized roles that have
|
||||||
delegate privileges.
|
delegate privileges.
|
||||||
:returns: Returns the cross tenant or tenant ID.
|
:returns: Returns the cross tenant or tenant ID.
|
||||||
'''
|
"""
|
||||||
if is_in_role(req, delegate_authorized_roles):
|
if is_in_role(req, delegate_authorized_roles):
|
||||||
params = parse_query_string(req.query_string)
|
params = parse_query_string(req.query_string)
|
||||||
if 'tenant_id' in params:
|
if 'tenant_id' in params:
|
||||||
@ -96,10 +96,10 @@ def get_cross_tenant_or_tenant_id(req, delegate_authorized_roles):
|
|||||||
|
|
||||||
|
|
||||||
def get_query_name(req):
|
def get_query_name(req):
|
||||||
'''
|
"""Returns the query param "name" if supplied.
|
||||||
Returns the query param "name" if supplied.
|
|
||||||
:param req: HTTP request object.
|
:param req: HTTP request object.
|
||||||
'''
|
"""
|
||||||
params = parse_query_string(req.query_string)
|
params = parse_query_string(req.query_string)
|
||||||
name = ''
|
name = ''
|
||||||
if 'name' in params:
|
if 'name' in params:
|
||||||
@ -108,12 +108,12 @@ def get_query_name(req):
|
|||||||
|
|
||||||
|
|
||||||
def get_query_dimensions(req):
|
def get_query_dimensions(req):
|
||||||
'''
|
"""Gets and parses the query param dimensions.
|
||||||
Gets and parses the query param dimensions.
|
|
||||||
:param req: HTTP request object.
|
:param req: HTTP request object.
|
||||||
:return: Returns the dimensions as a JSON object
|
:return: Returns the dimensions as a JSON object
|
||||||
:raises falcon.HTTPBadRequest: If dimensions are malformed.
|
:raises falcon.HTTPBadRequest: If dimensions are malformed.
|
||||||
'''
|
"""
|
||||||
try:
|
try:
|
||||||
params = parse_query_string(req.query_string)
|
params = parse_query_string(req.query_string)
|
||||||
dimensions = {}
|
dimensions = {}
|
||||||
@ -193,11 +193,11 @@ def get_query_period(req):
|
|||||||
|
|
||||||
|
|
||||||
def validate_query_name(name):
|
def validate_query_name(name):
|
||||||
'''
|
"""Validates the query param name.
|
||||||
Validates the query param name.
|
|
||||||
:param name: Query param name.
|
:param name: Query param name.
|
||||||
:raises falcon.HTTPBadRequest: If name is not valid.
|
:raises falcon.HTTPBadRequest: If name is not valid.
|
||||||
'''
|
"""
|
||||||
try:
|
try:
|
||||||
metric_name_schema.validate(name)
|
metric_name_schema.validate(name)
|
||||||
except schemas_exceptions.ValidationException as ex:
|
except schemas_exceptions.ValidationException as ex:
|
||||||
@ -206,13 +206,77 @@ def validate_query_name(name):
|
|||||||
|
|
||||||
|
|
||||||
def validate_query_dimensions(dimensions):
|
def validate_query_dimensions(dimensions):
|
||||||
'''
|
"""Validates the query param dimensions.
|
||||||
Validates the query param dimensions.
|
|
||||||
:param dimensions: Query param dimensions.
|
:param dimensions: Query param dimensions.
|
||||||
:raises falcon.HTTPBadRequest: If dimensions are not valid.
|
:raises falcon.HTTPBadRequest: If dimensions are not valid.
|
||||||
'''
|
"""
|
||||||
try:
|
try:
|
||||||
dimensions_schema.validate(dimensions)
|
dimensions_schema.validate(dimensions)
|
||||||
except schemas_exceptions.ValidationException as ex:
|
except schemas_exceptions.ValidationException as ex:
|
||||||
LOG.debug(ex)
|
LOG.debug(ex)
|
||||||
raise falcon.HTTPBadRequest('Bad request', ex.message)
|
raise falcon.HTTPBadRequest('Bad request', ex.message)
|
||||||
|
|
||||||
|
|
||||||
|
def get_link(uri, resource_id, rel='self'):
|
||||||
|
"""Returns a link dictionary containing href, and rel.
|
||||||
|
|
||||||
|
:param uri: the http request.uri.
|
||||||
|
:param resource_id: the id of the resource
|
||||||
|
"""
|
||||||
|
href = uri + '/' + resource_id
|
||||||
|
link_dict = dict(href=href, rel=rel)
|
||||||
|
return link_dict
|
||||||
|
|
||||||
|
|
||||||
|
def add_links_to_resource(resource, uri):
|
||||||
|
"""Adds links to the given resource dictionary.
|
||||||
|
|
||||||
|
:param resource: the resource dictionary you wish to add links.
|
||||||
|
:param uri: the http request.uri.
|
||||||
|
"""
|
||||||
|
resource['links'] = [get_link(uri, resource['id'])]
|
||||||
|
return resource
|
||||||
|
|
||||||
|
|
||||||
|
def add_links_to_resource_list(resourcelist, uri):
|
||||||
|
"""Adds links to the given resource dictionary list.
|
||||||
|
|
||||||
|
:param resourcelist: the list of resources you wish to add links.
|
||||||
|
:param uri: the http request.uri.
|
||||||
|
"""
|
||||||
|
for resource in resourcelist:
|
||||||
|
add_links_to_resource(resource, uri)
|
||||||
|
return resourcelist
|
||||||
|
|
||||||
|
|
||||||
|
def read_http_resource(req):
|
||||||
|
"""Read from http request and return json.
|
||||||
|
|
||||||
|
:param req: the http request.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
msg = req.stream.read()
|
||||||
|
json_msg = simplejson.loads(msg)
|
||||||
|
return json_msg
|
||||||
|
except ValueError as ex:
|
||||||
|
LOG.debug(ex)
|
||||||
|
raise falcon.HTTPBadRequest(
|
||||||
|
'Bad request',
|
||||||
|
'Request body is not valid JSON')
|
||||||
|
|
||||||
|
|
||||||
|
def raise_not_found_exception(resource_name, resource_id, tenant_id):
|
||||||
|
"""Provides exception for not found requests (update, delete, list).
|
||||||
|
|
||||||
|
:param resource_name: the name of the resource.
|
||||||
|
:param resource_id: id of the resource.
|
||||||
|
:param tenant_id: id of the tenant
|
||||||
|
"""
|
||||||
|
msg = 'No %s method exists for tenant_id = %s id = %s' % (
|
||||||
|
resource_name, tenant_id, resource_id)
|
||||||
|
raise falcon.HTTPError(
|
||||||
|
status='404 Not Found',
|
||||||
|
title='Not Found',
|
||||||
|
description=msg,
|
||||||
|
code=404)
|
||||||
|
223
monasca/v2/reference/notifications.py
Normal file
223
monasca/v2/reference/notifications.py
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# TODO: Used simplejson to read the yaml as simplejson transforms to "str"
|
||||||
|
# not "unicode"
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
import falcon
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
from monasca.openstack.common import log
|
||||||
|
from monasca.openstack.common import uuidutils
|
||||||
|
from monasca.api import monasca_notifications_api_v2
|
||||||
|
from monasca.common import resource_api
|
||||||
|
from monasca.common.repositories import exceptions as repository_exceptions
|
||||||
|
from monasca.v2.common.schemas import exceptions as schemas_exceptions
|
||||||
|
from monasca.v2.common.schemas import notifications_request_body_schema as schemas_notifications
|
||||||
|
from monasca.v2.reference import helpers
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Notifications(monasca_notifications_api_v2.NotificationsV2API):
|
||||||
|
|
||||||
|
def __init__(self, global_conf):
|
||||||
|
super(Notifications, self).__init__(global_conf)
|
||||||
|
self._region = cfg.CONF.region
|
||||||
|
self._default_authorized_roles = cfg.CONF.security.default_authorized_roles
|
||||||
|
self._notifications_repo = resource_api.init_driver('monasca.repositories',
|
||||||
|
cfg.CONF.repositories.notifications_driver)
|
||||||
|
|
||||||
|
def _validate_notification(self, notification):
|
||||||
|
"""Validates the notification
|
||||||
|
|
||||||
|
:param notification: An event object.
|
||||||
|
:raises falcon.HTTPBadRequest
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
schemas_notifications.validate(notification)
|
||||||
|
except schemas_exceptions.ValidationException as ex:
|
||||||
|
LOG.debug(ex)
|
||||||
|
raise falcon.HTTPBadRequest('Bad request', ex.message)
|
||||||
|
|
||||||
|
def _create_notification(self, id, tenant_id, notification):
|
||||||
|
"""Store the notification using the repository.
|
||||||
|
|
||||||
|
:param notification: A notification object.
|
||||||
|
:raises: falcon.HTTPServiceUnavailable,falcon.HTTPConflict
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
name = notification['name']
|
||||||
|
notification_type = notification['type'].upper()
|
||||||
|
address = notification['address']
|
||||||
|
if self._notifications_repo.exists(tenant_id, name):
|
||||||
|
raise falcon.HTTPConflict(
|
||||||
|
'Conflict', ('Notification Method already exists: tenant_id=%s name=%s' %
|
||||||
|
(tenant_id, name)), code=409)
|
||||||
|
self._notifications_repo.create_notification(
|
||||||
|
id,
|
||||||
|
tenant_id,
|
||||||
|
name,
|
||||||
|
notification_type,
|
||||||
|
address)
|
||||||
|
except repository_exceptions.RepositoryException as ex:
|
||||||
|
LOG.error(ex)
|
||||||
|
raise falcon.HTTPInternalServerError(
|
||||||
|
'Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
def _update_notification(self, id, tenant_id, notification):
|
||||||
|
"""Update the notification using the repository.
|
||||||
|
|
||||||
|
:param notification: A notification object.
|
||||||
|
:raises: falcon.HTTPServiceUnavailable,falcon.HTTPError (404)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
name = notification['name']
|
||||||
|
notification_type = notification['type'].upper()
|
||||||
|
address = notification['address']
|
||||||
|
self._notifications_repo.update_notification(
|
||||||
|
id,
|
||||||
|
tenant_id,
|
||||||
|
name,
|
||||||
|
notification_type,
|
||||||
|
address)
|
||||||
|
except repository_exceptions.DoesNotExistException:
|
||||||
|
helpers.raise_not_found_exception('notification', id, tenant_id)
|
||||||
|
except repository_exceptions.RepositoryException as ex:
|
||||||
|
LOG.error(ex)
|
||||||
|
raise falcon.HTTPInternalServerError(
|
||||||
|
'Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
def _create_notification_response(self, id, notification, uri):
|
||||||
|
name = notification['name']
|
||||||
|
notification_type = notification['type'].upper()
|
||||||
|
address = notification['address']
|
||||||
|
response = {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'type': notification_type,
|
||||||
|
'address': address
|
||||||
|
}
|
||||||
|
return json.dumps(helpers.add_links_to_resource(response, uri))
|
||||||
|
|
||||||
|
def _list_notifications(self, tenant_id, uri):
|
||||||
|
"""Lists all notifications for this tenant id.
|
||||||
|
|
||||||
|
:param tenant_id: The tenant id.
|
||||||
|
:raises: falcon.HTTPServiceUnavailable
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
notifications = self._notifications_repo.list_notifications(
|
||||||
|
tenant_id)
|
||||||
|
return json.dumps(
|
||||||
|
helpers.add_links_to_resource_list(notifications, uri))
|
||||||
|
except repository_exceptions.RepositoryException as ex:
|
||||||
|
LOG.error(ex)
|
||||||
|
raise falcon.HTTPInternalServerError(
|
||||||
|
'Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
def _list_notification(self, tenant_id, notification_id, uri):
|
||||||
|
"""Lists the notification by id.
|
||||||
|
|
||||||
|
:param tenant_id: The tenant id.
|
||||||
|
:param notification_id: The notification id
|
||||||
|
:raises: falcon.HTTPServiceUnavailable,falcon.HTTPError (404):
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
notifications = self._notifications_repo.list_notification(
|
||||||
|
tenant_id,
|
||||||
|
notification_id)
|
||||||
|
return json.dumps(
|
||||||
|
helpers.add_links_to_resource(notifications, uri))
|
||||||
|
except repository_exceptions.DoesNotExistException:
|
||||||
|
helpers.raise_not_found_exception('notification', notification_id, tenant_id)
|
||||||
|
except repository_exceptions.RepositoryException as ex:
|
||||||
|
LOG.error(ex)
|
||||||
|
raise falcon.HTTPInternalServerError(
|
||||||
|
'Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
def _delete_notification(self, tenant_id, notification_id):
|
||||||
|
"""Deletes the notification using the repository.
|
||||||
|
|
||||||
|
:param tenant_id: The tenant id.
|
||||||
|
:param notification_id: The notification id
|
||||||
|
:raises: falcon.HTTPServiceUnavailable,falcon.HTTPError (404)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._notifications_repo.delete_notification(
|
||||||
|
tenant_id,
|
||||||
|
notification_id)
|
||||||
|
except repository_exceptions.DoesNotExistException:
|
||||||
|
helpers.raise_not_found_exception('notification', notification_id, tenant_id)
|
||||||
|
except repository_exceptions.RepositoryException as ex:
|
||||||
|
LOG.error(ex)
|
||||||
|
raise falcon.HTTPInternalServerError(
|
||||||
|
'Service unavailable',
|
||||||
|
ex.message)
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods', method='post')
|
||||||
|
def do_post_notification_methods(self, req, res):
|
||||||
|
helpers.validate_json_content_type(req)
|
||||||
|
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||||
|
notification = helpers.read_http_resource(req)
|
||||||
|
self._validate_notification(notification)
|
||||||
|
id = uuidutils.generate_uuid()
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
self._create_notification(id, tenant_id, notification)
|
||||||
|
res.body = self._create_notification_response(
|
||||||
|
id,
|
||||||
|
notification,
|
||||||
|
req.uri)
|
||||||
|
res.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods', method='get')
|
||||||
|
def do_get_notification_methods(self, req, res):
|
||||||
|
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
res.body = self._list_notifications(tenant_id, req.uri)
|
||||||
|
res.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='delete')
|
||||||
|
def do_delete_notification_methods(self, req, res, id):
|
||||||
|
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
self._delete_notification(tenant_id, id)
|
||||||
|
res.status = falcon.HTTP_204
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='get')
|
||||||
|
def do_get_notification_method(self, req, res, id):
|
||||||
|
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
res.body = self._list_notification(tenant_id, id, req.uri)
|
||||||
|
res.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
@resource_api.Restify('/v2.0/notification-methods/{id}', method='put')
|
||||||
|
def do_put_notification_methods(self, req, res, id):
|
||||||
|
helpers.validate_json_content_type(req)
|
||||||
|
helpers.validate_authorization(req, self._default_authorized_roles)
|
||||||
|
notification = helpers.read_http_resource(req)
|
||||||
|
self._validate_notification(notification)
|
||||||
|
tenant_id = helpers.get_tenant_id(req)
|
||||||
|
self._update_notification(id, tenant_id, notification)
|
||||||
|
res.body = self._create_notification_response(
|
||||||
|
id,
|
||||||
|
notification,
|
||||||
|
req.uri)
|
||||||
|
res.status = falcon.HTTP_200
|
@ -43,6 +43,9 @@ monasca.events_dispatcher =
|
|||||||
monasca.transforms_dispatcher =
|
monasca.transforms_dispatcher =
|
||||||
v2_reference = monasca.v2.reference.transforms:Transforms
|
v2_reference = monasca.v2.reference.transforms:Transforms
|
||||||
|
|
||||||
|
monasca.notifications_dispatcher =
|
||||||
|
v2_reference = monasca.v2.reference.notifications:Notifications
|
||||||
|
|
||||||
paste.filter_factory =
|
paste.filter_factory =
|
||||||
login = monasca.middleware.login:filter_factory
|
login = monasca.middleware.login:filter_factory
|
||||||
inspector = monasca.middleware.inspector:filter_factory
|
inspector = monasca.middleware.inspector:filter_factory
|
||||||
@ -59,6 +62,7 @@ monasca.repositories =
|
|||||||
influxdb_metrics_repo = monasca.common.repositories.influxdb.metrics_repository:MetricsRepository
|
influxdb_metrics_repo = monasca.common.repositories.influxdb.metrics_repository:MetricsRepository
|
||||||
fake_events_repo = monasca.common.repositories.fake.events_repository:EventsRepository
|
fake_events_repo = monasca.common.repositories.fake.events_repository:EventsRepository
|
||||||
mysql_transforms_repo = monasca.common.repositories.mysql.transforms_repository:TransformsRepository
|
mysql_transforms_repo = monasca.common.repositories.mysql.transforms_repository:TransformsRepository
|
||||||
|
mysql_notifications_repo = monasca.common.repositories.mysql.notifications_repository:NotificationsRepository
|
||||||
|
|
||||||
[pbr]
|
[pbr]
|
||||||
warnerrors = True
|
warnerrors = True
|
||||||
|
Loading…
Reference in New Issue
Block a user