From: almagia Date: Sat, 30 Nov 2019 02:56:04 +0000 (+0100) Subject: Re-Revert "Revert "Migrates alarms to MongoDB"" approved by TSC X-Git-Tag: v7.0.0rc1~8 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F78%2F8278%2F1;p=osm%2FMON.git Re-Revert "Revert "Migrates alarms to MongoDB"" approved by TSC This reverts commit 628df021896fa8775f9743af62a4267b617cc35c. Change-Id: Ie07a6856ee3f2e15c539d52afc4c7e5ecc07ca95 --- diff --git a/docs/architecture.md b/docs/architecture.md index 8e90ab9..cec6697 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -50,7 +50,7 @@ MON Server subscribes to the message bus and waits for the following messages: It performs the corresponding action and sends a response through a unique topic made of 'alarm_response_' plus a correlation_id, which is a field contained in the request message. -Alarms are stored in MON database in the OSM MySQL engine. +Alarms are stored in MON database in the OSM MongoDB engine. ## MON Collector diff --git a/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg b/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg index 930380f..0e2e676 100644 Binary files a/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg and b/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg differ diff --git a/docs/assets/MON_Overview_Diagram.jpg b/docs/assets/MON_Overview_Diagram.jpg index c804347..e6f8b78 100644 Binary files a/docs/assets/MON_Overview_Diagram.jpg and b/docs/assets/MON_Overview_Diagram.jpg differ diff --git a/docs/assets/MON_Server_Create_Alarm.jpg b/docs/assets/MON_Server_Create_Alarm.jpg index a4b6b9d..5feeebc 100644 Binary files a/docs/assets/MON_Server_Create_Alarm.jpg and b/docs/assets/MON_Server_Create_Alarm.jpg differ diff --git a/osm_mon/cmd/mon_collector.py b/osm_mon/cmd/mon_collector.py index 3e493de..94c3883 100644 --- a/osm_mon/cmd/mon_collector.py +++ b/osm_mon/cmd/mon_collector.py @@ -27,12 +27,11 @@ import sys from osm_mon.collector.collector import Collector from osm_mon.core.config import Config -from osm_mon.core.database import DatabaseManager def main(): - parser = argparse.ArgumentParser(prog='osm-policy-agent') - parser.add_argument('--config-file', nargs='?', help='POL configuration file') + parser = argparse.ArgumentParser(prog='osm-mon-collector') + parser.add_argument('--config-file', nargs='?', help='MON configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -48,9 +47,6 @@ def main(): log.info("Starting MON Collector...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") - db_manager = DatabaseManager(cfg) - db_manager.create_tables() - log.info("Database initialized correctly.") collector = Collector(cfg) collector.collect_forever() diff --git a/osm_mon/cmd/mon_evaluator.py b/osm_mon/cmd/mon_evaluator.py index 3835d7e..ba9a420 100644 --- a/osm_mon/cmd/mon_evaluator.py +++ b/osm_mon/cmd/mon_evaluator.py @@ -26,13 +26,12 @@ import logging import sys from osm_mon.core.config import Config -from osm_mon.core.database import DatabaseManager from osm_mon.evaluator.evaluator import Evaluator def main(): - parser = argparse.ArgumentParser(prog='osm-policy-agent') - parser.add_argument('--config-file', nargs='?', help='POL configuration file') + parser = argparse.ArgumentParser(prog='osm-mon-evaluator') + parser.add_argument('--config-file', nargs='?', help='MON configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -48,9 +47,6 @@ def main(): log.info("Starting MON Evaluator...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") - db_manager = DatabaseManager(cfg) - db_manager.create_tables() - log.info("Database initialized correctly.") evaluator = Evaluator(cfg) evaluator.evaluate_forever() diff --git a/osm_mon/cmd/mon_server.py b/osm_mon/cmd/mon_server.py index 6698339..e05f4b8 100644 --- a/osm_mon/cmd/mon_server.py +++ b/osm_mon/cmd/mon_server.py @@ -27,13 +27,12 @@ import logging import sys from osm_mon.core.config import Config -from osm_mon.core.database import DatabaseManager from osm_mon.server.server import Server def main(): - parser = argparse.ArgumentParser(prog='osm-policy-agent') - parser.add_argument('--config-file', nargs='?', help='POL configuration file') + parser = argparse.ArgumentParser(prog='osm-mon-server') + parser.add_argument('--config-file', nargs='?', help='MON configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -49,9 +48,6 @@ def main(): log.info("Starting MON Server...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") - db_manager = DatabaseManager(cfg) - db_manager.create_tables() - log.info("Database initialized correctly.") loop = asyncio.get_event_loop() server = Server(cfg, loop) server.run() diff --git a/osm_mon/core/common_db.py b/osm_mon/core/common_db.py index 8f2f552..f15ae97 100644 --- a/osm_mon/core/common_db.py +++ b/osm_mon/core/common_db.py @@ -21,9 +21,12 @@ # For those usages not covered by the Apache License, Version 2.0 please # contact: bdiaz@whitestack.com or glavado@whitestack.com ## +from typing import List + from osm_common import dbmongo, dbmemory from osm_mon.core.config import Config +from osm_mon.core.models import Alarm class CommonDbClient: @@ -132,3 +135,16 @@ class CommonDbClient: def get_project(self, project_id: str): return self.common_db.get_one('projects', {'_id': project_id}) + + def create_alarm(self, alarm: Alarm): + return self.common_db.create('alarms', alarm.to_dict()) + + def delete_alarm(self, alarm_uuid: str): + return self.common_db.del_one('alarms', {'uuid': alarm_uuid}) + + def get_alarms(self) -> List[Alarm]: + alarms = [] + alarm_dicts = self.common_db.get_list('alarms') + for alarm_dict in alarm_dicts: + alarms.append(Alarm.from_dict(alarm_dict)) + return alarms diff --git a/osm_mon/core/database.py b/osm_mon/core/database.py deleted file mode 100644 index 61bd180..0000000 --- a/osm_mon/core/database.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## - -import logging -import os -from typing import Iterable - -from peewee import CharField, FloatField, Model, AutoField, Proxy, ForeignKeyField -from peewee_migrate import Router -from playhouse.db_url import connect - -from osm_mon import migrations -from osm_mon.core.config import Config - -log = logging.getLogger(__name__) - -db = Proxy() - - -class BaseModel(Model): - id = AutoField(primary_key=True) - - class Meta: - database = db - - -class Alarm(BaseModel): - uuid = CharField(unique=True) - name = CharField() - severity = CharField() - threshold = FloatField() - operation = CharField() - statistic = CharField() - metric = CharField() - - -class AlarmTag(BaseModel): - name = CharField() - value = CharField() - alarm = ForeignKeyField(Alarm, related_name='tags', on_delete='CASCADE') - - -class DatabaseManager: - def __init__(self, config: Config): - db.initialize(connect(config.get('sql', 'database_uri'))) - - def create_tables(self) -> None: - db.connect() - with db.atomic(): - router = Router(db, os.path.dirname(migrations.__file__)) - router.run() - db.close() - - -class AlarmTagRepository: - @staticmethod - def create(**query) -> Alarm: - return AlarmTag.create(**query) - - -class AlarmRepository: - @staticmethod - def create(**query) -> Alarm: - return Alarm.create(**query) - - @staticmethod - def get(*expressions) -> Alarm: - return Alarm.select().where(*expressions).get() - - @staticmethod - def list(*expressions) -> Iterable[Alarm]: - if expressions == (): - return Alarm.select() - else: - return Alarm.select().where(*expressions) diff --git a/osm_mon/core/models.py b/osm_mon/core/models.py new file mode 100644 index 0000000..1810c9b --- /dev/null +++ b/osm_mon/core/models.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## +import uuid + + +class Alarm: + + def __init__(self, name: str = None, severity: str = None, threshold: float = None, operation: str = None, + statistic: str = None, metric: str = None, tags: dict = {}): + self.uuid = str(uuid.uuid4()) + self.name = name + self.severity = severity + self.threshold = threshold + self.operation = operation + self.statistic = statistic + self.metric = metric + self.tags = tags + + def to_dict(self) -> dict: + alarm = { + 'uuid': self.uuid, + 'name': self.name, + 'severity': self.severity, + 'threshold': self.threshold, + 'statistic': self.statistic, + 'metric': self.metric, + 'tags': self.tags + } + return alarm + + @staticmethod + def from_dict(data: dict): + alarm = Alarm() + alarm.uuid = data.get('uuid', str(uuid.uuid4())) + alarm.name = data.get('name') + alarm.severity = data.get('severity') + alarm.threshold = data.get('threshold') + alarm.statistic = data.get('statistic') + alarm.metric = data.get('metric') + alarm.tags = data.get('tags') + return alarm diff --git a/osm_mon/evaluator/evaluator.py b/osm_mon/evaluator/evaluator.py index 2f22625..cc9a8ad 100644 --- a/osm_mon/evaluator/evaluator.py +++ b/osm_mon/evaluator/evaluator.py @@ -28,8 +28,8 @@ import time import peewee from osm_mon.core.config import Config -from osm_mon.core.database import Alarm from osm_mon.core.message_bus_client import MessageBusClient +from osm_mon.core.models import Alarm from osm_mon.core.response import ResponseBuilder from osm_mon.evaluator.service import EvaluatorService, AlarmStatus diff --git a/osm_mon/evaluator/service.py b/osm_mon/evaluator/service.py index de3798b..b3b0d26 100644 --- a/osm_mon/evaluator/service.py +++ b/osm_mon/evaluator/service.py @@ -25,10 +25,9 @@ import multiprocessing from enum import Enum from typing import Tuple, List -from osm_mon.core import database from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.database import Alarm, AlarmRepository +from osm_mon.core.models import Alarm from osm_mon.evaluator.backends.prometheus import PrometheusBackend log = logging.getLogger(__name__) @@ -57,11 +56,11 @@ class EvaluatorService: return BACKENDS[self.conf.get('evaluator', 'backend')](self.conf).get_metric_value(metric_name, tags) def _evaluate_metric(self, - alarm: Alarm, tags: dict): + alarm: Alarm): log.debug("_evaluate_metric") - metric_value = self._get_metric_value(alarm.metric, tags) + metric_value = self._get_metric_value(alarm.metric, alarm.tags) if metric_value is None: - log.warning("No metric result for alarm %s", alarm.id) + log.warning("No metric result for alarm %s", alarm.uuid) self.queue.put((alarm, AlarmStatus.INSUFFICIENT)) else: if alarm.operation.upper() == 'GT': @@ -78,25 +77,15 @@ class EvaluatorService: def evaluate_alarms(self) -> List[Tuple[Alarm, AlarmStatus]]: log.debug('evaluate_alarms') processes = [] - database.db.connect() - try: - with database.db.atomic(): - for alarm in AlarmRepository.list(): - # Tags need to be passed inside a dict to avoid database locking issues related to process forking - tags = {} - for tag in alarm.tags: - tags[tag.name] = tag.value - p = multiprocessing.Process(target=self._evaluate_metric, - args=(alarm, tags)) - processes.append(p) - p.start() - - for process in processes: - process.join(timeout=10) - alarms_tuples = [] - log.info("Appending alarms to queue") - while not self.queue.empty(): - alarms_tuples.append(self.queue.get()) - return alarms_tuples - finally: - database.db.close() + for alarm in self.common_db.get_alarms(): + p = multiprocessing.Process(target=self._evaluate_metric, + args=(alarm,)) + processes.append(p) + p.start() + + for process in processes: + process.join(timeout=10) + alarms_tuples = [] + while not self.queue.empty(): + alarms_tuples.append(self.queue.get()) + return alarms_tuples diff --git a/osm_mon/migrations/002_add_alarm_tags.py b/osm_mon/migrations/002_add_alarm_tags.py deleted file mode 100644 index 22f5de8..0000000 --- a/osm_mon/migrations/002_add_alarm_tags.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## -"""Peewee migrations -- 002_add_alarm_tags.py. - -Some examples (model - class or model name):: - - > Model = migrator.orm['model_name'] # Return model in current state by name - - > migrator.sql(sql) # Run custom SQL - > migrator.python(func, *args, **kwargs) # Run python code - > migrator.create_model(Model) # Create a model (could be used as decorator) - > migrator.remove_model(model, cascade=True) # Remove a model - > migrator.add_fields(model, **fields) # Add fields to a model - > migrator.change_fields(model, **fields) # Change fields - > migrator.remove_fields(model, *field_names, cascade=True) - > migrator.rename_field(model, old_field_name, new_field_name) - > migrator.rename_table(model, new_table_name) - > migrator.add_index(model, *col_names, unique=False) - > migrator.drop_index(model, *col_names) - > migrator.add_not_null(model, *field_names) - > migrator.drop_not_null(model, *field_names) - > migrator.add_default(model, field_name, default) - -""" - -import peewee as pw - -SQL = pw.SQL - - -def migrate(migrator, database, fake=False, **kwargs): - """Write your migrations here.""" - - @migrator.create_model - class AlarmTag(pw.Model): - id = pw.AutoField() - name = pw.CharField(max_length=255) - value = pw.CharField(max_length=255) - alarm = pw.ForeignKeyField(backref='tags', column_name='alarm_id', field='id', - model=migrator.orm['alarm'], on_delete='CASCADE') - - class Meta: - table_name = "alarmtag" - - -def rollback(migrator, database, fake=False, **kwargs): - """Write your rollback migrations here.""" - - migrator.remove_model('alarmtag') diff --git a/osm_mon/migrations/003_rename_monitoring_param.py b/osm_mon/migrations/003_rename_monitoring_param.py deleted file mode 100644 index 2d5108f..0000000 --- a/osm_mon/migrations/003_rename_monitoring_param.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## -"""Peewee migrations -- 003_rename_monitoring_param.py. - -Some examples (model - class or model name):: - - > Model = migrator.orm['model_name'] # Return model in current state by name - - > migrator.sql(sql) # Run custom SQL - > migrator.python(func, *args, **kwargs) # Run python code - > migrator.create_model(Model) # Create a model (could be used as decorator) - > migrator.remove_model(model, cascade=True) # Remove a model - > migrator.add_fields(model, **fields) # Add fields to a model - > migrator.change_fields(model, **fields) # Change fields - > migrator.remove_fields(model, *field_names, cascade=True) - > migrator.rename_field(model, old_field_name, new_field_name) - > migrator.rename_table(model, new_table_name) - > migrator.add_index(model, *col_names, unique=False) - > migrator.drop_index(model, *col_names) - > migrator.add_not_null(model, *field_names) - > migrator.drop_not_null(model, *field_names) - > migrator.add_default(model, field_name, default) - -""" - -import peewee as pw - -SQL = pw.SQL - - -def migrate(migrator, database, fake=False, **kwargs): - """Write your migrations here.""" - - migrator.rename_field('alarm', 'monitoring_param', 'metric') - - -def rollback(migrator, database, fake=False, **kwargs): - """Write your rollback migrations here.""" - - migrator.rename_field('alarm', 'metric', 'monitoring_param') diff --git a/osm_mon/migrations/004_remove_alarm_fields.py b/osm_mon/migrations/004_remove_alarm_fields.py deleted file mode 100644 index b9477ac..0000000 --- a/osm_mon/migrations/004_remove_alarm_fields.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## -"""Peewee migrations -- 004_remove_alarm_fields.py. - -Some examples (model - class or model name):: - - > Model = migrator.orm['model_name'] # Return model in current state by name - - > migrator.sql(sql) # Run custom SQL - > migrator.python(func, *args, **kwargs) # Run python code - > migrator.create_model(Model) # Create a model (could be used as decorator) - > migrator.remove_model(model, cascade=True) # Remove a model - > migrator.add_fields(model, **fields) # Add fields to a model - > migrator.change_fields(model, **fields) # Change fields - > migrator.remove_fields(model, *field_names, cascade=True) - > migrator.rename_field(model, old_field_name, new_field_name) - > migrator.rename_table(model, new_table_name) - > migrator.add_index(model, *col_names, unique=False) - > migrator.drop_index(model, *col_names) - > migrator.add_not_null(model, *field_names) - > migrator.drop_not_null(model, *field_names) - > migrator.add_default(model, field_name, default) - -""" - -import peewee as pw - -SQL = pw.SQL - - -def migrate(migrator, database, fake=False, **kwargs): - """Write your migrations here.""" - - migrator.remove_fields('alarm', 'vdur_name', 'vnf_member_index', 'nsr_id') - - -def rollback(migrator, database, fake=False, **kwargs): - """Write your rollback migrations here.""" - - migrator.add_fields('alarm', - vdur_name=pw.CharField(max_length=255), - vnf_member_index=pw.CharField(max_length=255), - nsr_id=pw.CharField(max_length=255)) diff --git a/osm_mon/migrations/__init__.py b/osm_mon/migrations/__init__.py deleted file mode 100644 index d81308a..0000000 --- a/osm_mon/migrations/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## diff --git a/osm_mon/migrations/conf.py b/osm_mon/migrations/conf.py deleted file mode 100644 index c6bda5a..0000000 --- a/osm_mon/migrations/conf.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. - -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## -import os - -DATABASE = os.getenv('OSMMON_SQL_DATABASE_URI', 'sqlite://') diff --git a/osm_mon/server/service.py b/osm_mon/server/service.py index 1d546e3..60cb3ec 100755 --- a/osm_mon/server/service.py +++ b/osm_mon/server/service.py @@ -21,12 +21,10 @@ # contact: bdiaz@whitestack.com or glavado@whitestack.com ## import logging -import uuid -from osm_mon.core import database from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.database import AlarmRepository, Alarm, AlarmTagRepository +from osm_mon.core.models import Alarm log = logging.getLogger(__name__) @@ -38,41 +36,16 @@ class ServerService: def create_alarm(self, name: str, - threshold: str, + threshold: float, operation: str, severity: str, statistic: str, metric_name: str, tags: dict) -> Alarm: - database.db.connect() - try: - with database.db.atomic(): - alarm = AlarmRepository.create( - uuid=str(uuid.uuid4()), - name=name, - threshold=threshold, - operation=operation.lower(), - severity=severity.lower(), - statistic=statistic.lower(), - metric=metric_name - ) - for k, v in tags.items(): - AlarmTagRepository.create( - name=k, - value=v, - alarm=alarm - ) - return alarm - - finally: - database.db.close() + alarm = Alarm(name, severity, threshold, operation, statistic, metric_name, tags) + self.common_db.create_alarm(alarm) + return alarm def delete_alarm(self, alarm_uuid: str) -> None: - database.db.connect() - try: - with database.db.atomic(): - alarm = AlarmRepository.get(Alarm.uuid == alarm_uuid) - alarm.delete_instance() - finally: - database.db.close() + self.common_db.delete_alarm(alarm_uuid) diff --git a/osm_mon/tests/unit/core/test_common_db_client.py b/osm_mon/tests/unit/core/test_common_db_client.py index e584149..7102226 100644 --- a/osm_mon/tests/unit/core/test_common_db_client.py +++ b/osm_mon/tests/unit/core/test_common_db_client.py @@ -27,6 +27,7 @@ from osm_common import dbmongo from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config +from osm_mon.core.models import Alarm class CommonDbClientTest(unittest.TestCase): @@ -146,3 +147,37 @@ class CommonDbClientTest(unittest.TestCase): decrypt_vim_password.assert_any_call('vim_password', schema_version, vim_id) self.assertRaises(AssertionError, decrypt_vim_password.assert_any_call, 'vrops_password', schema_version, vim_id) + + @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) + @mock.patch.object(dbmongo.DbMongo, "get_list") + def test_get_alarms(self, get_list): + get_list.return_value = [{ + 'uuid': '1', + 'name': 'name', + 'severity': 'severity', + 'threshold': 50, + 'operation': 'operation', + 'statistic': 'statistic', + 'tags': {}, + }] + + common_db_client = CommonDbClient(self.config) + alarms = common_db_client.get_alarms() + self.assertEqual('1', alarms[0].uuid) + + @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) + @mock.patch.object(dbmongo.DbMongo, "create") + def test_create_alarm(self, create): + alarm = Alarm('name', 'severity', 50.0, 'operation', 'statistic', 'metric', {}) + alarm.uuid = '1' + common_db_client = CommonDbClient(self.config) + common_db_client.create_alarm(alarm) + create.assert_called_with('alarms', {'tags': {}, 'threshold': 50.0, 'metric': 'metric', 'severity': 'severity', + 'statistic': 'statistic', 'name': 'name', 'uuid': '1'}) + + @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) + @mock.patch.object(dbmongo.DbMongo, "del_one") + def test_delete_alarm(self, delete): + common_db_client = CommonDbClient(self.config) + common_db_client.delete_alarm('1') + delete.assert_called_with('alarms', {'uuid': '1'}) diff --git a/osm_mon/tests/unit/evaluator/test_evaluator.py b/osm_mon/tests/unit/evaluator/test_evaluator.py index b20f602..43cec96 100644 --- a/osm_mon/tests/unit/evaluator/test_evaluator.py +++ b/osm_mon/tests/unit/evaluator/test_evaluator.py @@ -39,8 +39,7 @@ class EvaluatorTest(TestCase): @mock.patch('multiprocessing.Process') @mock.patch.object(Evaluator, "notify_alarm") @mock.patch.object(EvaluatorService, "evaluate_alarms") - @mock.patch('osm_mon.core.database.db') - def test_evaluate(self, db, evaluate_alarms, notify_alarm, process): + def test_evaluate(self, evaluate_alarms, notify_alarm, process): mock_alarm = mock.Mock() mock_alarm.operation = 'gt' mock_alarm.threshold = 50.0 diff --git a/osm_mon/tests/unit/evaluator/test_evaluator_service.py b/osm_mon/tests/unit/evaluator/test_evaluator_service.py index e09418d..bc93046 100644 --- a/osm_mon/tests/unit/evaluator/test_evaluator_service.py +++ b/osm_mon/tests/unit/evaluator/test_evaluator_service.py @@ -24,7 +24,6 @@ from unittest import TestCase, mock from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.database import AlarmRepository, AlarmTag from osm_mon.core.message_bus_client import MessageBusClient from osm_mon.evaluator.backends.prometheus import PrometheusBackend from osm_mon.evaluator.evaluator import AlarmStatus @@ -149,8 +148,7 @@ class EvaluatorTest(TestCase): self.config = Config() @mock.patch.object(EvaluatorService, "_get_metric_value") - @mock.patch('osm_mon.core.database.db') - def test_evaluate_metric(self, db, get_metric_value): + def test_evaluate_metric(self, get_metric_value): mock_alarm = mock.Mock() mock_alarm.operation = 'gt' mock_alarm.threshold = 50.0 @@ -159,33 +157,29 @@ class EvaluatorTest(TestCase): service = EvaluatorService(self.config) service.queue = mock.Mock() - service._evaluate_metric(mock_alarm, {}) + service._evaluate_metric(mock_alarm) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.ALARM)) service.queue.reset_mock() mock_alarm.operation = 'lt' - service._evaluate_metric(mock_alarm, {}) + service._evaluate_metric(mock_alarm) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.OK)) service.queue.reset_mock() get_metric_value.return_value = None - service._evaluate_metric(mock_alarm, {}) + service._evaluate_metric(mock_alarm) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.INSUFFICIENT)) @mock.patch('multiprocessing.Process') @mock.patch.object(EvaluatorService, "_evaluate_metric") @mock.patch.object(CommonDbClient, "get_vnfd") @mock.patch.object(CommonDbClient, "get_vnfr") - @mock.patch.object(AlarmRepository, "list") - @mock.patch('osm_mon.core.database.db') - def test_evaluate(self, db, alarm_list, get_vnfr, get_vnfd, evaluate_metric, process): + @mock.patch.object(CommonDbClient, "get_alarms") + def test_evaluate_alarms(self, alarm_list, get_vnfr, get_vnfd, evaluate_metric, process): mock_alarm = mock.Mock() mock_alarm.vdur_name = 'cirros_ns-1-cirros_vnfd-VM-1' mock_alarm.monitoring_param = 'cirros_vnf_memory_util' - mock_tag = AlarmTag() - mock_tag.name = 'name' - mock_tag.value = 'value' - mock_alarm.tags = [mock_tag] + mock_alarm.tags = {'name': 'value'} alarm_list.return_value = [mock_alarm] get_vnfr.return_value = vnfr_record_mock get_vnfd.return_value = vnfd_record_mock @@ -193,11 +187,10 @@ class EvaluatorTest(TestCase): evaluator = EvaluatorService(self.config) evaluator.evaluate_alarms() - process.assert_called_with(target=evaluate_metric, args=(mock_alarm, {'name': 'value'})) + process.assert_called_with(target=evaluate_metric, args=(mock_alarm,)) @mock.patch.object(PrometheusBackend, "get_metric_value") - @mock.patch('osm_mon.core.database.db') - def test_get_metric_value_prometheus(self, db, get_metric_value): + def test_get_metric_value_prometheus(self, get_metric_value): self.config.set('evaluator', 'backend', 'prometheus') evaluator = EvaluatorService(self.config) evaluator._get_metric_value('test', {})