diff --git a/surveil/api/controllers/v2/config/__init__.py b/surveil/api/controllers/v2/config/__init__.py index 2cacd55..ed9fccb 100644 --- a/surveil/api/controllers/v2/config/__init__.py +++ b/surveil/api/controllers/v2/config/__init__.py @@ -19,6 +19,7 @@ from surveil.api.controllers.v2.config import contactgroups from surveil.api.controllers.v2.config import contacts from surveil.api.controllers.v2.config import hostgroups from surveil.api.controllers.v2.config import hosts +from surveil.api.controllers.v2.config import macromodulations from surveil.api.controllers.v2.config import notificationways from surveil.api.controllers.v2.config import realms from surveil.api.controllers.v2.config import reload_config @@ -45,4 +46,5 @@ class ConfigController(rest.RestController): BusinessImpactModulationsController()) notificationways = notificationways.NotificationWaysController() checkmodulations = checkmodulations.CheckModulationsController() + macromodulations = macromodulations.MacroModulationController() # engine = EngineController() diff --git a/surveil/api/controllers/v2/config/macromodulations.py b/surveil/api/controllers/v2/config/macromodulations.py new file mode 100644 index 0000000..14ae821 --- /dev/null +++ b/surveil/api/controllers/v2/config/macromodulations.py @@ -0,0 +1,70 @@ +# Copyright 2015 - Savoir-Faire Linux inc. +# +# 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 pecan +from pecan import rest +import wsmeext.pecan as wsme_pecan + +from surveil.api.datamodel.config import macromodulation +from surveil.api.handlers.config import macromodulation_handler +from surveil.common import util + + +class MacroModulationController(rest.RestController): + + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose([macromodulation.MacroModulation]) + def get_all(self): + """Returns all macro modulation objects.""" + handler = macromodulation_handler.MacroModulationHandler(pecan.request) + modulations = handler.get_all() + return modulations + + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose(macromodulation.MacroModulation, unicode) + def get_one(self, timeperiod_name): + """Returns a specific macro modulation.""" + handler = macromodulation_handler.MacroModulationHandler(pecan.request) + modulation = handler.get(timeperiod_name) + return modulation + + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose(body=macromodulation.MacroModulation, status_code=201) + def post(self, data): + """Create a new macro modulation object. + + :param data: a macro modulation within the request body. + """ + handler = macromodulation_handler.MacroModulationHandler(pecan.request) + handler.create(data) + + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose(macromodulation.MacroModulation, + unicode, + status_code=204) + def delete(self, modulation_name): + """Returns a specific macro modulation.""" + handler = macromodulation_handler.MacroModulationHandler(pecan.request) + handler.delete(modulation_name) + + @util.policy_enforce(['authenticated']) + @wsme_pecan.wsexpose(macromodulation.MacroModulation, + unicode, + body=macromodulation.MacroModulation, + status_code=204) + def put(self, modulation_name, modulation): + """Update a specific macro modulation.""" + handler = macromodulation_handler.MacroModulationHandler(pecan.request) + handler.update(modulation_name, modulation) diff --git a/surveil/api/datamodel/config/macromodulation.py b/surveil/api/datamodel/config/macromodulation.py new file mode 100644 index 0000000..7ff3233 --- /dev/null +++ b/surveil/api/datamodel/config/macromodulation.py @@ -0,0 +1,57 @@ +# Copyright 2015 - Savoir-Faire Linux inc. +# +# 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 wsme +import wsme.types as wtypes + +from surveil.api.datamodel import types + + +class MacroModulation(types.Base): + macromodulation_name = wsme.wsattr(wtypes.text, mandatory=True) + modulation_period = wsme.wsattr(wtypes.text, mandatory=True) + # _CRITICAL = wsme.wsattr(int, mandatory=True) + # _WARNING = wsme.wsattr(int, mandatory=True) + + macros = wsme.wsattr( + wtypes.DictType(wtypes.text, int), + mandatory=False + ) + + def __init__(self, **kwargs): + super(MacroModulation, self).__init__(**kwargs) + + # Custom fields start with '_'. Detect them and assign them. + macros = [i for i in kwargs.items() + if isinstance(i[0], str) and i[0].startswith('_')] + if len(macros) > 0: + self.macros = {} + for item in macros: + self.macros[item[0]] = item[1] + + def as_dict(self): + mod_dict = super(MacroModulation, self).as_dict() + macros = mod_dict.pop("macros", None) + if macros: + for item in macros.items(): + mod_dict[item[0]] = item[1] + return mod_dict + + @classmethod + def sample(cls): + return cls( + macromodulation_name='HighDuringNight', + modulation_period='night', + macros={"_CRITICAL": 20, "_WARNING": 10} + ) diff --git a/surveil/api/handlers/config/macromodulation_handler.py b/surveil/api/handlers/config/macromodulation_handler.py new file mode 100644 index 0000000..ca24985 --- /dev/null +++ b/surveil/api/handlers/config/macromodulation_handler.py @@ -0,0 +1,71 @@ +# Copyright 2014 - Savoir-Faire Linux inc. +# +# 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 surveil.api.datamodel.config import macromodulation +from surveil.api.handlers import handler + + +class MacroModulationHandler(handler.Handler): + """Fulfills a request on the macro modulation resource.""" + + def get(self, modulation_name): + """Return a macro modulation.""" + + m = self.request.mongo_connection.shinken.macromodulations.find_one( + {"macromodulation_name": modulation_name}, {'_id': 0} + ) + return macromodulation.MacroModulation(**m) + + def update(self, modulation_name, modulation): + """Modify an existing macro modulation.""" + modulation_dict = modulation.as_dict() + if "macromodulation_name" not in modulation_dict.keys(): + modulation_dict['contactgroup_name'] = modulation_name + + self.request.mongo_connection.shinken.macromodulations.update( + {"macromodulation_name": modulation_name}, + modulation_dict + ) + + def delete(self, modulation_name): + """Delete existing macro modulation.""" + self.request.mongo_connection.shinken.macromodulations.remove( + {"macromodulation_name": modulation_name} + ) + + def create(self, modulation): + """Create a new macro modulation.""" + self.request.mongo_connection.shinken.macromodulations.insert( + modulation.as_dict() + ) + + def get_all(self): + """Return all macro modulation objects.""" + modulations = [m for m + in self.request.mongo_connection. + shinken.macromodulations.find( + # Don't return templates + { + "register": {"$ne": "0"} + }, + { + "_id": 0 + } + ) + ] + + modulations = [macromodulation.MacroModulation(**m) + for m in modulations] + + return modulations diff --git a/surveil/tests/api/controllers/v2/config/test_macromodulations.py b/surveil/tests/api/controllers/v2/config/test_macromodulations.py new file mode 100644 index 0000000..1ea200e --- /dev/null +++ b/surveil/tests/api/controllers/v2/config/test_macromodulations.py @@ -0,0 +1,135 @@ +# Copyright 2014 - Savoir-Faire Linux inc. +# +# 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 copy +import json + + +from surveil.tests.api import functionalTest + + +class TestMacroModulationController(functionalTest.FunctionalTest): + + def setUp(self): + super(TestMacroModulationController, self).setUp() + self.modulations = [ + { + 'macromodulation_name': 'HighDuringNight', + 'modulation_period': 'night', + '_CRITICAL': 20, + '_WARNING': 10, + }, + { + 'macromodulation_name': 'LowDuringNight', + 'modulation_period': 'night', + '_CRITICAL': 10, + '_WARNING': 20, + } + ] + self.mongoconnection.shinken.macromodulations.insert( + copy.deepcopy(self.modulations) + ) + + def test_get_all_macromodulations(self): + response = self.get('/v2/config/macromodulations') + + self.assertItemsEqual( + [ + { + 'macromodulation_name': 'HighDuringNight', + 'modulation_period': 'night', + 'macros': { + '_CRITICAL': 20, + '_WARNING': 10}}, + { + 'macromodulation_name': 'LowDuringNight', + 'modulation_period': 'night', + 'macros': { + '_CRITICAL': 10, + '_WARNING': 20}} + ], + json.loads(response.body.decode()) + + ) + self.assertEqual(response.status_int, 200) + + def test_get_one_macromodulation(self): + response = self.get('/v2/config/macromodulations/HighDuringNight') + + self.assertEqual( + json.loads(response.body.decode()), + {'macromodulation_name': 'HighDuringNight', + 'modulation_period': 'night', + 'macros': { + '_CRITICAL': 20, + '_WARNING': 10}} + ) + + def test_create_macromodulation(self): + m = { + 'macromodulation_name': 'TEST_CREATE_MODULATION', + 'modulation_period': 'night', + 'macros': { + '_CRITICAL': 10, + '_WARNING': 20 + } + } + + self.post_json('/v2/config/macromodulations', m) + + self.assertIsNotNone( + self.mongoconnection.shinken.macromodulations.find_one( + { + 'macromodulation_name': 'TEST_CREATE_MODULATION', + '_CRITICAL': 10, + '_WARNING': 20 + } + ) + ) + + def test_delete_macromodulation(self): + self.assertIsNotNone( + self.mongoconnection.shinken.macromodulations.find_one( + {"macromodulation_name": 'HighDuringNight'} + ) + ) + + self.delete('/v2/config/macromodulations/HighDuringNight') + + self.assertIsNone( + self.mongoconnection.shinken.macromodulations.find_one( + {"macromodulation_name": 'HighDuringNight'} + ) + ) + + def test_put_macromodulation(self): + self.assertEqual( + self.mongoconnection.shinken.macromodulations.find_one( + {'macromodulation_name': 'HighDuringNight'} + )['modulation_period'], + 'night' + ) + + self.put_json( + '/v2/config/macromodulations/HighDuringNight', + {"macromodulation_name": "HighDuringNight", + "modulation_period": "TESTUPDATE"} + ) + + self.assertEqual( + self.mongoconnection.shinken.macromodulations.find_one( + {'macromodulation_name': 'HighDuringNight'} + )['modulation_period'], + 'TESTUPDATE' + )