summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--etc/moniker-central.conf.sample8
-rw-r--r--moniker/central/service.py95
-rw-r--r--moniker/exceptions.py12
-rw-r--r--moniker/notification_handler/__init__.py0
-rw-r--r--moniker/notification_handler/base.py51
-rw-r--r--moniker/notification_handler/nova.py136
-rw-r--r--moniker/storage/__init__.py2
-rw-r--r--moniker/storage/base.py4
-rw-r--r--moniker/storage/impl_sqlalchemy/migrate_repo/versions/002_add_managed_col_for_records.py53
-rw-r--r--moniker/storage/impl_sqlalchemy/models.py6
-rw-r--r--moniker/tests/__init__.py34
-rw-r--r--moniker/tests/sample_notifications/nova/compute.instance.create.end.json139
-rw-r--r--moniker/tests/sample_notifications/nova/compute.instance.create.start.json131
-rw-r--r--moniker/tests/sample_notifications/nova/compute.instance.delete.start.json130
-rw-r--r--moniker/tests/sample_notifications/nova/compute.instance.shutdown.end.json130
-rw-r--r--moniker/tests/sample_notifications/nova/compute.instance.shutdown.start.json130
-rw-r--r--moniker/tests/sample_notifications/nova/network.floating_ip.allocate.json102
-rw-r--r--moniker/tests/sample_notifications/nova/network.floating_ip.associate.json102
-rw-r--r--moniker/tests/sample_notifications/nova/network.floating_ip.deallocate.json102
-rw-r--r--moniker/tests/sample_notifications/nova/network.floating_ip.disassociate.json102
-rw-r--r--moniker/tests/sample_notifications/nova/scheduler.run_instance.end.json177
-rw-r--r--moniker/tests/sample_notifications/nova/scheduler.run_instance.scheduled.json182
-rw-r--r--moniker/tests/sample_notifications/nova/scheduler.run_instance.start.json176
-rw-r--r--moniker/tests/test_central/__init__.py4
-rw-r--r--moniker/tests/test_handler/__init__.py49
-rw-r--r--moniker/tests/test_handler/test_nova.py115
-rw-r--r--moniker/tests/test_storage/__init__.py1
-rwxr-xr-xsetup.py4
29 files changed, 2161 insertions, 17 deletions
diff --git a/.gitignore b/.gitignore
index ad65c362..e040954e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ doc/source/api/*
doc/build/*
dist
moniker/versioninfo
+*.orig
diff --git a/etc/moniker-central.conf.sample b/etc/moniker-central.conf.sample
index 945c7600..ddbddf81 100644
--- a/etc/moniker-central.conf.sample
+++ b/etc/moniker-central.conf.sample
@@ -11,9 +11,13 @@ state_path = ./var/
# Database connection string.
database_connection = sqlite://
-#
-notification_driver=moniker.openstack.common.notifier.rabbit_notifier
+# Driver used for issuing notifications
+# notification_driver=moniker.openstack.common.notifier.rabbit_notifier
+
+# List of notification handlers to enable
+#enabled_handlers = nova
# There has to be a better way to set these defaults
allowed_rpc_exception_modules = moniker.exceptions, moniker.openstack.common.exception
logging_context_format_string = %(asctime)s %(levelname)s %(name)s [%(request_id)s %(user)s %(tenant)s] %(instance)s %(message)s
+default_log_levels = amqplib=WARN, sqlalchemy=WARN, boto=WARN, suds=INFO, keystone=INFO, eventlet.wsgi.server=WARN, stevedore=WARN
diff --git a/moniker/central/service.py b/moniker/central/service.py
index 46011b7c..0a5e017d 100644
--- a/moniker/central/service.py
+++ b/moniker/central/service.py
@@ -15,15 +15,22 @@
# under the License.
from moniker.openstack.common import cfg
from moniker.openstack.common import log as logging
+from moniker.openstack.common import rpc
from moniker.openstack.common.rpc import service as rpc_service
+from stevedore.named import NamedExtensionManager
from moniker import storage
from moniker import utils
from moniker import policy
from moniker.agent import api as agent_api
-
LOG = logging.getLogger(__name__)
+HANDLER_NAMESPACE = 'moniker.notification.handler'
+
+cfg.CONF.register_opts([
+ cfg.ListOpt('enabled-handlers', default=[], help='Enabled Handlers'),
+])
+
class Service(rpc_service.Service):
def __init__(self, *args, **kwargs):
@@ -36,8 +43,94 @@ class Service(rpc_service.Service):
super(Service, self).__init__(*args, **kwargs)
+ # Get a storage connection
self.storage_conn = storage.get_connection(cfg.CONF)
+ # Initialize extensions
+ self.handlers = self._init_extensions()
+
+ if self.handlers:
+ # Get a rpc connection if needed
+ self.rpc_conn = rpc.create_connection()
+
+ def _init_extensions(self):
+ """ Loads and prepares all enabled extensions """
+ self.extensions_manager = NamedExtensionManager(
+ HANDLER_NAMESPACE, names=cfg.CONF.enabled_handlers)
+
+ def _load_extension(ext):
+ handler_cls = ext.plugin
+ handler_cls.register_opts(cfg.CONF)
+
+ return handler_cls(central_service=self)
+
+ try:
+ return self.extensions_manager.map(_load_extension)
+ except RuntimeError:
+ # No handlers enabled. No problem.
+ return []
+
+ def start(self):
+ super(Service, self).start()
+
+ if self.handlers:
+ # Setup notification subscriptions and start consuming
+ self._setup_subscriptions()
+ self.rpc_conn.consume_in_thread_group(self.tg)
+
+ def stop(self):
+ if self.handlers:
+ # Try to shut the connection down, but if we get any sort of
+ # errors, go ahead and ignore them.. as we're shutting down anyway
+ try:
+ self.rpc_conn.close()
+ except Exception:
+ pass
+
+ super(Service, self).stop()
+
+ def _setup_subscriptions(self):
+ """
+ Set's up subscriptions for the various exchange+topic combinations that
+ we have a handler for.
+ """
+ for handler in self.handlers:
+ exchange, topics = handler.get_exchange_topics()
+
+ for topic in topics:
+ queue_name = "moniker.notifications.%s.%s" % (exchange, topic)
+
+ self.rpc_conn.declare_topic_consumer(
+ queue_name=queue_name,
+ topic=topic,
+ exchange_name=exchange,
+ callback=self._process_notification)
+
+ def _process_notification(self, notification):
+ """
+ Processes an incoming notification, offering each extension the
+ opportunity to handle it.
+ """
+ event_type = notification.get('event_type')
+
+ LOG.debug('Processing notification: %s' % event_type)
+
+ for handler in self.handlers:
+ self._process_notification_for_handler(handler, notification)
+
+ def _process_notification_for_handler(self, handler, notification):
+ """
+ Processes an incoming notification for a specific handler, checking
+ to see if the handler is interested in the notification before
+ handing it over.
+ """
+ event_type = notification['event_type']
+ payload = notification['payload']
+
+ if event_type in handler.get_event_types():
+ LOG.debug('Found handler for: %s' % event_type)
+ handler.process_notification(event_type, payload)
+
# Server Methods
def create_server(self, context, values):
server = self.storage_conn.create_server(context, values)
diff --git a/moniker/exceptions.py b/moniker/exceptions.py
index ee4a4518..3970e9e9 100644
--- a/moniker/exceptions.py
+++ b/moniker/exceptions.py
@@ -23,19 +23,23 @@ class ConfigNotFound(Base):
pass
-class InvalidObject(Base):
+class ConfigurationError(Base):
pass
-class Forbidden(Base):
+class NoServersConfigured(ConfigurationError):
pass
-class InvalidSortKey(Base):
+class InvalidObject(Base):
pass
-class NoServersConfigured(Base):
+class Forbidden(Base):
+ pass
+
+
+class InvalidSortKey(Base):
pass
diff --git a/moniker/notification_handler/__init__.py b/moniker/notification_handler/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/moniker/notification_handler/__init__.py
diff --git a/moniker/notification_handler/base.py b/moniker/notification_handler/base.py
new file mode 100644
index 00000000..2c1ff859
--- /dev/null
+++ b/moniker/notification_handler/base.py
@@ -0,0 +1,51 @@
+# Copyright 2012 Managed I.T.
+#
+# Author: Kiall Mac Innes <kiall@managedit.ie>
+#
+# 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
+from moniker.openstack.common import log as logging
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Handler(object):
+ """ Base class for notification handlers """
+
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, central_service):
+ LOG.debug('Loaded handler: %s' % __name__)
+ self.central_service = central_service
+
+ @staticmethod
+ def register_opts(conf):
+ pass
+
+ @abc.abstractmethod
+ def get_exchange_topics(self):
+ """
+ Returns a tuple of (exchange, list(topics)) this handler wishes
+ to receive notifications from.
+ """
+
+ @abc.abstractmethod
+ def get_event_types(self):
+ """
+ Returns a list of event types this handler is capable of processing
+ """
+
+ @abc.abstractmethod
+ def process_notification(self, event_type, payload):
+ """ Processes a given notification """
diff --git a/moniker/notification_handler/nova.py b/moniker/notification_handler/nova.py
new file mode 100644
index 00000000..2eaec5ac
--- /dev/null
+++ b/moniker/notification_handler/nova.py
@@ -0,0 +1,136 @@
+# Copyright 2012 Managed I.T.
+#
+# Author: Kiall Mac Innes <kiall@managedit.ie>
+#
+# 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 moniker.openstack.common import cfg
+from moniker.openstack.common import log as logging
+from moniker.openstack.common.context import get_admin_context
+from moniker import exceptions
+from moniker.notification_handler.base import Handler
+
+LOG = logging.getLogger(__name__)
+
+
+class NovaHandler(Handler):
+ """ Hanlder for Nova's notifications """
+
+ def __init__(self, *args, **kwargs):
+ super(NovaHandler, self).__init__(*args, **kwargs)
+
+ self.fixed_ip_domain = cfg.CONF.nova_fixed_ip_domain
+
+ if not self.fixed_ip_domain:
+ msg = ('nova_fixed_ip_domain must be configured to use the nova '
+ 'handler')
+ raise exceptions.ConfigurationError(msg)
+
+ @staticmethod
+ def register_opts(conf):
+ conf.register_opts([
+ cfg.StrOpt('nova-fixed-ip-domain', default=None),
+ cfg.IntOpt('nova-control-exchange', default='nova'),
+ cfg.ListOpt('nova-notification-topics', default=['monitor'])
+ ])
+
+ def get_exchange_topics(self):
+ exchange = cfg.CONF.nova_control_exchange
+
+ topics = [topic + ".info"
+ for topic in cfg.CONF.nova_notification_topics]
+
+ return (exchange, topics)
+
+ def get_event_types(self):
+ return [
+ 'compute.instance.create.end',
+ 'compute.instance.delete.start',
+ # 'compute.instance.rebuild.start', # Needed?
+ # 'compute.instance.rebuild.end', # Needed?
+ # 'compute.instance.exists', # Needed?
+ # 'network.floating_ip.allocate', # Needed?
+ # 'network.floating_ip.deallocate', # Needed?
+ 'network.floating_ip.associate',
+ 'network.floating_ip.disassociate',
+ ]
+
+ def process_notification(self, event_type, payload):
+ LOG.debug('NovaHandler recieved notification - %s' % event_type)
+
+ if event_type == 'compute.instance.create.end':
+ return self.handle_instance_create(payload)
+
+ elif event_type == 'compute.instance.delete.start':
+ return self.handle_instance_delete(payload)
+
+ elif event_type == 'network.floating_ip.associate':
+ return self.handle_floating_ip_associate(payload)
+
+ elif event_type == 'network.floating_ip.disassociate':
+ return self.handle_floating_ip_disassociate(payload)
+
+ else:
+ raise ValueError('NovaHandler recieved an invalid event type')
+
+ def handle_instance_create(self, payload):
+ context = get_admin_context()
+
+ # Fetch the FixedIP Domain
+ fixed_ip_domain = self.central_service.get_domain(context,
+ self.fixed_ip_domain)
+
+ # For each fixed ip, create an associated record.
+ for fixed_ip in payload['fixed_ips']:
+ record_name = '%(instance_id)s.%(tenant_id)s.%(domain)s' % dict(
+ instance_id=payload['instance_id'],
+ tenant_id=payload['tenant_id'],
+ domain=fixed_ip_domain['name'])
+
+ record_values = {
+ 'type': 'A' if fixed_ip['version'] == 4 else 'AAAA',
+ 'name': record_name,
+ 'data': fixed_ip['address'],
+
+ 'managed_resource': True,
+ 'managed_resource_type': u'instance',
+ 'managed_resource_id': payload['instance_id'],
+ }
+
+ self.central_service.create_record(context, self.fixed_ip_domain,
+ record_values)
+
+ def handle_instance_delete(self, payload):
+ context = get_admin_context()
+
+ # Fetch the instances managed records
+ criterion = {
+ 'managed_resource': True,
+ 'managed_resource_type': u'instance',
+ 'managed_resource_id': payload['instance_id']
+ }
+
+ records = self.central_service.get_records(context,
+ self.fixed_ip_domain,
+ criterion)
+ # Delete the matching records
+ for record in records:
+ LOG.debug('Deleting record %s' % record['id'])
+
+ self.central_service.delete_record(context, self.fixed_ip_domain,
+ record['id'])
+
+ def handle_floating_ip_associate(self, payload):
+ pass
+
+ def handle_floating_ip_disassociate(self, payload):
+ pass
diff --git a/moniker/storage/__init__.py b/moniker/storage/__init__.py
index a0afb094..63c87e7c 100644
--- a/moniker/storage/__init__.py
+++ b/moniker/storage/__init__.py
@@ -44,7 +44,7 @@ def get_engine_name(string):
def get_engine(conf):
scheme = urlparse(conf.database_connection).scheme
engine_name = get_engine_name(scheme)
- LOG.debug('looking for %r engine in %r', engine_name, DRIVER_NAMESPACE)
+ LOG.debug('Looking for %r engine in %r', engine_name, DRIVER_NAMESPACE)
mgr = driver.DriverManager(
DRIVER_NAMESPACE,
engine_name,
diff --git a/moniker/storage/base.py b/moniker/storage/base.py
index ea37dcb5..f75c91ce 100644
--- a/moniker/storage/base.py
+++ b/moniker/storage/base.py
@@ -17,9 +17,7 @@ import abc
class StorageEngine(object):
- """
- Base class for storage engines
- """
+ """ Base class for storage engines """
__metaclass__ = abc.ABCMeta
diff --git a/moniker/storage/impl_sqlalchemy/migrate_repo/versions/002_add_managed_col_for_records.py b/moniker/storage/impl_sqlalchemy/migrate_repo/versions/002_add_managed_col_for_records.py
new file mode 100644
index 00000000..81fa85c1
--- /dev/null
+++ b/moniker/storage/impl_sqlalchemy/migrate_repo/versions/002_add_managed_col_for_records.py
@@ -0,0 +1,53 @@
+# Copyright 2012 Managed I.T.
+#
+# Author: Kiall Mac Innes <kiall@managedit.ie>
+#
+# 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 sqlalchemy import MetaData, Table, Column, Boolean
+from moniker.storage.impl_sqlalchemy.types import UUID
+
+meta = MetaData()
+
+
+def upgrade(migrate_engine):
+ meta.bind = migrate_engine
+
+ records_table = Table('records', meta, autoload=True)
+
+ managed_resource = Column('managed_resource', Boolean(), default=False)
+ managed_resource.create(records_table, populate_default=True)
+
+ managed_resource_type = Column('managed_resource_type', UUID(),
+ default=None, nullable=True)
+ managed_resource_type.create(records_table, populate_default=True)
+
+ managed_resource_id = Column('managed_resource_id', UUID(), default=None,
+ nullable=True)
+ managed_resource_id.create(records_table, populate_default=True)
+
+
+def downgrade(migrate_engine):
+ meta.bind = migrate_engine
+
+ records_table = Table('records', meta, autoload=True)
+
+ managed_resource_id = Column('managed_resource_id', UUID(), default=None,
+ nullable=True)
+ managed_resource_id.drop(records_table)
+
+ managed_resource_type = Column('managed_resource_type', UUID(),
+ default=None, nullable=True)
+ managed_resource_type.drop(records_table)
+
+ managed_resource = Column('managed_resource', Boolean(), default=False)
+ managed_resource.drop(records_table)
diff --git a/moniker/storage/impl_sqlalchemy/models.py b/moniker/storage/impl_sqlalchemy/models.py
index ba2b8836..cdc86a22 100644
--- a/moniker/storage/impl_sqlalchemy/models.py
+++ b/moniker/storage/impl_sqlalchemy/models.py
@@ -18,7 +18,7 @@
from uuid import uuid4
from urlparse import urlparse
from sqlalchemy import (Column, DateTime, String, Text, Integer, ForeignKey,
- Enum)
+ Enum, Boolean, Unicode)
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import relationship, backref, object_mapper
from sqlalchemy.ext.declarative import declarative_base
@@ -176,6 +176,10 @@ class Record(Base):
priority = Column(Integer, default=None)
ttl = Column(Integer, default=3600, nullable=False)
+ managed_resource = Column(Boolean, default=False)
+ managed_resource_type = Column(Unicode(50), default=None, nullable=True)
+ managed_resource_id = Column(UUID, default=None, nullable=True)
+
domain_id = Column(UUID, ForeignKey('domains.id'), nullable=False)
@hybrid_property
diff --git a/moniker/tests/__init__.py b/moniker/tests/__init__.py
index 06f78e8b..da249d4a 100644
--- a/moniker/tests/__init__.py
+++ b/moniker/tests/__init__.py
@@ -20,6 +20,7 @@ from moniker.openstack.common import cfg
from moniker.openstack.common import log as logging
from moniker.openstack.common.context import RequestContext, get_admin_context
from moniker import storage
+from moniker.central import service as central_service
LOG = logging.getLogger(__name__)
@@ -34,6 +35,8 @@ class TestCase(unittest.TestCase):
notification_driver=[])
storage.setup_schema()
+ self.admin_context = self.get_admin_context()
+
def tearDown(self):
storage.teardown_schema()
cfg.CONF.reset()
@@ -46,6 +49,9 @@ class TestCase(unittest.TestCase):
for k, v in kwargs.iteritems():
cfg.CONF.set_override(k, v, group)
+ def get_central_service(self):
+ return central_service.Service()
+
def get_context(self, **kwargs):
return RequestContext(**kwargs)
@@ -67,6 +73,34 @@ if sys.version_info < (2, 7):
TestCase.assertIsNotNone = assertIsNotNone
+ def assertIn(self, test_value, expected_set):
+ msg = "%s did not occur in %s" % (test_value, expected_set)
+ self.assert_(test_value in expected_set, msg)
+
+ TestCase.assertIn = assertIn
+
+ def assertNotIn(self, test_value, expected_set):
+ msg = "%s occurred in %s" % (test_value, expected_set)
+ self.assert_(test_value not in expected_set, msg)
+
+ TestCase.assertNotIn = assertNotIn
+
+ def assertGreaterEqual(self, a, b, msg=None):
+ if not msg:
+ msg = '%r not greater than or equal to %r' % (a, b)
+
+ self.assert_(a >= b, msg)
+
+ TestCase.assertGreaterEqual = assertGreaterEqual
+
+ def assertLessEqual(self, a, b, msg=None):
+ if not msg:
+ msg = '%r not less than or equal to %r' % (a, b)
+
+ self.assert_(a <= b, msg)
+
+ TestCase.assertLessEqual = assertLessEqual
+
def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
@contextmanager
def context():
diff --git a/moniker/tests/sample_notifications/nova/compute.instance.create.end.json b/moniker/tests/sample_notifications/nova/compute.instance.create.end.json
new file mode 100644
index 00000000..f94d5708
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/compute.instance.create.end.json
@@ -0,0 +1,139 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-5bef6a23-2e14-4b3f-9eb1-1be293b75fb7",
+ "_context_quota_class": null,
+ "event_type": "compute.instance.create.end",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 17:54:48.797009",
+ "_context_is_admin": true,
+ "message_id": "af100d58-7a9c-41a1-9311-8c52b44ca294",
+ "_context_auth_token": "d7f4118a789f47b8ab708a00f239268f",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T17:54:27.320555",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "compute.stack01",
+ "payload": {
+ "state_description": "",
+ "availability_zone": null,
+ "ramdisk_id": "",
+ "instance_type_id": 2,
+ "deleted_at": "",
+ "fixed_ips": [{
+ "floating_ips": [],
+ "label": "private",
+ "version": 4,
+ "meta": {},
+ "address": "172.16.0.14",
+ "type": "fixed"
+ }],
+ "memory_mb": 512,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "reservation_id": "r-1ekblkfw",
+ "state": "active",
+ "launched_at": "2012-11-03 17:54:48.514631",
+ "metadata": [],
+ "ephemeral_gb": 0,
+ "access_ip_v6": null,
+ "disk_gb": 0,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "image_name": "ubuntu-precise",
+ "host": "stack01",
+ "display_name": "TestInstance",
+ "image_ref_url": "http://192.0.2.98:9292/images/e52f1321-fb9e-40fb-8057-555a850462e8",
+ "root_gb": 0,
+ "tenant_id": "33a88272e06a49c1a0f653abc374b56b",
+ "created_at": "2012-11-03 17:54:27",
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "instance_type": "m1.tiny",
+ "vcpus": 1,
+ "image_meta": {
+ "base_image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8"
+ },
+ "architecture": null,
+ "os_type": null
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/compute.instance.create.start.json b/moniker/tests/sample_notifications/nova/compute.instance.create.start.json
new file mode 100644
index 00000000..addb75a1
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/compute.instance.create.start.json
@@ -0,0 +1,131 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-5bef6a23-2e14-4b3f-9eb1-1be293b75fb7",
+ "_context_quota_class": null,
+ "event_type": "compute.instance.create.start",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 17:54:30.227605",
+ "_context_is_admin": true,
+ "message_id": "3f471852-2d65-41c5-b4c7-18de76bdce1f",
+ "_context_auth_token": "d7f4118a789f47b8ab708a00f239268f",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T17:54:27.320555",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "compute.stack01",
+ "payload": {
+ "state_description": "scheduling",
+ "availability_zone": null,
+ "ramdisk_id": "",
+ "instance_type_id": 2,
+ "deleted_at": "",
+ "reservation_id": "r-1ekblkfw",
+ "memory_mb": 512,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "state": "building",
+ "launched_at": "",
+ "metadata": [],
+ "ephemeral_gb": 0,
+ "access_ip_v6": null,
+ "disk_gb": 0,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "image_name": "ubuntu-precise",
+ "host": "stack01",
+ "display_name": "TestInstance",
+ "image_ref_url": "http://192.0.2.98:9292/images/e52f1321-fb9e-40fb-8057-555a850462e8",
+ "root_gb": 0,
+ "tenant_id": "33a88272e06a49c1a0f653abc374b56b",
+ "created_at": "2012-11-03T17:54:27.000000",
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "instance_type": "m1.tiny",
+ "vcpus": 1,
+ "image_meta": {
+ "base_image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8"
+ },
+ "architecture": null,
+ "os_type": null
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/compute.instance.delete.start.json b/moniker/tests/sample_notifications/nova/compute.instance.delete.start.json
new file mode 100644
index 00000000..59487162
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/compute.instance.delete.start.json
@@ -0,0 +1,130 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-951e8b61-6681-4581-8321-02cece4a1830",
+ "_context_quota_class": null,
+ "event_type": "compute.instance.delete.start",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:59.882973",
+ "_context_is_admin": false,
+ "message_id": "bc6841d3-73fc-4f17-aede-20802b9e388d",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:59.435020",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "compute.stack01",
+ "payload": {
+ "state_description": "",
+ "availability_zone": null,
+ "ramdisk_id": "",
+ "instance_type_id": 2,
+ "deleted_at": "",
+ "reservation_id": "r-1ekblkfw",
+ "memory_mb": 512,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "state": "active",
+ "launched_at": "2012-11-03T17:54:48.000000",
+ "metadata": [],
+ "ephemeral_gb": 0,
+ "access_ip_v6": null,
+ "disk_gb": 0,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "host": "stack01",
+ "display_name": "TestInstance",
+ "image_ref_url": "http://192.0.2.98:9292/images/e52f1321-fb9e-40fb-8057-555a850462e8",
+ "root_gb": 0,
+ "tenant_id": "33a88272e06a49c1a0f653abc374b56b",
+ "created_at": "2012-11-03T17:54:27.000000",
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "instance_type": "m1.tiny",
+ "vcpus": 1,
+ "image_meta": {
+ "base_image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8"
+ },
+ "architecture": null,
+ "os_type": null
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/compute.instance.shutdown.end.json b/moniker/tests/sample_notifications/nova/compute.instance.shutdown.end.json
new file mode 100644
index 00000000..92727a5f
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/compute.instance.shutdown.end.json
@@ -0,0 +1,130 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-951e8b61-6681-4581-8321-02cece4a1830",
+ "_context_quota_class": null,
+ "event_type": "compute.instance.shutdown.end",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "9d4044f4601145eebb60fe0446d640ab",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8",
+ "internalURL": "http://s3",
+ "publicURL": "http://s3"
+ }],
+ "endpoints_links": [],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a",
+ "internalURL": "http://image:9292/v1",
+ "publicURL": "http://image/v1"
+ }],
+ "endpoints_links": [],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "8e9b87c7e3a94697b8656ab845c74017",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839",
+ "internalURL": "http://ec2/services/Cloud",
+ "publicURL": "http://ec2/services/Cloud"
+ }],
+ "endpoints_links": [],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "id": "6dc68974176140c5b1eacd4329e94ae2",
+ "internalURL": "http://dns/v1.0",
+ "publicURL": "http://dns/v1.0"
+ }],
+ "endpoints_links": [],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd",
+ "internalURL": "http://identity/v2.0",
+ "publicURL": "http://identity/v2.0"
+ }],
+ "endpoints_links": [],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:02:13.060229",
+ "_context_is_admin": true,
+ "message_id": "22c404f7-dd2a-492e-bce0-e63631672171",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:59.435020",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "compute.stack01",
+ "payload": {
+ "state_description": "",
+ "availability_zone": null,
+ "ramdisk_id": "",
+ "instance_type_id": 2,
+ "deleted_at": "",
+ "reservation_id": "r-1ekblkfw",
+ "memory_mb": 512,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "state": "active",
+ "launched_at": "2012-11-03T17:54:48.000000",
+ "metadata": [],
+ "ephemeral_gb": 0,
+ "access_ip_v6": null,
+ "disk_gb": 0,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "host": "stack01",
+ "display_name": "TestInstance",
+ "image_ref_url": "http://192.0.2.98:9292/images/e52f1321-fb9e-40fb-8057-555a850462e8",
+ "root_gb": 0,
+ "tenant_id": "33a88272e06a49c1a0f653abc374b56b",
+ "created_at": "2012-11-03T17:54:27.000000",
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "instance_type": "m1.tiny",
+ "vcpus": 1,
+ "image_meta": {
+ "base_image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8"
+ },
+ "architecture": null,
+ "os_type": null
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/compute.instance.shutdown.start.json b/moniker/tests/sample_notifications/nova/compute.instance.shutdown.start.json
new file mode 100644
index 00000000..889d36f7
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/compute.instance.shutdown.start.json
@@ -0,0 +1,130 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-951e8b61-6681-4581-8321-02cece4a1830",
+ "_context_quota_class": null,
+ "event_type": "compute.instance.shutdown.start",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "9d4044f4601145eebb60fe0446d640ab",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8",
+ "internalURL": "http://s3",
+ "publicURL": "http://s3"
+ }],
+ "endpoints_links": [],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a",
+ "internalURL": "http://image:9292/v1",
+ "publicURL": "http://image/v1"
+ }],
+ "endpoints_links": [],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "8e9b87c7e3a94697b8656ab845c74017",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839",
+ "internalURL": "http://ec2/services/Cloud",
+ "publicURL": "http://ec2/services/Cloud"
+ }],
+ "endpoints_links": [],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "id": "6dc68974176140c5b1eacd4329e94ae2",
+ "internalURL": "http://dns/v1.0",
+ "publicURL": "http://dns/v1.0"
+ }],
+ "endpoints_links": [],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd",
+ "internalURL": "http://identity/v2.0",
+ "publicURL": "http://identity/v2.0"
+ }],
+ "endpoints_links": [],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:59.908205",
+ "_context_is_admin": true,
+ "message_id": "51033f41-e0ae-4d2b-b701-697357db5ee9",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:59.435020",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "compute.stack01",
+ "payload": {
+ "state_description": "",
+ "availability_zone": null,
+ "ramdisk_id": "",
+ "instance_type_id": 2,
+ "deleted_at": "",
+ "reservation_id": "r-1ekblkfw",
+ "memory_mb": 512,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "state": "active",
+ "launched_at": "2012-11-03T17:54:48.000000",
+ "metadata": [],
+ "ephemeral_gb": 0,
+ "access_ip_v6": null,
+ "disk_gb": 0,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "host": "stack01",
+ "display_name": "TestInstance",
+ "image_ref_url": "http://192.0.2.98:9292/images/e52f1321-fb9e-40fb-8057-555a850462e8",
+ "root_gb": 0,
+ "tenant_id": "33a88272e06a49c1a0f653abc374b56b",
+ "created_at": "2012-11-03T17:54:27.000000",
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "instance_type": "m1.tiny",
+ "vcpus": 1,
+ "image_meta": {
+ "base_image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8"
+ },
+ "architecture": null,
+ "os_type": null
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/network.floating_ip.allocate.json b/moniker/tests/sample_notifications/nova/network.floating_ip.allocate.json
new file mode 100644
index 00000000..2db8fe02
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/network.floating_ip.allocate.json
@@ -0,0 +1,102 @@
+{
+ "_context_roles": ["Member"],
+ "_context_request_id": "req-310065bf-21ba-48e9-8838-f97421271021",
+ "_context_quota_class": null,
+ "event_type": "network.floating_ip.allocate",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:15.814992",
+ "_context_is_admin": false,
+ "message_id": "7cbbe178-16ce-4d97-b98a-f56e44ccbeac",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:15.615906",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "network.stack01",
+ "payload": {
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "floating_ip": "192.0.2.125"
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/network.floating_ip.associate.json b/moniker/tests/sample_notifications/nova/network.floating_ip.associate.json
new file mode 100644
index 00000000..1baf8ae9
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/network.floating_ip.associate.json
@@ -0,0 +1,102 @@
+{
+ "_context_roles": ["Member"],
+ "_context_request_id": "req-937d1d76-a101-4853-81f3-a54d1daa982d",
+ "_context_quota_class": null,
+ "event_type": "network.floating_ip.associate",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:33.344797",
+ "_context_is_admin": false,
+ "message_id": "40266f53-0db8-4000-b531-77188adf4408",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:30.414284",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "network.stack01",
+ "payload": {
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "floating_ip": "192.0.2.125"
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/network.floating_ip.deallocate.json b/moniker/tests/sample_notifications/nova/network.floating_ip.deallocate.json
new file mode 100644
index 00000000..9d886e61
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/network.floating_ip.deallocate.json
@@ -0,0 +1,102 @@
+{
+ "_context_roles": ["Member"],
+ "_context_request_id": "req-8d785ddf-7e46-44ec-a4ca-d83a2c832681",
+ "_context_quota_class": null,
+ "event_type": "network.floating_ip.deallocate",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:49.724982",
+ "_context_is_admin": false,
+ "message_id": "3113801a-bf55-4b4f-bb54-0a4c41ca5016",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:49.584191",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "network.stack01",
+ "payload": {
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "floating_ip": "192.0.2.125"
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/network.floating_ip.disassociate.json b/moniker/tests/sample_notifications/nova/network.floating_ip.disassociate.json
new file mode 100644
index 00000000..d2dd0c03
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/network.floating_ip.disassociate.json
@@ -0,0 +1,102 @@
+{
+ "_context_roles": ["Member"],
+ "_context_request_id": "req-0cc687fc-21b2-41fc-a015-dd0889438a5b",
+ "_context_quota_class": null,
+ "event_type": "network.floating_ip.disassociate",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 18:01:42.411369",
+ "_context_is_admin": false,
+ "message_id": "5945fc5c-4d0c-4bfe-86e8-0311f61612f3",
+ "_context_auth_token": "9b044204adf647c2a5f3e8cf030ecf62",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T18:01:41.229276",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "network.stack01",
+ "payload": {
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "floating_ip": "192.0.2.125"
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/scheduler.run_instance.end.json b/moniker/tests/sample_notifications/nova/scheduler.run_instance.end.json
new file mode 100644
index 00000000..fcb151d7
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/scheduler.run_instance.end.json
@@ -0,0 +1,177 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-5bef6a23-2e14-4b3f-9eb1-1be293b75fb7",
+ "_context_quota_class": null,
+ "event_type": "scheduler.run_instance.end",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 17:54:28.466477",
+ "_context_is_admin": false,
+ "message_id": "ca39e28e-d8f2-472b-9841-52ac70e368da",
+ "_context_auth_token": "d7f4118a789f47b8ab708a00f239268f",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T17:54:27.320555",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "scheduler.stack01",
+ "payload": {
+ "request_spec": {
+ "block_device_mapping": [],
+ "image": {
+ "status": "active",
+ "name": "ubuntu-precise",
+ "deleted": false,
+ "container_format": "bare",
+ "created_at": "2012-08-23T20:51:48.000000",
+ "disk_format": "qcow2",
+ "updated_at": "2012-09-01T21:14:09.000000",
+ "id": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "owner": "7964afa81aeb40b0aa0191469f33acb2",
+ "min_ram": 0,
+ "checksum": "28c510b1e49a65d638cfb469754a93d3",
+ "min_disk": 0,
+ "is_public": true,
+ "deleted_at": null,
+ "properties": {},
+ "size": 233177088
+ },
+ "instance_type": {
+ "disabled": false,
+ "root_gb": 0,
+ "name": "m1.tiny",
+ "flavorid": "1",
+ "deleted": false,
+ "created_at": null,
+ "ephemeral_gb": 0,
+ "updated_at": null,
+ "memory_mb": 512,
+ "vcpus": 1,
+ "extra_specs": {},
+ "swap": 0,
+ "rxtx_factor": 1.0,
+ "is_public": true,
+ "deleted_at": null,
+ "vcpu_weight": null,
+ "id": 2
+ },
+ "instance_properties": {
+ "vm_state": "building",
+ "availability_zone": null,
+ "launch_index": 0,
+ "ephemeral_gb": 0,
+ "instance_type_id": 2,
+ "user_data": null,
+ "vm_mode": null,
+ "reservation_id": "r-1ekblkfw",
+ "root_device_name": null,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "display_description": "TestInstance",
+ "key_data": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAl5eTgQ1IMCr9pFPiR1ZdpnNagRqmfCgqhSsUOb7E6w6anzc/K4Xj9wy5gxvrrG7hVqI7iNQ+Yddfcc4QXfMkUO9CPWUBC2bXs21Sy5nPnGyveJIro+LbBkf+FPyN/WL95O8ymJ/7V0Suo+XSTO25wu4LLe2t33QNtZpPYthD0amHGuVhbL97ie7dwA9iZQfGsGIgrd10+uGYNKlb+NwEF9i+w6t4tGjyjuE4cxo2E+/KmiwNShOXQ7eq4a0qf7kmz6ZIZEBo8Gut0OcmzL8bb4PxVbQsL1IqwkbNa4oN+w7+TLVbdmGxqYO0tgVz2FadgXEnX3jlzPWYyDTk2bbI/w== user-name@wk01-lmst.managedit.ie",
+ "power_state": 0,
+ "progress": 0,
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "config_drive": "",
+ "ramdisk_id": "",
+ "access_ip_v6": null,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "key_name": "user-name",
+ "display_name": "TestInstance",
+ "config_drive_id": "",
+ "root_gb": 0,
+ "locked": false,
+ "launch_time": "2012-11-03T17:54:27Z",
+ "memory_mb": 512,
+ "vcpus": 1,
+ "image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "architecture": null,
+ "auto_disk_config": null,
+ "os_type": null,
+ "metadata": {}
+ },
+ "security_group": ["default"],
+ "instance_uuids": ["3e301a55-fbbe-478d-92d0-eefabf135c38"]
+ }
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/scheduler.run_instance.scheduled.json b/moniker/tests/sample_notifications/nova/scheduler.run_instance.scheduled.json
new file mode 100644
index 00000000..d5337dd3
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/scheduler.run_instance.scheduled.json
@@ -0,0 +1,182 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-5bef6a23-2e14-4b3f-9eb1-1be293b75fb7",
+ "_context_quota_class": null,
+ "event_type": "scheduler.run_instance.scheduled",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "9d4044f4601145eebb60fe0446d640ab",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8",
+ "internalURL": "http://s3",
+ "publicURL": "http://s3"
+ }],
+ "endpoints_links": [],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a",
+ "internalURL": "http://image:9292/v1",
+ "publicURL": "http://image/v1"
+ }],
+ "endpoints_links": [],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "id": "8e9b87c7e3a94697b8656ab845c74017",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b"
+ }],
+ "endpoints_links": [],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839",
+ "internalURL": "http://ec2/services/Cloud",
+ "publicURL": "http://ec2/services/Cloud"
+ }],
+ "endpoints_links": [],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "id": "6dc68974176140c5b1eacd4329e94ae2",
+ "internalURL": "http://dns/v1.0",
+ "publicURL": "http://dns/v1.0"
+ }],
+ "endpoints_links": [],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd",
+ "internalURL": "http://identity/v2.0",
+ "publicURL": "http://identity/v2.0"
+ }],
+ "endpoints_links": [],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 17:54:28.223787",
+ "_context_is_admin": true,
+ "message_id": "7197db7d-a96f-44c7-9b60-abc27b8b47c1",
+ "_context_auth_token": "d7f4118a789f47b8ab708a00f239268f",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T17:54:27.320555",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "scheduler.stack01",
+ "payload": {
+ "instance_id": "3e301a55-fbbe-478d-92d0-eefabf135c38",
+ "weighted_host": {
+ "host": "stack01",
+ "weight": -12847.0
+ },
+ "request_spec": {
+ "block_device_mapping": [],
+ "image": {
+ "status": "active",
+ "name": "ubuntu-precise",
+ "deleted": false,
+ "container_format": "bare",
+ "created_at": "2012-08-23T20:51:48.000000",
+ "disk_format": "qcow2",
+ "updated_at": "2012-09-01T21:14:09.000000",
+ "id": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "owner": "7964afa81aeb40b0aa0191469f33acb2",
+ "min_ram": 0,
+ "checksum": "28c510b1e49a65d638cfb469754a93d3",
+ "min_disk": 0,
+ "is_public": true,
+ "deleted_at": null,
+ "properties": {},
+ "size": 233177088
+ },
+ "instance_type": {
+ "disabled": false,
+ "root_gb": 0,
+ "name": "m1.tiny",
+ "flavorid": "1",
+ "deleted": false,
+ "created_at": null,
+ "ephemeral_gb": 0,
+ "updated_at": null,
+ "memory_mb": 512,
+ "vcpus": 1,
+ "extra_specs": {},
+ "swap": 0,
+ "rxtx_factor": 1.0,
+ "is_public": true,
+ "deleted_at": null,
+ "vcpu_weight": null,
+ "id": 2
+ },
+ "instance_properties": {
+ "vm_state": "building",
+ "availability_zone": null,
+ "launch_index": 0,
+ "ephemeral_gb": 0,
+ "instance_type_id": 2,
+ "user_data": null,
+ "vm_mode": null,
+ "reservation_id": "r-1ekblkfw",
+ "root_device_name": null,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "display_description": "TestInstance",
+ "key_data": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAl5eTgQ1IMCr9pFPiR1ZdpnNagRqmfCgqhSsUOb7E6w6anzc/K4Xj9wy5gxvrrG7hVqI7iNQ+Yddfcc4QXfMkUO9CPWUBC2bXs21Sy5nPnGyveJIro+LbBkf+FPyN/WL95O8ymJ/7V0Suo+XSTO25wu4LLe2t33QNtZpPYthD0amHGuVhbL97ie7dwA9iZQfGsGIgrd10+uGYNKlb+NwEF9i+w6t4tGjyjuE4cxo2E+/KmiwNShOXQ7eq4a0qf7kmz6ZIZEBo8Gut0OcmzL8bb4PxVbQsL1IqwkbNa4oN+w7+TLVbdmGxqYO0tgVz2FadgXEnX3jlzPWYyDTk2bbI/w== user-name@wk01-lmst.managedit.ie",
+ "power_state": 0,
+ "progress": 0,
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "config_drive": "",
+ "ramdisk_id": "",
+ "access_ip_v6": null,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "key_name": "user-name",
+ "display_name": "TestInstance",
+ "config_drive_id": "",
+ "root_gb": 0,
+ "locked": false,
+ "launch_time": "2012-11-03T17:54:27Z",
+ "memory_mb": 512,
+ "vcpus": 1,
+ "image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "architecture": null,
+ "auto_disk_config": null,
+ "os_type": null,
+ "metadata": {}
+ },
+ "security_group": ["default"],
+ "instance_uuids": ["3e301a55-fbbe-478d-92d0-eefabf135c38"]
+ }
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/sample_notifications/nova/scheduler.run_instance.start.json b/moniker/tests/sample_notifications/nova/scheduler.run_instance.start.json
new file mode 100644
index 00000000..bd3ff117
--- /dev/null
+++ b/moniker/tests/sample_notifications/nova/scheduler.run_instance.start.json
@@ -0,0 +1,176 @@
+{
+ "_context_roles": ["Member", "admin"],
+ "_context_request_id": "req-5bef6a23-2e14-4b3f-9eb1-1be293b75fb7",
+ "_context_quota_class": null,
+ "event_type": "scheduler.run_instance.start",
+ "_context_user_name": "user-name",
+ "_context_project_name": "tenant-name",
+ "_context_service_catalog": [{
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://compute/v2/33a88272e06a49c1a0f653abc374b56b",
+ "id": "9d4044f4601145eebb60fe0446d640ab"
+ }],
+ "type": "compute",
+ "name": "nova"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://s3",
+ "region": "dub01",
+ "publicURL": "http://s3",
+ "internalURL": "http://s3",
+ "id": "97e22c600c7141ac916a9be13d8ffbb8"
+ }],
+ "type": "s3",
+ "name": "s3"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://image:9292/v1",
+ "region": "dub01",
+ "publicURL": "http://image/v1",
+ "internalURL": "http://image:9292/v1",
+ "id": "c5b95f59ccb841e293dfdcafcaaf0a4a"
+ }],
+ "type": "image",
+ "name": "glance"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "region": "dub01",
+ "publicURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "internalURL": "http://volume/v1/33a88272e06a49c1a0f653abc374b56b",
+ "id": "8e9b87c7e3a94697b8656ab845c74017"
+ }],
+ "type": "volume",
+ "name": "cinder"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://ec2/services/Admin",
+ "region": "dub01",
+ "publicURL": "http://ec2/services/Cloud",
+ "internalURL": "http://ec2/services/Cloud",
+ "id": "e465f3ed91534fe3a3a457f9ff90d839"
+ }],
+ "type": "ec2",
+ "name": "ec2"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://dns/v1.0",
+ "region": "dub01",
+ "publicURL": "http://dns/v1.0",
+ "internalURL": "http://dns/v1.0",
+ "id": "6dc68974176140c5b1eacd4329e94ae2"
+ }],
+ "type": "dns",
+ "name": "moniker"
+ }, {
+ "endpoints_links": [],
+ "endpoints": [{
+ "adminURL": "http://identity:35357/v2.0",
+ "region": "dub01",
+ "publicURL": "http://identity/v2.0",
+ "internalURL": "http://identity/v2.0",
+ "id": "4034b8fb88df41e2abd7b3056fc908fd"
+ }],
+ "type": "identity",
+ "name": "keystone"
+ }],
+ "timestamp": "2012-11-03 17:54:28.174160",
+ "_context_is_admin": false,
+ "message_id": "441bc776-6bd7-420f-b566-0f18f06b6122",
+ "_context_auth_token": "d7f4118a789f47b8ab708a00f239268f",
+ "_context_instance_lock_checked": false,
+ "_context_project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "_context_timestamp": "2012-11-03T17:54:27.320555",
+ "_context_read_deleted": "no",
+ "_context_user_id": "953f8394fa044302b7d42f47228e427d",
+ "_context_remote_address": "127.0.0.1",
+ "publisher_id": "scheduler.stack01",
+ "payload": {
+ "request_spec": {
+ "block_device_mapping": [],
+ "image": {
+ "status": "active",
+ "name": "ubuntu-precise",
+ "deleted": false,
+ "container_format": "bare",
+ "created_at": "2012-08-23T20:51:48.000000",
+ "disk_format": "qcow2",
+ "updated_at": "2012-09-01T21:14:09.000000",
+ "id": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "owner": "7964afa81aeb40b0aa0191469f33acb2",
+ "min_ram": 0,
+ "checksum": "28c510b1e49a65d638cfb469754a93d3",
+ "min_disk": 0,
+ "is_public": true,
+ "deleted_at": null,
+ "properties": {},
+ "size": 233177088
+ },
+ "instance_type": {
+ "disabled": false,
+ "root_gb": 0,
+ "name": "m1.tiny",
+ "flavorid": "1",
+ "deleted": false,
+ "created_at": null,
+ "ephemeral_gb": 0,
+ "updated_at": null,
+ "memory_mb": 512,
+ "vcpus": 1,
+ "extra_specs": {},
+ "swap": 0,
+ "rxtx_factor": 1.0,
+ "is_public": true,
+ "deleted_at": null,
+ "vcpu_weight": null,
+ "id": 2
+ },
+ "instance_properties": {
+ "vm_state": "building",
+ "availability_zone": null,
+ "ephemeral_gb": 0,
+ "instance_type_id": 2,
+ "user_data": null,
+ "vm_mode": null,
+ "reservation_id": "r-1ekblkfw",
+ "root_device_name": null,
+ "user_id": "953f8394fa044302b7d42f47228e427d",
+ "display_description": "TestInstance",
+ "key_data": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAl5eTgQ1IMCr9pFPiR1ZdpnNagRqmfCgqhSsUOb7E6w6anzc/K4Xj9wy5gxvrrG7hVqI7iNQ+Yddfcc4QXfMkUO9CPWUBC2bXs21Sy5nPnGyveJIro+LbBkf+FPyN/WL95O8ymJ/7V0Suo+XSTO25wu4LLe2t33QNtZpPYthD0amHGuVhbL97ie7dwA9iZQfGsGIgrd10+uGYNKlb+NwEF9i+w6t4tGjyjuE4cxo2E+/KmiwNShOXQ7eq4a0qf7kmz6ZIZEBo8Gut0OcmzL8bb4PxVbQsL1IqwkbNa4oN+w7+TLVbdmGxqYO0tgVz2FadgXEnX3jlzPWYyDTk2bbI/w== user-name@wk01-lmst.managedit.ie",
+ "power_state": 0,
+ "progress": 0,
+ "project_id": "33a88272e06a49c1a0f653abc374b56b",
+ "config_drive": "",
+ "ramdisk_id": "",
+ "access_ip_v6": null,
+ "access_ip_v4": null,
+ "kernel_id": "",
+ "key_name": "user-name",
+ "display_name": "TestInstance",
+ "config_drive_id": "",
+ "root_gb": 0,
+ "locked": false,
+ "launch_time": "2012-11-03T17:54:27Z",
+ "memory_mb": 512,
+ "vcpus": 1,
+ "image_ref": "e52f1321-fb9e-40fb-8057-555a850462e8",
+ "architecture": null,
+ "auto_disk_config": null,
+ "os_type": null,
+ "metadata": {}
+ },
+ "security_group": ["default"],
+ "instance_uuids": ["3e301a55-fbbe-478d-92d0-eefabf135c38"]
+ }
+ },
+ "priority": "INFO"
+}
diff --git a/moniker/tests/test_central/__init__.py b/moniker/tests/test_central/__init__.py
index d46e91e6..2d464616 100644
--- a/moniker/tests/test_central/__init__.py
+++ b/moniker/tests/test_central/__init__.py
@@ -13,12 +13,8 @@
# 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 moniker.central import service as central_service
from moniker.tests import TestCase
class CentralTestCase(TestCase):
__test__ = False
-
- def get_central_service(self):
- return central_service.Service()
diff --git a/moniker/tests/test_handler/__init__.py b/moniker/tests/test_handler/__init__.py
new file mode 100644
index 00000000..3b4b3618
--- /dev/null
+++ b/moniker/tests/test_handler/__init__.py
@@ -0,0 +1,49 @@
+# Copyright 2012 Managed I.T.
+#
+# Author: Kiall Mac Innes <kiall@managedit.ie>
+#
+# 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 json
+import os
+from moniker.openstack.common import cfg
+from moniker import storage
+from moniker.tests import TestCase
+
+FIXTURES_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..',
+ 'sample_notifications'))
+
+
+class HandlerTestCase(TestCase):
+ __test__ = False
+
+ def setUp(self):
+ super(HandlerTestCase, self).setUp()
+ self.central_service = self.get_central_service()
+
+ def get_notification_fixture(self, service, name):
+ filename = os.path.join(FIXTURES_PATH, service, '%s.json' % name)
+
+ if not os.path.exists(filename):
+ raise Exception('Invalid notification fixture requested')
+
+ with open(filename, 'r') as fh:
+ return json.load(fh)
+
+ def test_invalid_event_type(self):
+ event_type = 'invalid'
+
+ self.assertNotIn(event_type, self.handler.get_event_types())
+
+ with self.assertRaises(ValueError):
+ self.handler.process_notification(event_type, 'payload')
diff --git a/moniker/tests/test_handler/test_nova.py b/moniker/tests/test_handler/test_nova.py
new file mode 100644
index 00000000..507b8a6a
--- /dev/null
+++ b/moniker/tests/test_handler/test_nova.py
@@ -0,0 +1,115 @@
+# Copyright 2012 Managed I.T.
+#
+# Author: Kiall Mac Innes <kiall@managedit.ie>
+#
+# 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 nose import SkipTest
+from moniker.openstack.common import cfg
+from moniker.openstack.common import log as logging
+from moniker.tests.test_handler import HandlerTestCase
+from moniker.notification_handler import nova
+
+LOG = logging.getLogger(__name__)
+
+
+class NovaHandlerTest(HandlerTestCase):
+ __test__ = True
+
+ def setUp(self):
+ super(NovaHandlerTest, self).setUp()
+
+ self._init_handler()
+
+ def _init_handler(self):
+ # Create provider domain
+ values = {'name': 'exampe.com', 'email': 'info@example.com'}
+
+ domain = self.central_service.create_domain(self.admin_context, values)
+ self.fixed_ip_domain = domain['id']
+
+ # Register handler specific config options
+ nova.NovaHandler.register_opts(cfg.CONF)
+
+ # Override default config values
+ self.config(nova_fixed_ip_domain=self.fixed_ip_domain)
+
+ # Initialize the handler
+ self.handler = nova.NovaHandler(central_service=self.central_service)
+
+ def test_instance_create_end(self):
+ event_type = 'compute.instance.create.end'
+ fixture = self.get_notification_fixture('nova', event_type)
+
+ self.assertIn(event_type, self.handler.get_event_types())
+
+ # Ensure we start with 0 records
+ records = self.central_service.get_records(self.admin_context,
+ self.fixed_ip_domain)
+
+ self.assertEqual(0, len(records))
+
+ self.handler.process_notification(event_type, fixture['payload'])
+
+ # Ensure we now have exactly 1 record
+ records = self.central_service.get_records(self.admin_context,
+ self.fixed_ip_domain)
+
+ self.assertEqual(len(records), 1)
+
+ def test_instance_delete_start(self):
+ # Prepare for the test
+ start_event_type = 'compute.instance.create.end'
+ start_fixture = self.get_notification_fixture('nova', start_event_type)
+
+ self.handler.process_notification(start_event_type,
+ start_fixture['payload'])
+
+ # Now - Onto the real test
+ event_type = 'compute.instance.delete.start'
+ fixture = self.get_notification_fixture('nova', event_type)
+
+ self.assertIn(event_type, self.handler.get_event_types())
+
+ # Ensure we start with at least 1 record
+ records = self.central_service.get_records(self.admin_context,
+ self.fixed_ip_domain)
+
+ self.assertGreaterEqual(len(records), 1)
+
+ self.handler.process_notification(event_type, fixture['payload'])
+
+ # Ensure we now have exactly 0 records
+ records = self.central_service.get_records(self.admin_context,
+ self.fixed_ip_domain)
+
+ self.assertEqual(0, len(records))
+
+ def test_floating_ip_associate(self):
+ raise SkipTest()
+
+ event_type = 'network.floating_ip.associate'
+ fixture = self.get_notification_fixture('nova', event_type)
+
+ self.assertIn(event_type, self.handler.get_event_types())
+
+ self.handler.process_notification(event_type, fixture['payload'])
+
+ def test_floating_ip_disassociate(self):
+ raise SkipTest()
+
+ event_type = 'network.floating_ip.disassociate'
+ fixture = self.get_notification_fixture('nova', event_type)
+
+ self.assertIn(event_type, self.handler.get_event_types())
+
+ self.handler.process_notification(event_type, fixture['payload'])
diff --git a/moniker/tests/test_storage/__init__.py b/moniker/tests/test_storage/__init__.py
index d4b43b68..916cef84 100644
--- a/moniker/tests/test_storage/__init__.py
+++ b/moniker/tests/test_storage/__init__.py
@@ -71,7 +71,6 @@ class StorageDriverTestCase(StorageTestCase):
def setUp(self):
super(StorageDriverTestCase, self).setUp()
self.storage_conn = self.get_storage_driver()
- self.admin_context = self.get_admin_context()
def create_server_fixture(self, fixture=0, values={}):
_values = copy.copy(self.server_fixtures[fixture])
diff --git a/setup.py b/setup.py
index e9ce356c..72669a19 100755
--- a/setup.py
+++ b/setup.py
@@ -59,6 +59,10 @@ setup(
mysql = moniker.storage.impl_sqlalchemy:SQLAlchemyStorage
postgresql = moniker.storage.impl_sqlalchemy:SQLAlchemyStorage
sqlite = moniker.storage.impl_sqlalchemy:SQLAlchemyStorage
+
+ [moniker.notification.handler]
+ nova = moniker.notification_handler.nova:NovaHandler
+
[moniker.cli]
database init = moniker.cli.database:InitCommand
database sync = moniker.cli.database:SyncCommand