monasca-api/monasca/common/repositories/mysql/alarm_definitions_repositor...

298 lines
12 KiB
Python

# Copyright 2014 Hewlett-Packard
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
from monasca.common.repositories import alarm_definitions_repository
from monasca.common.repositories.exceptions import DoesNotExistException
from monasca.common.repositories.mysql.mysql_repository import MySQLRepository
from monasca.common.repositories.mysql.mysql_repository import mysql_try_catch_block
from monasca.openstack.common import log
from monasca.openstack.common import uuidutils
from monasca.common.repositories import exceptions
LOG = log.getLogger(__name__)
class AlarmDefinitionsRepository(MySQLRepository,
alarm_definitions_repository.AlarmDefinitionsRepository):
base_query = """
select ad.id, ad.name, ad.description, ad.expression,
ad.match_by, ad.severity, ad.actions_enabled,
aaa.alarm_actions, aao.ok_actions, aau.undetermined_actions
from alarm_definition as ad
left join (select alarm_definition_id,
group_concat(action_id) as alarm_actions
from alarm_action
where alarm_state = 'ALARM'
group by alarm_definition_id) as aaa
on aaa.alarm_definition_id = ad.id
left join (select alarm_definition_id,
group_concat(action_id) as ok_actions
from alarm_action
where alarm_state = 'OK'
group by alarm_definition_id) as aao
on aao.alarm_definition_id = ad.id
left join (select alarm_definition_id,
group_concat(action_id) as undetermined_actions
from alarm_action
where alarm_state = 'UNDETERMINED'
group by alarm_definition_id) as aau
on aau.alarm_definition_id = ad.id
"""
def __init__(self):
super(AlarmDefinitionsRepository, self).__init__()
@mysql_try_catch_block
def get_alarm_definition(self, tenant_id, id):
parms = [tenant_id, id]
where_clause = """ where ad.tenant_id = ?
and ad.id = ?
and deleted_at is NULL """
query = AlarmDefinitionsRepository.base_query + where_clause
rows = self._execute_query(query, parms)
if rows:
return rows[0]
else:
raise DoesNotExistException
@mysql_try_catch_block
def get_alarm_definitions(self, tenant_id, name, dimensions):
parms = [tenant_id]
select_clause = AlarmDefinitionsRepository.base_query
where_clause = " where ad.tenant_id = ? and deleted_at is NULL "
if name:
where_clause += " and ad.name = ? "
parms.append(name.encode('utf8'))
order_by_clause = " order by ad.created_at "
if dimensions:
inner_join = """ inner join sub_alarm_definition as sad
on sad.alarm_definition_id = ad.id """
i = 0
inner_join_parms = []
for n, v in dimensions.iteritems():
inner_join += """
inner join
(select distinct sub_alarm_definition_id
from sub_alarm_definition_dimension
where dimension_name = ? and value = ?) as sadd{}
on sadd{}.sub_alarm_definition_id = sad.id
""".format(i, i)
inner_join_parms += [n.encode('utf8'), v.encode('utf8')]
i += 1
select_clause += inner_join
parms = inner_join_parms + parms
query = select_clause + where_clause + order_by_clause
return self._execute_query(query, parms)
@mysql_try_catch_block
def get_sub_alarms(self, tenant_id, alarm_definition_id):
parms = [tenant_id, alarm_definition_id]
query = """select distinct sa.id as sub_alarm_id, sa.alarm_id,
sa.expression
from sub_alarm as sa
inner join alarm as a
on a.id = sa.alarm_id
inner join alarm_definition as ad
on ad.id = a.alarm_definition_id
where ad.tenant_id = ? and ad.id = ?
"""
return self._execute_query(query, parms)
@mysql_try_catch_block
def get_alarm_metrics(self, tenant_id, alarm_definition_id):
parms = [tenant_id, alarm_definition_id]
query = """select distinct a.id as alarm_id, md.name,
mdg.dimensions
from alarm as a
inner join alarm_definition as ad
on ad.id = a.alarm_definition_id
inner join alarm_metric as am on am.alarm_id = a.id
inner join metric_definition_dimensions as mdd
on mdd.id = am.metric_definition_dimensions_id
inner join metric_definition as md
on md.id = mdd.metric_definition_id
left join (select dimension_set_id,
group_concat(name, '=', value) as dimensions
from metric_dimension group by dimension_set_id) as mdg
on mdg.dimension_set_id = mdd.metric_dimension_set_id
where ad.tenant_id = ? and ad.id = ?
order by a.id
"""
return self._execute_query(query, parms)
@mysql_try_catch_block
def delete_alarm_definition(self, tenant_id, alarm_definition_id):
"""Soft delete the alarm definition.
Soft delete the alarm definition and hard delete any associated
alarms.
:param tenant_id:
:param alarm_definition_id:
:returns True: -- if alarm definition exists and was deleted.
:returns False: -- if the alarm definition does not exists.
:raises RepositoryException:
"""
cnxn, cursor = self._get_cnxn_cursor_tuple()
cursor.execute("""update alarm_definition
set deleted_at = NOW()
where tenant_id = ? and id = ? and deleted_at is NULL""",
[tenant_id, alarm_definition_id])
if cursor.rowcount < 1:
self._commit_close_cnxn(cnxn)
return False
cursor.execute("""delete from alarm where alarm_definition_id = ?""",
[alarm_definition_id])
self._commit_close_cnxn(cnxn)
return True
@mysql_try_catch_block
def get_sub_alarm_definitions(self, alarm_definition_id):
parms = [alarm_definition_id]
query = """select sad.*, sadd.dimensions
from sub_alarm_definition as sad
left join (select sub_alarm_definition_id,
group_concat(dimension_name, '=', value)
as dimensions
from sub_alarm_definition_dimension
group by sub_alarm_definition_id)
as sadd
on sadd.sub_alarm_definition_id = sad.id
where sad.alarm_definition_id = ?
"""
return self._execute_query(query, parms)
@mysql_try_catch_block
def create_alarm_definition(self, tenant_id, name, expression,
sub_expr_list, description, severity, match_by,
alarm_actions, undetermined_actions,
ok_actions):
cnxn, cursor = self._get_cnxn_cursor_tuple()
now = datetime.datetime.utcnow()
alarm_definition_id = uuidutils.generate_uuid()
cursor.execute("""insert into alarm_definition(
id,
tenant_id,
name,
description,
expression,
severity,
match_by,
actions_enabled,
created_at,
updated_at)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
alarm_definition_id, tenant_id, name.encode('utf8'),
description.encode('utf8'), expression.encode('utf8'),
severity.upper().encode('utf8'),
",".join(match_by).encode('utf8'), 1, now, now)
for sub_expr in sub_expr_list:
sub_alarm_definition_id = uuidutils.generate_uuid()
sub_expr.id = sub_alarm_definition_id
cursor.execute("""insert into sub_alarm_definition(
id,
alarm_definition_id,
function,
metric_name,
operator,
threshold,
period,
periods,
created_at,
updated_at)
values(?,?,?,?,?,?,?,?,?,?)""",
sub_alarm_definition_id, alarm_definition_id,
sub_expr.normalized_func.encode('utf8'),
sub_expr.normalized_metric_name.encode("utf8"),
sub_expr.normalized_operator.encode('utf8'),
sub_expr.threshold.encode('utf8'),
sub_expr.period.encode('utf8'),
sub_expr.periods.encode('utf8'), now, now)
for dimension in sub_expr.dimensions_as_list:
parsed_dimension = dimension.split('=')
cursor.execute("""insert into sub_alarm_definition_dimension(
sub_alarm_definition_id,
dimension_name,
value)
values(?,?,?)""", sub_alarm_definition_id,
parsed_dimension[0].encode('utf8'),
parsed_dimension[1].encode('utf8'))
self._insert_into_alarm_action(cursor, alarm_definition_id,
alarm_actions, u"ALARM")
self._insert_into_alarm_action(cursor, alarm_definition_id,
undetermined_actions, u"UNDETERMINED")
self._insert_into_alarm_action(cursor, alarm_definition_id, ok_actions,
u"OK")
self._commit_close_cnxn(cnxn)
return alarm_definition_id
def _insert_into_alarm_action(self, cursor, alarm_definition_id, actions,
alarm_state):
for action in actions:
cursor.execute("select id from notification_method where id = ?",
action.encode('utf8'))
row = cursor.fetchone()
if not row:
raise exceptions.RepositoryException(
"Non-existent notification id {} submitted for {} "
"notification action".format(action.encode('utf8'),
alarm_state.encode('utf8')))
cursor.execute("""insert into alarm_action(
alarm_definition_id,
alarm_state,
action_id)
values(?,?,?)""", alarm_definition_id,
alarm_state.encode('utf8'), action.encode('utf8'))