Alarms support in HBase Part 2
Refactor query creation: it is needed to make two different methods for query creation and start and stop - rows determination. Partialy implements bp hbase-alarming Change-Id: I2a2a728597d92c27b86e4a93dd0f151b6f52403b
This commit is contained in:
parent
c1d3ffa2ca
commit
b4bb537e90
@ -33,6 +33,7 @@ from ceilometer.openstack.common.gettextutils import _ # noqa
|
|||||||
from ceilometer.openstack.common import log
|
from ceilometer.openstack.common import log
|
||||||
from ceilometer.openstack.common import network_utils
|
from ceilometer.openstack.common import network_utils
|
||||||
from ceilometer.openstack.common import timeutils
|
from ceilometer.openstack.common import timeutils
|
||||||
|
from ceilometer import storage
|
||||||
from ceilometer.storage import base
|
from ceilometer.storage import base
|
||||||
from ceilometer.storage import models
|
from ceilometer.storage import models
|
||||||
from ceilometer import utils
|
from ceilometer import utils
|
||||||
@ -203,10 +204,9 @@ class Connection(base.Connection):
|
|||||||
#TODO(nprivalova): to be refactored
|
#TODO(nprivalova): to be refactored
|
||||||
if enabled is not None:
|
if enabled is not None:
|
||||||
enabled = json.dumps(enabled)
|
enabled = json.dumps(enabled)
|
||||||
|
q = make_query(alarm_id=alarm_id, name=name, enabled=enabled,
|
||||||
|
user_id=user, project_id=project)
|
||||||
|
|
||||||
q = make_query(require_meter=False, query_only=True,
|
|
||||||
alarm_id=alarm_id, name=name,
|
|
||||||
enabled=enabled, user_id=user, project_id=project)
|
|
||||||
gen = alarm_table.scan(filter=q)
|
gen = alarm_table.scan(filter=q)
|
||||||
for ignored, data in gen:
|
for ignored, data in gen:
|
||||||
stored_alarm = deserialize_entry(data)
|
stored_alarm = deserialize_entry(data)
|
||||||
@ -218,26 +218,17 @@ class Connection(base.Connection):
|
|||||||
end_timestamp=None, end_timestamp_op=None):
|
end_timestamp=None, end_timestamp_op=None):
|
||||||
alarm_history_table = self.conn.table(self.ALARM_HISTORY_TABLE)
|
alarm_history_table = self.conn.table(self.ALARM_HISTORY_TABLE)
|
||||||
|
|
||||||
q = make_query(start=start_timestamp,
|
q = make_query(alarm_id=alarm_id, on_behalf_of=on_behalf_of, type=type,
|
||||||
start_op=start_timestamp_op,
|
user_id=user, project_id=project)
|
||||||
end=end_timestamp,
|
|
||||||
end_op=end_timestamp_op,
|
|
||||||
require_meter=False, query_only=True,
|
|
||||||
include_rts_in_filters=False, alarm_id=alarm_id,
|
|
||||||
on_behalf_of=on_behalf_of, type=type, user_id=user,
|
|
||||||
project_id=project)
|
|
||||||
#TODO(nprivalova): refactor make_query to move this stuff there
|
|
||||||
rts_start = str(reverse_timestamp(start_timestamp) + 1) \
|
|
||||||
if start_timestamp else ""
|
|
||||||
rts_end = str(reverse_timestamp(end_timestamp) + 1) \
|
|
||||||
if end_timestamp else ""
|
|
||||||
if start_timestamp_op == 'gt':
|
|
||||||
rts_start = str(long(rts_start) - 2)
|
|
||||||
if end_timestamp_op == 'le':
|
|
||||||
rts_end = str(long(rts_end) - 1)
|
|
||||||
|
|
||||||
gen = alarm_history_table.scan(filter=q, row_start=rts_end,
|
start_row, end_row = make_timestamp_query(
|
||||||
row_stop=rts_start)
|
_make_general_rowkey_scan,
|
||||||
|
start=start_timestamp, start_op=start_timestamp_op,
|
||||||
|
end=end_timestamp, end_op=end_timestamp_op, bounds_only=True,
|
||||||
|
some_id=alarm_id)
|
||||||
|
|
||||||
|
gen = alarm_history_table.scan(filter=q, row_start=start_row,
|
||||||
|
row_stop=end_row)
|
||||||
for ignored, data in gen:
|
for ignored, data in gen:
|
||||||
stored_entry = deserialize_entry(data)
|
stored_entry = deserialize_entry(data)
|
||||||
# It is needed to return 'details' field as string
|
# It is needed to return 'details' field as string
|
||||||
@ -420,17 +411,15 @@ class Connection(base.Connection):
|
|||||||
)
|
)
|
||||||
meter_table = self.conn.table(self.METER_TABLE)
|
meter_table = self.conn.table(self.METER_TABLE)
|
||||||
|
|
||||||
q, start_row, stop_row = make_query(user_id=user,
|
sample_filter = storage.SampleFilter(
|
||||||
project_id=project,
|
user=user, project=project,
|
||||||
source=source,
|
start=start_timestamp, start_timestamp_op=start_timestamp_op,
|
||||||
resource_id=resource,
|
end=end_timestamp, end_timestamp_op=end_timestamp_op,
|
||||||
start=start_timestamp,
|
resource=resource, source=source, metaquery=metaquery)
|
||||||
start_op=start_timestamp_op,
|
|
||||||
end=end_timestamp,
|
q, start_row, stop_row = make_sample_query_from_filter(
|
||||||
end_op=end_timestamp_op,
|
sample_filter, require_meter=False)
|
||||||
metaquery=metaquery,
|
|
||||||
require_meter=False,
|
|
||||||
query_only=False)
|
|
||||||
LOG.debug(_("Query Meter table: %s") % q)
|
LOG.debug(_("Query Meter table: %s") % q)
|
||||||
meters = meter_table.scan(filter=q, row_start=start_row,
|
meters = meter_table.scan(filter=q, row_start=start_row,
|
||||||
row_stop=stop_row)
|
row_stop=stop_row)
|
||||||
@ -469,9 +458,8 @@ class Connection(base.Connection):
|
|||||||
if pagination:
|
if pagination:
|
||||||
raise NotImplementedError(_('Pagination not implemented'))
|
raise NotImplementedError(_('Pagination not implemented'))
|
||||||
resource_table = self.conn.table(self.RESOURCE_TABLE)
|
resource_table = self.conn.table(self.RESOURCE_TABLE)
|
||||||
q = make_query(user_id=user, project_id=project, resource_id=resource,
|
q = make_query(metaquery=metaquery, user_id=user, project_id=project,
|
||||||
source=source, metaquery=metaquery,
|
resource_id=resource, source=source)
|
||||||
require_meter=False, query_only=True)
|
|
||||||
LOG.debug(_("Query Resource table: %s") % q)
|
LOG.debug(_("Query Resource table: %s") % q)
|
||||||
|
|
||||||
gen = resource_table.scan(filter=q)
|
gen = resource_table.scan(filter=q)
|
||||||
@ -515,8 +503,8 @@ class Connection(base.Connection):
|
|||||||
|
|
||||||
meter_table = self.conn.table(self.METER_TABLE)
|
meter_table = self.conn.table(self.METER_TABLE)
|
||||||
|
|
||||||
q, start, stop = make_query_from_filter(sample_filter,
|
q, start, stop = make_sample_query_from_filter(
|
||||||
require_meter=False)
|
sample_filter, require_meter=False)
|
||||||
LOG.debug(_("Query Meter Table: %s") % q)
|
LOG.debug(_("Query Meter Table: %s") % q)
|
||||||
gen = meter_table.scan(filter=q, row_start=start, row_stop=stop)
|
gen = meter_table.scan(filter=q, row_start=start, row_stop=stop)
|
||||||
for ignored, meter in gen:
|
for ignored, meter in gen:
|
||||||
@ -568,9 +556,7 @@ class Connection(base.Connection):
|
|||||||
raise NotImplementedError("Group by not implemented.")
|
raise NotImplementedError("Group by not implemented.")
|
||||||
|
|
||||||
meter_table = self.conn.table(self.METER_TABLE)
|
meter_table = self.conn.table(self.METER_TABLE)
|
||||||
|
q, start, stop = make_sample_query_from_filter(sample_filter)
|
||||||
q, start, stop = make_query_from_filter(sample_filter)
|
|
||||||
|
|
||||||
meters = list(meter for (ignored, meter) in
|
meters = list(meter for (ignored, meter) in
|
||||||
meter_table.scan(filter=q, row_start=start,
|
meter_table.scan(filter=q, row_start=start,
|
||||||
row_stop=stop)
|
row_stop=stop)
|
||||||
@ -764,30 +750,41 @@ def reverse_timestamp(dt):
|
|||||||
return 0x7fffffffffffffff - ts
|
return 0x7fffffffffffffff - ts
|
||||||
|
|
||||||
|
|
||||||
def make_query(meter=None, start=None, start_op=None,
|
def make_timestamp_query(func, start=None, start_op=None, end=None,
|
||||||
end=None, end_op=None, metaquery=None,
|
end_op=None, bounds_only=False, **kwargs):
|
||||||
require_meter=True, query_only=False,
|
"""Return a filter start and stop row for filtering and a query
|
||||||
include_rts_in_filters=True, **kwargs):
|
which based on the fact that CF-name is 'rts'
|
||||||
"""Return a filter query string based on the selected parameters.
|
|
||||||
|
|
||||||
:param meter: Optional counter-name
|
|
||||||
:param start: Optional start timestamp
|
:param start: Optional start timestamp
|
||||||
:param start_op: Optional start timestamp operator, like gt, ge
|
:param start_op: Optional start timestamp operator, like gt, ge
|
||||||
:param end: Optional end timestamp
|
:param end: Optional end timestamp
|
||||||
:param end_op: Optional end timestamp operator, like lt, le
|
:param end_op: Optional end timestamp operator, like lt, le
|
||||||
:param require_meter: If true and the filter does not have a meter,
|
:param bounds_only: if True than query will not be returned
|
||||||
raise an error.
|
:param func: a function that provide a format of row
|
||||||
:param query_only: If true only returns the filter query,
|
:param kwargs: kwargs for :param func
|
||||||
otherwise also returns start and stop rowkeys
|
|
||||||
"""
|
"""
|
||||||
|
rts_start, rts_end = get_start_end_rts(start, start_op, end, end_op)
|
||||||
|
start_row, end_row = func(rts_start, rts_end, **kwargs)
|
||||||
|
|
||||||
|
if bounds_only:
|
||||||
|
return start_row, end_row
|
||||||
|
|
||||||
q = []
|
q = []
|
||||||
|
if rts_start:
|
||||||
|
q.append("SingleColumnValueFilter ('f', 'rts', <=, 'binary:%s')" %
|
||||||
|
rts_start)
|
||||||
|
if rts_end:
|
||||||
|
q.append("SingleColumnValueFilter ('f', 'rts', >=, 'binary:%s')" %
|
||||||
|
rts_end)
|
||||||
|
|
||||||
for key, value in kwargs.iteritems():
|
res_q = None
|
||||||
if value is not None:
|
if len(q):
|
||||||
q.append("SingleColumnValueFilter "
|
res_q = " AND ".join(q)
|
||||||
"('f', '%s', =, 'binary:%s')" % (key, value))
|
|
||||||
|
return start_row, end_row, res_q
|
||||||
|
|
||||||
|
|
||||||
|
def get_start_end_rts(start, start_op, end, end_op):
|
||||||
|
|
||||||
start_row, end_row = "", ""
|
|
||||||
rts_start = str(reverse_timestamp(start) + 1) if start else ""
|
rts_start = str(reverse_timestamp(start) + 1) if start else ""
|
||||||
rts_end = str(reverse_timestamp(end) + 1) if end else ""
|
rts_end = str(reverse_timestamp(end) + 1) if end else ""
|
||||||
|
|
||||||
@ -797,26 +794,22 @@ def make_query(meter=None, start=None, start_op=None,
|
|||||||
if end_op == 'le':
|
if end_op == 'le':
|
||||||
rts_end = str(long(rts_end) - 1)
|
rts_end = str(long(rts_end) - 1)
|
||||||
|
|
||||||
# when start_time and end_time is provided,
|
return rts_start, rts_end
|
||||||
# if it's filtered by meter,
|
|
||||||
# rowkey will be used in the query;
|
|
||||||
# else it's non meter filter query(e.g. project_id, user_id etc),
|
|
||||||
# SingleColumnValueFilter against rts will be appended to the query
|
|
||||||
# query other tables should have no start and end passed in
|
|
||||||
if meter:
|
|
||||||
start_row, end_row = _make_rowkey_scan(meter, rts_start, rts_end)
|
|
||||||
q.append("SingleColumnValueFilter "
|
|
||||||
"('f', 'counter_name', =, 'binary:%s')" % meter)
|
|
||||||
elif require_meter:
|
|
||||||
raise RuntimeError('Missing required meter specifier')
|
|
||||||
elif include_rts_in_filters:
|
|
||||||
if rts_start:
|
|
||||||
q.append("SingleColumnValueFilter ('f', 'rts', <=, 'binary:%s')" %
|
|
||||||
rts_start)
|
|
||||||
if rts_end:
|
|
||||||
q.append("SingleColumnValueFilter ('f', 'rts', >=, 'binary:%s')" %
|
|
||||||
rts_end)
|
|
||||||
|
|
||||||
|
|
||||||
|
def make_query(metaquery=None, **kwargs):
|
||||||
|
"""Return a filter query string based on the selected parameters.
|
||||||
|
|
||||||
|
:param metaquery: optional metaquery dict
|
||||||
|
:param kwargs: key-value pairs to filter on. Key should be a real
|
||||||
|
column name in db
|
||||||
|
"""
|
||||||
|
q = []
|
||||||
|
|
||||||
|
for key, value in kwargs.iteritems():
|
||||||
|
if value is not None:
|
||||||
|
q.append("SingleColumnValueFilter "
|
||||||
|
"('f', '%s', =, 'binary:%s')" % (key, value))
|
||||||
res_q = None
|
res_q = None
|
||||||
if len(q):
|
if len(q):
|
||||||
res_q = " AND ".join(q)
|
res_q = " AND ".join(q)
|
||||||
@ -834,41 +827,51 @@ def make_query(meter=None, start=None, start_op=None,
|
|||||||
else:
|
else:
|
||||||
res_q = meta_q # metaquery only
|
res_q = meta_q # metaquery only
|
||||||
|
|
||||||
if query_only:
|
return res_q or ""
|
||||||
return res_q
|
|
||||||
else:
|
|
||||||
return res_q, start_row, end_row
|
|
||||||
|
|
||||||
|
|
||||||
def make_query_from_filter(sample_filter, require_meter=True):
|
def make_sample_query_from_filter(sample_filter, require_meter=True):
|
||||||
"""Return a query dictionary based on the settings in the filter.
|
"""Return a query dictionary based on the settings in the filter.
|
||||||
|
|
||||||
:param sample_filter: SampleFilter instance
|
:param sample_filter: SampleFilter instance
|
||||||
:param require_meter: If true and the filter does not have a meter,
|
:param require_meter: If true and the filter does not have a meter,
|
||||||
raise an error.
|
raise an error.
|
||||||
"""
|
"""
|
||||||
return make_query(user_id=sample_filter.user,
|
meter = sample_filter.meter
|
||||||
|
if not meter and require_meter:
|
||||||
|
raise RuntimeError('Missing required meter specifier')
|
||||||
|
start_row, end_row, ts_query = make_timestamp_query(
|
||||||
|
_make_general_rowkey_scan,
|
||||||
|
start=sample_filter.start, start_op=sample_filter.start_timestamp_op,
|
||||||
|
end=sample_filter.end, end_op=sample_filter.end_timestamp_op,
|
||||||
|
some_id=meter)
|
||||||
|
|
||||||
|
q = make_query(metaquery=sample_filter.metaquery,
|
||||||
|
user_id=sample_filter.user,
|
||||||
project_id=sample_filter.project,
|
project_id=sample_filter.project,
|
||||||
meter=sample_filter.meter,
|
counter_name=meter,
|
||||||
resource_id=sample_filter.resource,
|
resource_id=sample_filter.resource,
|
||||||
source=sample_filter.source,
|
source=sample_filter.source,
|
||||||
start=sample_filter.start,
|
message_id=sample_filter.message_id)
|
||||||
start_op=sample_filter.start_timestamp_op,
|
|
||||||
end=sample_filter.end,
|
if q:
|
||||||
end_op=sample_filter.end_timestamp_op,
|
ts_query = (" AND " + ts_query) if ts_query else ""
|
||||||
metaquery=sample_filter.metaquery,
|
res_q = q + ts_query if ts_query else q
|
||||||
message_id=sample_filter.message_id,
|
else:
|
||||||
require_meter=require_meter)
|
res_q = ts_query if ts_query else None
|
||||||
|
return res_q, start_row, end_row
|
||||||
|
|
||||||
|
|
||||||
def _make_rowkey_scan(meter, rts_start=None, rts_end=None):
|
def _make_general_rowkey_scan(rts_start=None, rts_end=None, some_id=None):
|
||||||
"""If it's meter filter without start and end,
|
"""If it's filter on some_id without start and end,
|
||||||
start_row = meter while end_row = meter + MAX_BYTE
|
start_row = some_id while end_row = some_id + MAX_BYTE
|
||||||
"""
|
"""
|
||||||
|
if some_id is None:
|
||||||
|
return None, None
|
||||||
if not rts_start:
|
if not rts_start:
|
||||||
rts_start = chr(127)
|
rts_start = chr(127)
|
||||||
end_row = "%s_%s" % (meter, rts_start)
|
end_row = "%s_%s" % (some_id, rts_start)
|
||||||
start_row = "%s_%s" % (meter, rts_end)
|
start_row = "%s_%s" % (some_id, rts_end)
|
||||||
|
|
||||||
return start_row, end_row
|
return start_row, end_row
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user