Versioned object - WatchRule and WatchData
Prototype implementation of oslo.versionedobjects. This patch adds WatchRule and WatchData object. Implements: blueprint versioned-objects Co-Authored-By: ShaoHe Feng <shaohe.feng@intel.com> Co-Authored-By: He Jie Xu <hejie.xu@intel.com> Co-Authored-By: Grzegorz Grasza <grzegorz.grasza@intel.com> Change-Id: I29fc0fc99c0c425291246dc3889393cbcc0b82cf
This commit is contained in:
parent
0a0f7c9389
commit
4dd2a188f1
@ -256,6 +256,10 @@ def watch_data_get_all(context):
|
||||
return IMPL.watch_data_get_all(context)
|
||||
|
||||
|
||||
def watch_data_get_all_by_watch_rule_id(context, watch_rule_id):
|
||||
return IMPL.watch_data_get_all_by_watch_rule_id(context, watch_rule_id)
|
||||
|
||||
|
||||
def software_config_create(context, values):
|
||||
return IMPL.software_config_create(context, values)
|
||||
|
||||
|
@ -725,6 +725,12 @@ def watch_data_get_all(context):
|
||||
return results
|
||||
|
||||
|
||||
def watch_data_get_all_by_watch_rule_id(context, watch_rule_id):
|
||||
results = model_query(context, models.WatchData).filter_by(
|
||||
watch_rule_id=watch_rule_id).all()
|
||||
return results
|
||||
|
||||
|
||||
def software_config_create(context, values):
|
||||
obj_ref = models.SoftwareConfig()
|
||||
obj_ref.update(values)
|
||||
|
@ -35,7 +35,6 @@ from heat.common.i18n import _LW
|
||||
from heat.common import identifier
|
||||
from heat.common import messaging as rpc_messaging
|
||||
from heat.common import service_utils
|
||||
from heat.db import api as db_api
|
||||
from heat.engine import api
|
||||
from heat.engine import attributes
|
||||
from heat.engine import clients
|
||||
@ -55,6 +54,8 @@ from heat.objects import event as event_object
|
||||
from heat.objects import resource as resource_objects
|
||||
from heat.objects import snapshot as snapshot_object
|
||||
from heat.objects import stack as stack_object
|
||||
from heat.objects import watch_data
|
||||
from heat.objects import watch_rule
|
||||
from heat.openstack.common import service
|
||||
from heat.openstack.common import threadgroup
|
||||
from heat.rpc import api as rpc_api
|
||||
@ -1335,7 +1336,7 @@ class EngineService(service.Service):
|
||||
if watch_name:
|
||||
yield watchrule.WatchRule.load(cnxt, watch_name)
|
||||
else:
|
||||
for wr in db_api.watch_rule_get_all(cnxt):
|
||||
for wr in watch_rule.WatchRule.get_all(cnxt):
|
||||
if watchrule.rule_can_use_sample(wr, stats_data):
|
||||
yield watchrule.WatchRule.load(cnxt, watch=wr)
|
||||
|
||||
@ -1364,7 +1365,7 @@ class EngineService(service.Service):
|
||||
wrn = [watch_name]
|
||||
else:
|
||||
try:
|
||||
wrn = [w.name for w in db_api.watch_rule_get_all(cnxt)]
|
||||
wrn = [w.name for w in watch_rule.WatchRule.get_all(cnxt)]
|
||||
except Exception as ex:
|
||||
LOG.warn(_LW('show_watch (all) db error %s'), ex)
|
||||
return
|
||||
@ -1393,7 +1394,7 @@ class EngineService(service.Service):
|
||||
return
|
||||
|
||||
try:
|
||||
wds = db_api.watch_data_get_all(cnxt)
|
||||
wds = watch_data.WatchData.get_all(cnxt)
|
||||
except Exception as ex:
|
||||
LOG.warn(_LW('show_metric (all) db error %s'), ex)
|
||||
return
|
||||
|
@ -21,10 +21,11 @@ from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.common.i18n import _LI
|
||||
from heat.common.i18n import _LW
|
||||
from heat.db import api as db_api
|
||||
from heat.engine import stack
|
||||
from heat.engine import timestamp
|
||||
from heat.objects import stack as stack_object
|
||||
from heat.objects import watch_data as watch_data_objects
|
||||
from heat.objects import watch_rule as watch_rule_objects
|
||||
from heat.rpc import api as rpc_api
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -48,8 +49,10 @@ class WatchRule(object):
|
||||
NORMAL: 'OKActions',
|
||||
NODATA: 'InsufficientDataActions'}
|
||||
|
||||
created_at = timestamp.Timestamp(db_api.watch_rule_get, 'created_at')
|
||||
updated_at = timestamp.Timestamp(db_api.watch_rule_get, 'updated_at')
|
||||
created_at = timestamp.Timestamp(watch_rule_objects.WatchRule.get_by_id,
|
||||
'created_at')
|
||||
updated_at = timestamp.Timestamp(watch_rule_objects.WatchRule.get_by_id,
|
||||
'updated_at')
|
||||
|
||||
def __init__(self, context, watch_name, rule, stack_id=None,
|
||||
state=NODATA, wid=None, watch_data=None,
|
||||
@ -77,7 +80,8 @@ class WatchRule(object):
|
||||
'''
|
||||
if watch is None:
|
||||
try:
|
||||
watch = db_api.watch_rule_get_by_name(context, watch_name)
|
||||
watch = watch_rule_objects.WatchRule.get_by_name(context,
|
||||
watch_name)
|
||||
except Exception as ex:
|
||||
LOG.warn(_LW('WatchRule.load (%(watch_name)s) db error '
|
||||
'%(ex)s'), {'watch_name': watch_name, 'ex': ex})
|
||||
@ -107,17 +111,18 @@ class WatchRule(object):
|
||||
}
|
||||
|
||||
if not self.id:
|
||||
wr = db_api.watch_rule_create(self.context, wr_values)
|
||||
wr = watch_rule_objects.WatchRule.create(self.context, wr_values)
|
||||
self.id = wr.id
|
||||
else:
|
||||
db_api.watch_rule_update(self.context, self.id, wr_values)
|
||||
watch_rule_objects.WatchRule.update_by_id(self.context, self.id,
|
||||
wr_values)
|
||||
|
||||
def destroy(self):
|
||||
'''
|
||||
Delete the watchrule from the database.
|
||||
'''
|
||||
if self.id:
|
||||
db_api.watch_rule_delete(self.context, self.id)
|
||||
watch_rule_objects.WatchRule.delete(self.context, self.id)
|
||||
|
||||
def do_data_cmp(self, data, threshold):
|
||||
op = self.rule['ComparisonOperator']
|
||||
@ -320,7 +325,7 @@ class WatchRule(object):
|
||||
'data': data,
|
||||
'watch_rule_id': self.id
|
||||
}
|
||||
wd = db_api.watch_data_create(None, watch_data)
|
||||
wd = watch_data_objects.WatchData.create(self.context, watch_data)
|
||||
LOG.debug('new watch:%(name)s data:%(data)s'
|
||||
% {'name': self.name, 'data': str(wd.data)})
|
||||
|
||||
|
66
heat/objects/watch_data.py
Normal file
66
heat/objects/watch_data.py
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright 2014 Intel Corp.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
WatchData object
|
||||
"""
|
||||
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from heat.db import api as db_api
|
||||
from heat.objects import fields as heat_fields
|
||||
|
||||
|
||||
class WatchData(base.VersionedObject, base.VersionedObjectDictCompat):
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(nullable=False),
|
||||
'data': heat_fields.JsonField(nullable=True),
|
||||
'watch_rule_id': fields.StringField(nullable=False),
|
||||
'watch_rule': fields.ObjectField('WatchRule'),
|
||||
'created_at': fields.DateTimeField(read_only=True),
|
||||
'updated_at': fields.DateTimeField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object(context, rule, db_data):
|
||||
from heat.objects import watch_rule
|
||||
for field in rule.fields:
|
||||
if field == 'watch_rule':
|
||||
rule[field] = watch_rule.WatchRule._from_db_object(
|
||||
context,
|
||||
watch_rule.WatchRule(),
|
||||
db_data['watch_rule'])
|
||||
else:
|
||||
rule[field] = db_data[field]
|
||||
rule._context = context
|
||||
rule.obj_reset_changes()
|
||||
return rule
|
||||
|
||||
@classmethod
|
||||
def create(cls, context, values):
|
||||
db_data = db_api.watch_data_create(context, values)
|
||||
return cls._from_db_object(context, cls(), db_data)
|
||||
|
||||
@classmethod
|
||||
def get_all(cls, context):
|
||||
return [cls._from_db_object(context, cls(), db_data)
|
||||
for db_data in db_api.watch_data_get_all(context)]
|
||||
|
||||
@classmethod
|
||||
def get_all_by_watch_rule_id(cls, context, watch_rule_id):
|
||||
return (cls._from_db_object(context, cls(), db_data)
|
||||
for db_data in db_api.watch_data_get_all_by_watch_rule_id(
|
||||
context, watch_rule_id))
|
90
heat/objects/watch_rule.py
Normal file
90
heat/objects/watch_rule.py
Normal file
@ -0,0 +1,90 @@
|
||||
# Copyright 2014 Intel Corp.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
WatchRule object
|
||||
"""
|
||||
|
||||
from oslo_versionedobjects import base
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from heat.db import api as db_api
|
||||
from heat.objects import fields as heat_fields
|
||||
from heat.objects import stack
|
||||
from heat.objects import watch_data
|
||||
|
||||
|
||||
class WatchRule(base.VersionedObject, base.VersionedObjectDictCompat):
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(nullable=False),
|
||||
'name': fields.StringField(nullable=True),
|
||||
'rule': heat_fields.JsonField(nullable=True),
|
||||
'state': fields.StringField(nullable=True),
|
||||
'last_evaluated': fields.DateTimeField(nullable=True),
|
||||
'stack_id': fields.StringField(nullable=False),
|
||||
'stack': fields.ObjectField(stack.Stack),
|
||||
'watch_data': fields.ListOfObjectsField(watch_data.WatchData),
|
||||
'created_at': fields.DateTimeField(read_only=True),
|
||||
'updated_at': fields.DateTimeField(nullable=True),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _from_db_object(context, rule, db_rule):
|
||||
for field in rule.fields:
|
||||
if field == 'stack':
|
||||
rule[field] = stack.Stack._from_db_object(
|
||||
context, stack.Stack(), db_rule[field])
|
||||
elif field == 'watch_data':
|
||||
rule[field] = watch_data.WatchData.get_all_by_watch_rule_id(
|
||||
context, db_rule['id'])
|
||||
else:
|
||||
rule[field] = db_rule[field]
|
||||
rule._context = context
|
||||
rule.obj_reset_changes()
|
||||
return rule
|
||||
|
||||
@classmethod
|
||||
def get_by_id(cls, context, rule_id):
|
||||
db_rule = db_api.watch_rule_get(context, rule_id)
|
||||
return cls._from_db_object(context, cls(), db_rule)
|
||||
|
||||
@classmethod
|
||||
def get_by_name(cls, context, watch_rule_name):
|
||||
db_rule = db_api.watch_rule_get_by_name(context, watch_rule_name)
|
||||
return cls._from_db_object(context, cls(), db_rule)
|
||||
|
||||
@classmethod
|
||||
def get_all(cls, context):
|
||||
return [cls._from_db_object(context, cls(), db_rule)
|
||||
for db_rule in db_api.watch_rule_get_all(context)]
|
||||
|
||||
@classmethod
|
||||
def get_all_by_stack(cls, context, stack_id):
|
||||
return [cls._from_db_object(context, cls(), db_rule)
|
||||
for db_rule in db_api.watch_rule_get_all_by_stack(context,
|
||||
stack_id)]
|
||||
|
||||
@classmethod
|
||||
def update_by_id(cls, context, watch_id, values):
|
||||
db_api.watch_rule_update(context, watch_id, values)
|
||||
|
||||
@classmethod
|
||||
def create(cls, context, values):
|
||||
return cls._from_db_object(context, cls(),
|
||||
db_api.watch_rule_create(context, values))
|
||||
|
||||
@classmethod
|
||||
def delete(cls, context, watch_id):
|
||||
db_api.watch_rule_delete(context, watch_id)
|
@ -18,10 +18,10 @@ import mox
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.db import api as db_api
|
||||
from heat.engine import parser
|
||||
from heat.engine import template
|
||||
from heat.engine import watchrule
|
||||
from heat.objects import watch_rule
|
||||
from heat.tests import common
|
||||
from heat.tests import utils
|
||||
|
||||
@ -321,7 +321,7 @@ class WatchRuleTest(common.HeatTestCase):
|
||||
stack_id=self.stack_id, rule=rule)
|
||||
self.wr.store()
|
||||
|
||||
dbwr = db_api.watch_rule_get_by_name(self.ctx, 'storetest')
|
||||
dbwr = watch_rule.WatchRule.get_by_name(self.ctx, 'storetest')
|
||||
self.assertIsNotNone(dbwr)
|
||||
self.assertEqual('storetest', dbwr.name)
|
||||
self.assertEqual(watchrule.WatchRule.NODATA, dbwr.state)
|
||||
@ -624,8 +624,9 @@ class WatchRuleTest(common.HeatTestCase):
|
||||
"Dimensions": []}}
|
||||
self.wr.create_watch_data(data)
|
||||
|
||||
dbwr = db_api.watch_rule_get_by_name(self.ctx, 'create_data_test')
|
||||
self.assertEqual(data, dbwr.watch_data[0].data)
|
||||
obj_wr = watch_rule.WatchRule.get_by_name(self.ctx, 'create_data_test')
|
||||
obj_wds = [wd for wd in obj_wr.watch_data]
|
||||
self.assertEqual(data, obj_wds[0].data)
|
||||
|
||||
# Note, would be good to write another datapoint and check it
|
||||
# but sqlite seems to not interpret the backreference correctly
|
||||
@ -654,8 +655,9 @@ class WatchRuleTest(common.HeatTestCase):
|
||||
"Dimensions": []}}
|
||||
self.wr.create_watch_data(data)
|
||||
|
||||
dbwr = db_api.watch_rule_get_by_name(self.ctx, 'create_data_test')
|
||||
self.assertEqual([], dbwr.watch_data)
|
||||
obj_wr = watch_rule.WatchRule.get_by_name(self.ctx, 'create_data_test')
|
||||
obj_wds = [wd for wd in obj_wr.watch_data]
|
||||
self.assertEqual([], obj_wds)
|
||||
|
||||
def test_create_watch_data_match(self):
|
||||
rule = {u'EvaluationPeriods': u'1',
|
||||
|
Loading…
Reference in New Issue
Block a user