Move event database driver out of engine

This patch moves the event module out of the engine in preparation for a
re-org of the event logging facility.

Change-Id: Ic8fbf1af13a06b400215339d340c6343743f93bf
partial-blueprint: generic-event
This commit is contained in:
tengqm 2016-11-16 00:15:55 -05:00
parent 38ec3ea2b4
commit b47d9b6ca2
5 changed files with 130 additions and 116 deletions

View File

@ -11,106 +11,20 @@
# under the License. # under the License.
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import reflection
from oslo_utils import timeutils from oslo_utils import timeutils
from senlin.common.i18n import _LC, _LE, _LW, _LI from senlin.common.i18n import _LC, _LE, _LW, _LI
from senlin.objects import event as eo from senlin.events import database as DB
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class Event(object):
'''Class capturing an interesting happening in Senlin.'''
def __init__(self, timestamp, level, entity=None, **kwargs):
self.timestamp = timestamp
self.level = level
self.id = kwargs.get('id', None)
self.user = kwargs.get('user', None)
self.project = kwargs.get('project', None)
self.action = kwargs.get('action', None)
self.status = kwargs.get('status', None)
self.status_reason = kwargs.get('status_reason', None)
# we deal with deserialization first
self.oid = kwargs.get('oid', None)
self.otype = kwargs.get('otype', None)
self.oname = kwargs.get('oname', None)
self.cluster_id = kwargs.get('cluster_id', None)
self.metadata = kwargs.get('metadata', {})
# entity not None implies an initial creation of event object,
# not a deserialization, so we try make an inference here
if entity is not None:
self._infer_entity_data(entity)
def _infer_entity_data(self, entity):
if self.status is None:
self.status = entity.status
if self.status_reason is None:
self.status_reason = entity.status_reason
e_type = reflection.get_class_name(entity, fully_qualified=False)
e_type = e_type.upper()
if e_type == 'CLUSTER':
self.oid = entity.id
self.cluster_id = entity.id
self.oname = entity.name
self.otype = 'CLUSTER'
elif e_type == 'NODE':
self.oid = entity.id
self.cluster_id = entity.cluster_id
self.oname = entity.name
self.otype = 'NODE'
elif e_type == 'CLUSTERACTION':
self.oid = entity.target
self.cluster_id = entity.target
self.oname = entity.cluster.name
self.otype = 'CLUSTER'
elif e_type == 'NODEACTION':
self.oid = entity.target
self.cluster_id = entity.node.cluster_id
self.oname = entity.node.name
self.otype = 'NODE'
else:
self.oid = entity.target
self.cluster_id = ''
self.oname = ''
self.otype = ''
def store(self, context):
'''Store the event into database and return its ID.'''
values = {
'level': self.level,
'timestamp': self.timestamp,
'oid': self.oid,
'otype': self.otype,
'oname': self.oname,
'cluster_id': self.cluster_id,
'user': self.user,
'project': self.project,
'action': self.action,
'status': self.status,
'status_reason': self.status_reason,
'meta_data': self.metadata,
}
event = eo.Event.create(context, values)
self.id = event.id
return self.id
def critical(context, entity, action, status=None, status_reason=None, def critical(context, entity, action, status=None, status_reason=None,
timestamp=None): timestamp=None):
timestamp = timestamp or timeutils.utcnow(True) timestamp = timestamp or timeutils.utcnow(True)
event = Event(timestamp, logging.CRITICAL, entity, event = DB.Event(timestamp, logging.CRITICAL, entity,
action=action, status=status, status_reason=status_reason, action=action, status=status, status_reason=status_reason,
user=context.user, project=context.project) user=context.user, project=context.project)
event.store(context) event.store(context)
LOG.critical(_LC('%(name)s [%(id)s] - %(status)s: %(reason)s'), LOG.critical(_LC('%(name)s [%(id)s] - %(status)s: %(reason)s'),
{'name': event.oname, {'name': event.oname,
@ -122,9 +36,9 @@ def critical(context, entity, action, status=None, status_reason=None,
def error(context, entity, action, status=None, status_reason=None, def error(context, entity, action, status=None, status_reason=None,
timestamp=None): timestamp=None):
timestamp = timestamp or timeutils.utcnow(True) timestamp = timestamp or timeutils.utcnow(True)
event = Event(timestamp, logging.ERROR, entity, event = DB.Event(timestamp, logging.ERROR, entity,
action=action, status=status, status_reason=status_reason, action=action, status=status, status_reason=status_reason,
user=context.user, project=context.project) user=context.user, project=context.project)
event.store(context) event.store(context)
msg = _LE('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s') msg = _LE('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s')
LOG.error(msg, LOG.error(msg,
@ -138,9 +52,9 @@ def error(context, entity, action, status=None, status_reason=None,
def warning(context, entity, action, status=None, status_reason=None, def warning(context, entity, action, status=None, status_reason=None,
timestamp=None): timestamp=None):
timestamp = timestamp or timeutils.utcnow(True) timestamp = timestamp or timeutils.utcnow(True)
event = Event(timestamp, logging.WARNING, entity, event = DB.Event(timestamp, logging.WARNING, entity,
action=action, status=status, status_reason=status_reason, action=action, status=status, status_reason=status_reason,
user=context.user, project=context.project) user=context.user, project=context.project)
event.store(context) event.store(context)
msg = _LW('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s') msg = _LW('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s')
LOG.warning(msg, LOG.warning(msg,
@ -154,9 +68,9 @@ def warning(context, entity, action, status=None, status_reason=None,
def info(context, entity, action, status=None, status_reason=None, def info(context, entity, action, status=None, status_reason=None,
timestamp=None): timestamp=None):
timestamp = timestamp or timeutils.utcnow(True) timestamp = timestamp or timeutils.utcnow(True)
event = Event(timestamp, logging.INFO, entity, event = DB.Event(timestamp, logging.INFO, entity,
action=action, status=status, status_reason=status_reason, action=action, status=status, status_reason=status_reason,
user=context.user, project=context.project) user=context.user, project=context.project)
event.store(context) event.store(context)
LOG.info(_LI('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s'), LOG.info(_LI('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s'),
{'name': event.oname, {'name': event.oname,
@ -169,9 +83,9 @@ def info(context, entity, action, status=None, status_reason=None,
def debug(context, entity, action, status=None, status_reason=None, def debug(context, entity, action, status=None, status_reason=None,
timestamp=None): timestamp=None):
timestamp = timestamp or timeutils.utcnow(True) timestamp = timestamp or timeutils.utcnow(True)
event = Event(timestamp, logging.DEBUG, entity, event = DB.Event(timestamp, logging.DEBUG, entity,
action=action, status=status, status_reason=status_reason, action=action, status=status, status_reason=status_reason,
user=context.user, project=context.project) user=context.user, project=context.project)
event.store(context) event.store(context)
LOG.debug('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s', LOG.debug('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s',
{'name': event.oname, {'name': event.oname,

View File

100
senlin/events/database.py Normal file
View File

@ -0,0 +1,100 @@
# 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 oslo_utils import reflection
from senlin.objects import event as eo
class Event(object):
"""Class encapsulating an interesting happening in Senlin."""
def __init__(self, timestamp, level, entity=None, **kwargs):
self.timestamp = timestamp
self.level = level
self.id = kwargs.get('id', None)
self.user = kwargs.get('user', None)
self.project = kwargs.get('project', None)
self.action = kwargs.get('action', None)
self.status = kwargs.get('status', None)
self.status_reason = kwargs.get('status_reason', None)
# we deal with deserialization first
self.oid = kwargs.get('oid', None)
self.otype = kwargs.get('otype', None)
self.oname = kwargs.get('oname', None)
self.cluster_id = kwargs.get('cluster_id', None)
self.metadata = kwargs.get('metadata', {})
# entity not None implies an initial creation of event object,
# not a deserialization, so we try make an inference here
if entity is not None:
self._infer_entity_data(entity)
def _infer_entity_data(self, entity):
if self.status is None:
self.status = entity.status
if self.status_reason is None:
self.status_reason = entity.status_reason
e_type = reflection.get_class_name(entity, fully_qualified=False)
e_type = e_type.upper()
if e_type == 'CLUSTER':
self.oid = entity.id
self.cluster_id = entity.id
self.oname = entity.name
self.otype = 'CLUSTER'
elif e_type == 'NODE':
self.oid = entity.id
self.cluster_id = entity.cluster_id
self.oname = entity.name
self.otype = 'NODE'
elif e_type == 'CLUSTERACTION':
self.oid = entity.target
self.cluster_id = entity.target
self.oname = entity.cluster.name
self.otype = 'CLUSTER'
elif e_type == 'NODEACTION':
self.oid = entity.target
self.cluster_id = entity.node.cluster_id
self.oname = entity.node.name
self.otype = 'NODE'
else:
self.oid = entity.target
self.cluster_id = ''
self.oname = ''
self.otype = ''
def store(self, context):
"""Store the event into database and return its ID."""
values = {
'level': self.level,
'timestamp': self.timestamp,
'oid': self.oid,
'otype': self.otype,
'oname': self.oname,
'cluster_id': self.cluster_id,
'user': self.user,
'project': self.project,
'action': self.action,
'status': self.status,
'status_reason': self.status_reason,
'meta_data': self.metadata,
}
event = eo.Event.create(context, values)
self.id = event.id
return self.id

View File

View File

@ -16,7 +16,7 @@ from oslo_log import log as logging
from oslo_utils import timeutils from oslo_utils import timeutils
from senlin.engine import cluster as cluster_mod from senlin.engine import cluster as cluster_mod
from senlin.engine import event as EVENT from senlin.events import database as DB
from senlin.objects import event as eo from senlin.objects import event as eo
from senlin.tests.unit.common import base from senlin.tests.unit.common import base
from senlin.tests.unit.common import utils from senlin.tests.unit.common import utils
@ -24,10 +24,10 @@ from senlin.tests.unit.common import utils
CLUSTER_ID = '2c5139a6-24ba-4a6f-bd53-a268f61536de' CLUSTER_ID = '2c5139a6-24ba-4a6f-bd53-a268f61536de'
class TestEvent(base.SenlinTestCase): class TestDatabase(base.SenlinTestCase):
def setUp(self): def setUp(self):
super(TestEvent, self).setUp() super(TestDatabase, self).setUp()
self.context = utils.dummy_context() self.context = utils.dummy_context()
def test_event_init(self): def test_event_init(self):
@ -46,7 +46,7 @@ class TestEvent(base.SenlinTestCase):
'metadata': {'foo': 'bar'}, 'metadata': {'foo': 'bar'},
} }
event = EVENT.Event(timestamp, logging.CRITICAL, **kwargs) event = DB.Event(timestamp, logging.CRITICAL, **kwargs)
self.assertEqual(timestamp, event.timestamp) self.assertEqual(timestamp, event.timestamp)
self.assertEqual(logging.CRITICAL, event.level) self.assertEqual(logging.CRITICAL, event.level)
@ -69,11 +69,11 @@ class TestEvent(base.SenlinTestCase):
x_cluster = cluster_mod.Cluster('fake-cluster', 0, 'fake-profile', x_cluster = cluster_mod.Cluster('fake-cluster', 0, 'fake-profile',
id='FAKE_CLUSTER') id='FAKE_CLUSTER')
event = EVENT.Event(timestamp, logging.CRITICAL, x_cluster, event = DB.Event(timestamp, logging.CRITICAL, x_cluster,
action="FAKE_ACTION", status="ACTIVE", action="FAKE_ACTION", status="ACTIVE",
status_reason="Recovered just now", status_reason="Recovered just now",
user=self.context.user, user=self.context.user,
project=self.context.project) project=self.context.project)
self.assertEqual(timestamp, event.timestamp) self.assertEqual(timestamp, event.timestamp)
self.assertIsNone(event.id) self.assertIsNone(event.id)
@ -97,7 +97,7 @@ class TestEvent(base.SenlinTestCase):
entity.name = 'obj-name' entity.name = 'obj-name'
mock_get.return_value = 'Cluster' mock_get.return_value = 'Cluster'
event = EVENT.Event('timestamp', 'level', entity) event = DB.Event('timestamp', 'level', entity)
self.assertEqual('timestamp', event.timestamp) self.assertEqual('timestamp', event.timestamp)
self.assertEqual('level', event.level) self.assertEqual('level', event.level)
@ -117,7 +117,7 @@ class TestEvent(base.SenlinTestCase):
entity.name = 'obj-name' entity.name = 'obj-name'
mock_get.return_value = 'Node' mock_get.return_value = 'Node'
event = EVENT.Event('timestamp', 'level', entity) event = DB.Event('timestamp', 'level', entity)
self.assertEqual('timestamp', event.timestamp) self.assertEqual('timestamp', event.timestamp)
self.assertEqual('level', event.level) self.assertEqual('level', event.level)
@ -137,7 +137,7 @@ class TestEvent(base.SenlinTestCase):
entity.cluster.name = 'obj-name' entity.cluster.name = 'obj-name'
mock_get.return_value = 'ClusterAction' mock_get.return_value = 'ClusterAction'
event = EVENT.Event('timestamp', 'level', entity) event = DB.Event('timestamp', 'level', entity)
self.assertEqual('timestamp', event.timestamp) self.assertEqual('timestamp', event.timestamp)
self.assertEqual('level', event.level) self.assertEqual('level', event.level)
@ -158,7 +158,7 @@ class TestEvent(base.SenlinTestCase):
entity.node.cluster_id = CLUSTER_ID entity.node.cluster_id = CLUSTER_ID
mock_get.return_value = 'NodeAction' mock_get.return_value = 'NodeAction'
event = EVENT.Event('timestamp', 'level', entity) event = DB.Event('timestamp', 'level', entity)
self.assertEqual('timestamp', event.timestamp) self.assertEqual('timestamp', event.timestamp)
self.assertEqual('level', event.level) self.assertEqual('level', event.level)
@ -185,7 +185,7 @@ class TestEvent(base.SenlinTestCase):
'metadata': {'foo': 'bar'}, 'metadata': {'foo': 'bar'},
} }
event = EVENT.Event(timestamp, logging.CRITICAL, **kwargs) event = DB.Event(timestamp, logging.CRITICAL, **kwargs)
self.assertIsNone(event.id) self.assertIsNone(event.id)
event_id = event.store(self.context) event_id = event.store(self.context)