def _setup_nrpe(self): # Create an Alignak module mod = Module({ 'module_alias': 'nrpe-booster', 'module_types': 'nrpe-booster', 'python_name': 'alignak_module_nrpe_booster' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('poller', None) # Load and initialize the modules self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] return my_module
def test_conflicting_modules(self): # prepare 2 modconfs: modconfA = Module({ 'module_alias': 'whatever', 'python_name': 'test_module_as_package_dir.modA' }) modconfB = Module({ 'module_alias': '42', 'python_name': 'test_module_as_package_dir.modB' }) mods = (modconfA, modconfB) mm = self.modulemanager = ModulesManager('broker', None) mm.load_and_init(mods) modA = None modB = None for _, mod in mm.modules_assoc: if mod.__package__ == 'test_module_as_package_dir.modA': modA = mod elif mod.__package__ == 'test_module_as_package_dir.modB': modB = mod if mod.properties['type'].startswith("mod"): self.assertEqual(mod.expected_helpers_X, mod.helpers.X) self.assertIsNotNone(modA) self.assertIsNotNone(modB) self.assertNotEqual(modA.helpers.X, modB.helpers.X)
class NrpePollerTestMixin(object): def setUp(self): super(NrpePollerTestMixin, self).setUp() logger.setLevel(logging.DEBUG) def _setup_nrpe(self): # Create an Alignak module mod = Module({ 'module_alias': 'nrpe-booster', 'module_types': 'nrpe-booster', 'python_name': 'alignak_module_nrpe_booster' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('poller', None) # Load and initialize the modules self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] return my_module
def get_module(self, mod_name): """Get and load a module :param mod_name: module name to get :type mod_name: str :return: module :rtype: object """ if self.modules_dir and self.modules_dir not in sys.path: sys.path.append(self.modules_dir) if self.modules_dir: mod_dir = os.path.join(self.modules_dir, mod_name) else: mod_dir = None # to keep it back-compatible with previous Alignak module way, # we first try with "import `mod_name`.module" and if we succeed # then that's the one to actually use: mod = ModulesManager.try_best_load('.module', mod_name) if mod: return mod # otherwise simply try new and old style: return ModulesManager.try_load(mod_name, mod_dir)
class TestModuleWsHostGet(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ[ 'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test' # Delete used mongo DBs print("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split('mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'])) assert exit_code == 0 fnull = open(os.devnull, 'w') cls.p = subprocess.Popen([ 'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid' ], stdout=fnull, stderr=fnull) time.sleep(3) endpoint = 'http://127.0.0.1:5000' test_dir = os.path.dirname(os.path.realpath(__file__)) print("Current test directory: %s" % test_dir) print("Feeding Alignak backend... %s" % test_dir) exit_code = subprocess.call(shlex.split( 'alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir), stdout=fnull, stderr=fnull) assert exit_code == 0 print("Fed") # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = { 'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id } response = requests.post(endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print("Created a new user: %s" % resp) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = { 'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag'] } data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' @classmethod def tearDownClass(cls): cls.p.kill() def test_module_zzz_host_get(self): """Test the module /host API - host creation and get information :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', 'give_result': '1', 'give_feedback': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1', # Errors for unknown host/service 'ignore_unknown_host': '0', 'ignore_unknown_service': '0', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Do not allow GET request on /host - not yet authorized! response = requests.get('http://127.0.0.1:8888/host') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Get a non-existing host - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/host', auth=self.auth, params={'name': 'new_host_2'}) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested host 'new_host_2' does not exist"] }) # Get a non-existing host - 2nd: use host name in the URI response = session.get('http://127.0.0.1:8888/host/new_host_2', auth=self.auth) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested host 'new_host_2' does not exist"] }) #Â ----- # Request to create an host - no provided data (default) headers = {'Content-Type': 'application/json'} data = { "name": "new_host_0", } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"Requested host 'new_host_0' does not exist.", u"Requested host 'new_host_0' created." ], u'_feedback': { u'name': u'new_host_0' } }) # Host created with default check_command and in default user realm #Â ----- # Get new host to confirm creation - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/host', auth=self.auth, params={'name': 'new_host_0'}) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(result['_result'][0]['name'], 'new_host_0') # Get new host to confirm creation - 2nd: use host name in the URI response = session.get('http://127.0.0.1:8888/host/new_host_0', auth=self.auth) result = response.json() from pprint import pprint pprint(result['_result']) # [{u'2d_coords': u'', # u'3d_coords': u'', # u'_created': u'Thu, 01 Jun 2017 10:58:30 GMT', # u'_etag': u'691c3f4a7cc8996c1d047932421759c020d00857', # u'_id': u'592ff35606fd4b7eec395625', # u'_is_template': False, # u'_links': {u'self': {u'href': u'host/592ff35606fd4b7eec395625', # u'title': u'Host'}}, # u'_overall_state_id': 3, # u'_realm': {u'_all_children': [], # u'_children': [], # u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'_etag': u'26b3830c017b4fca8553365246f21267aece46a7', # u'_id': u'592ff35006fd4b7eec3955eb', # u'_level': 0, # u'_parent': None, # u'_tree_parents': [], # u'_updated': u'Thu, 01 Jun 2017 10:58:27 GMT', # u'alias': u'', # u'default': True, # u'definition_order': 100, # u'global_critical_threshold': 5, # u'global_warning_threshold': 3, # u'hosts_critical_threshold': 5, # u'hosts_warning_threshold': 3, # u'imported_from': u'unknown', # u'name': u'All', # u'notes': u'', # u'services_critical_threshold': 5, # u'services_warning_threshold': 3}, # u'_sub_realm': True, # u'_template_fields': {}, # u'_templates': [], # u'_templates_with_services': True, # u'_updated': u'Thu, 01 Jun 2017 10:58:30 GMT', # u'action_url': u'', # u'active_checks_enabled': True, # u'address': u'', # u'address6': u'', # u'alias': u'', # u'business_impact': 2, # u'business_impact_modulations': [], # u'business_rule_downtime_as_ack': False, # u'business_rule_host_notification_options': [u'd', u'u', u'r', u'f', u's'], # u'business_rule_output_template': u'', # u'business_rule_service_notification_options': [u'w', # u'u', # u'c', # u'r', # u'f', # u's'], # u'business_rule_smart_notifications': False, # u'check_command': {u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'_etag': u'356d02479ca7dbebe85e22b9b43e95dc9d5d037c', # u'_id': u'592ff35006fd4b7eec3955f1', # u'_realm': u'592ff35006fd4b7eec3955eb', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'alias': u'Host/service is always UP/OK', # u'command_line': u'_internal_host_up', # u'definition_order': 100, # u'enable_environment_macros': False, # u'imported_from': u'unknown', # u'module_type': u'fork', # u'name': u'_internal_host_up', # u'notes': u'', # u'poller_tag': u'', # u'reactionner_tag': u'', # u'timeout': -1}, # u'check_command_args': u'', # u'check_freshness': False, # u'check_interval': 5, # u'checkmodulations': [], # u'custom_views': [], # u'customs': {}, # u'definition_order': 100, # u'display_name': u'', # u'escalations': [], # u'event_handler': None, # u'event_handler_args': u'', # u'event_handler_enabled': False, # u'failure_prediction_enabled': False, # u'first_notification_delay': 0, # u'flap_detection_enabled': True, # u'flap_detection_options': [u'o', u'd', u'x'], # u'freshness_state': u'x', # u'freshness_threshold': 0, # u'high_flap_threshold': 50, # u'icon_image': u'', # u'icon_image_alt': u'', # u'icon_set': u'', # u'imported_from': u'unknown', # u'initial_state': u'x', # u'labels': [], # u'location': {u'coordinates': [48.858293, 2.294601], u'type': u'Point'}, # u'low_flap_threshold': 25, # u'ls_acknowledged': False, # u'ls_acknowledgement_type': 1, # u'ls_attempt': 0, # u'ls_current_attempt': 0, # u'ls_downtimed': False, # u'ls_execution_time': 0.0, # u'ls_grafana': False, # u'ls_grafana_panelid': 0, # u'ls_impact': False, # u'ls_last_check': 0, # u'ls_last_hard_state_changed': 0, # u'ls_last_notification': 0, # u'ls_last_state': u'OK', # u'ls_last_state_changed': 0, # u'ls_last_state_type': u'HARD', # u'ls_last_time_down': 0, # u'ls_last_time_unknown': 0, # u'ls_last_time_unreachable': 0, # u'ls_last_time_up': 0, # u'ls_latency': 0.0, # u'ls_long_output': u'', # u'ls_max_attempts': 0, # u'ls_next_check': 0, # u'ls_output': u'', # u'ls_passive_check': False, # u'ls_perf_data': u'', # u'ls_state': u'UNREACHABLE', # u'ls_state_id': 3, # u'ls_state_type': u'HARD', # u'macromodulations': [], # u'max_check_attempts': 1, # u'name': u'new_host_0', # u'notes': u'', # u'notes_url': u'', # u'notification_interval': 60, # u'notification_options': [u'd', u'x', u'r', u'f', u's'], # u'notifications_enabled': True, # u'obsess_over_host': False, # u'parents': [], # u'passive_checks_enabled': True, # u'poller_tag': u'', # u'process_perf_data': True, # u'reactionner_tag': u'', # u'resultmodulations': [], # u'retry_interval': 0, # u'service_excludes': [], # u'service_includes': [], # u'service_overrides': [], # u'snapshot_criteria': [u'd', u'x'], # u'snapshot_enabled': False, # u'snapshot_interval': 5, # u'stalking_options': [], # u'statusmap_image': u'', # u'tags': [], # u'time_to_orphanage': 300, # u'trending_policies': [], # u'trigger_broker_raise_enabled': False, # u'trigger_name': u'', # u'usergroups': [], # u'users': [], # u'vrml_image': u''}] # self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(result['_result'][0]['name'], 'new_host_0') #Â ----- # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
def test_module_manager_arbiter(self): """ Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'SnmpBoosterArbiter', 'module_types': 'checks', 'python_name': 'alignak_module_snmp_booster.snmpbooster_arbiter', 'loaded_by': 'arbiter', 'datasource': './cfg/genDevConfig/example.ini', 'db_host': 'localhost', 'db_port': 6379 }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('arbiter', None) # Clear logs self.clear_logs() # Load and initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module logs self.assert_log_match( re.escape( "Importing Python module 'alignak_module_snmp_booster.snmpbooster_arbiter' for " "SnmpBoosterArbiter..."), 0) self.assert_log_match( re.escape( "Module properties: {'daemons': ['arbiter'], 'phases': ['running', " "'late_configuration'], 'type': 'snmp_booster', 'external': False, " "'worker_capable': True}"), 1) self.assert_log_match( re.escape( "Imported 'alignak_module_snmp_booster.snmpbooster_arbiter' for SnmpBoosterArbiter" ), 2) self.assert_log_match( re.escape( "Loaded Python module 'alignak_module_snmp_booster.snmpbooster_arbiter' " "(SnmpBoosterArbiter)"), 3) self.assert_log_match( re.escape( "Give an instance of alignak_module_snmp_booster.snmpbooster_arbiter " "for alias: SnmpBoosterArbiter"), 4) self.assert_log_match( re.escape( "[SnmpBooster] [code 0101] Loading SNMP Booster module for plugin SnmpBoosterArbiter" ), 5) self.assert_log_match( re.escape( "[SnmpBooster] [code 0902] Reading input configuration file: " "./cfg/genDevConfig/example.ini"), 6) # Starting internal module logs self.assert_log_match( re.escape("Trying to initialize module: SnmpBoosterArbiter"), 7) self.assert_log_match( re.escape( "[SnmpBooster] [code 1101] Initialization of the SNMP Booster 2.0.0" ), 8) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([my_module], self.modulemanager.get_internal_instances()) for phase in ['configuration', 'retention']: self.assertListEqual( [], self.modulemanager.get_internal_instances(phase)) for phase in ['late_configuration', 'running']: self.assertListEqual( [my_module], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([], self.modulemanager.get_external_instances()) for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: self.assertListEqual( [], self.modulemanager.get_external_instances(phase)) # Clear logs self.clear_logs() # Nothing special ... self.modulemanager.check_alive_instances() # And we clear all now self.modulemanager.stop_all()
class TestModuleNoBackend(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): #Â Simulate an Alignak receiver daemon cls.ws_endpoint = 'http://127.0.0.1:7773/ws' import cherrypy class ReceiverItf(object): @cherrypy.expose def index(self): return "I am the Receiver daemon!" from alignak.http.daemon import HTTPDaemon as AlignakDaemon http_daemon1 = AlignakDaemon('0.0.0.0', 7773, ReceiverItf(), False, None, None, None, None, 10, '/tmp/alignak-cherrypy.log') def run_http_server(): http_daemon1.run() import threading cls.http_thread1 = threading.Thread(target=run_http_server, name='http_server_receiver') cls.http_thread1.daemon = True cls.http_thread1.start() print("Thread started") cls.modulemanager = None def setUp(self): super(TestModuleNoBackend, self).setUp() def tearDown(self): """Delete resources in backend :return: None """ super(TestModuleNoBackend, self).tearDown() if self.modulemanager: self.modulemanager.stop_all() def test_module_host_livestate_unauthorized(self): """Test the module /host API - host livestate - unauthorized access :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': '', 'username': '', 'password': '', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Do not give feedback data 'give_feedback': '0', 'give_result': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Set module to listen on all interfaces 'host': '0.0.0.0', 'port': 8888, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1', # Force Alignak backend update by the module (default is not force!) 'alignak_backend_livestate_update': '0', # Disable authorization 'authorization': '0' }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) session = requests.Session() headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Update an host with an host livestate (heartbeat / host is alive): livestate # Because there is no backend configured, only an external command is raised # to Alignak for the host data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch(self.ws_endpoint + '/host', json=data, headers=headers) print(response) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { '_status': 'OK', '_result': [ 'new_host_0 is alive :)', "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", ] }) # No errors - an extrenal command was raised for the host livestate #Â ----- # Update an host with an host livestate (heartbeat / host is alive): livestate # Because there is no backend configured, only an external command is raised # to Alignak for the host data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", }, "services": [{ "name": "test_svc_0", "livestate": { "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } }] } self.assertEqual(my_module.received_commands, 1) response = session.patch(self.ws_endpoint + '/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { '_status': 'OK', '_result': [ 'new_host_0 is alive :)', "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", "PROCESS_SERVICE_CHECK_RESULT;new_host_0;test_svc_0;0;Output...|'counter'=1\nLong output..." ] }) # No errors - an extrenal command was raised for the host livestate self.modulemanager.stop_all()
class TestModules(AlignakTest): """ This class contains the tests for the modules """ def setUp(self): super(TestModules, self).setUp() self.set_unit_tests_logger_level('INFO') def test_module_loading(self): """ Test arbiter, broker, ... detecting configured modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct self.show_configuration_logs() self.show_logs() # arbiter modules modules = [m.module_alias for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] modules = [m.name for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] # broker modules modules = [m.module_alias for m in self._broker_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._broker_daemon.modules] assert modules == ['Example'] # # The only existing poller module is Example declared in the configuration # modules = [m.module_alias for m in self.pollers['poller-master'].modules] # assert modules == ['Example'] # # # The only existing receiver module is Example declared in the configuration # modules = [m.module_alias for m in self.receivers['receiver-master'].modules] # assert modules == ['Example'] # # # The only existing reactionner module is Example declared in the configuration # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules] # assert modules == ['Example'] # No scheduler modules created modules = [m.module_alias for m in self._scheduler_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._scheduler_daemon.modules] assert modules == ['Example'] self.show_logs() # Loading module logs self.assert_any_log_match(re.escape( u"Importing Python module 'alignak_module_example' for Example..." )) self.assert_any_log_match(re.escape( u"Imported 'alignak_module_example' for Example" )) self.assert_any_log_match(re.escape( u"Give an instance of alignak_module_example for alias: Example" )) self.assert_any_log_match(re.escape( u"I correctly loaded my modules: [Example]" )) def test_arbiter_configuration_module(self): """ Test arbiter configuration loading :return: """ self.setup_with_file('./cfg/modules/arbiter_modules.cfg') assert self.conf_is_correct self.show_configuration_logs() self.show_logs() # The arbiter module is 'backend_arbiter' declared in the configuration modules = [m.module_alias for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] def test_module_on_module(self): """ No module configuration for modules Check that the feature is detected as disabled :return: """ self.setup_with_file('cfg/modules/alignak_module_with_submodules.cfg') assert self.conf_is_correct self.show_configuration_logs() # arbiter modules modules = [m.module_alias for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] modules = [m.name for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] # broker modules modules = [m.module_alias for m in self._broker_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._broker_daemon.modules] assert modules == ['Example'] # # The only existing poller module is Example declared in the configuration # modules = [m.module_alias for m in self.pollers['poller-master'].modules] # assert modules == ['Example'] # # # The only existing receiver module is Example declared in the configuration # modules = [m.module_alias for m in self.receivers['receiver-master'].modules] # assert modules == ['Example'] # # # The only existing reactionner module is Example declared in the configuration # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules] # assert modules == ['Example'] # No scheduler modules created modules = [m.module_alias for m in self._scheduler_daemon.modules] assert modules == ['Example', 'inner-retention'] modules = [m.name for m in self._scheduler_daemon.modules] assert modules == ['Example', 'inner-retention'] def test_modulemanager_1(self): """ Module manager manages its modules - old form Test if the module manager manages correctly all the modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example' }) self.run_modulemanager(mod) def test_modulemanager_2(self): """ Module manager manages its modules - new form Test if the module manager manages correctly all the modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # Create an Alignak module mod = Module({ 'name': 'mod-example', 'type': 'example', 'python_name': 'alignak_module_example' }) self.run_modulemanager(mod) def run_modulemanager(self, mod): # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([mod]) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.clear_logs() my_module = self.modules_manager.instances[0] assert my_module.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module] == self.modules_manager.get_external_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [my_module] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.show_logs() # Starting external module logs idx = 0 self.assert_log_match(re.escape( "Trying to initialize module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Test - Example in init" ), idx) idx += 1 self.assert_log_match(re.escape( "Initialization of the example module" ), idx) idx += 1 self.assert_log_match(re.escape( "Module mod-example is initialized" ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external process for module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "mod-example is now started (pid=" ), idx) idx += 1 self.assert_log_count(7) # Check alive assert my_module.process is not None assert my_module.process.is_alive() self.clear_logs() # Check the alive module instances... self.modules_manager.check_alive_instances() # Try to restart the dead modules, if any self.modules_manager.try_to_restart_deads() self.assert_log_count(0) # Kill the external module (normal stop is .stop_process) self.clear_logs() my_module.kill() idx = 0 self.assert_log_match(re.escape( "Killing external module " ), idx) idx += 1 self.show_logs() # self.assert_log_match(re.escape( # "mod-example is still living " # ), idx) # idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time normal_kill = True logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 normal_kill = False break log_num += 1 break self.assert_log_match(re.escape( "External module killed" ), idx) idx += 1 self.assert_log_count(idx) # The module is dead (not normally stopped...) so this module inner # process reference is not None! assert my_module.process is not None # Check the alive module instances... self.clear_logs() idx = 0 self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_match(re.escape( "The external module mod-example died unexpectedly!" ), idx) idx += 1 self.assert_log_match(re.escape( "Setting the module mod-example to restart" ), idx) self.assert_log_count(2) idx += 1 if normal_kill: # Try to restart the dead modules, if any # Indeed, it's too early, so it won't do it self.clear_logs() idx = 0 print("try init: %d" % my_module.init_try) self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match(re.escape( "Trying to restart module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD ), idx) idx += 1 self.assert_log_count(2) # Here the module instance is still dead assert not my_module.process.is_alive() # Wait for a minimum delay time.sleep(MODULE_INIT_PERIOD + 1) # my_module.last_init_try = -5 self.clear_logs() self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_count(0) # Try to restart the dead modules, if any # Now it is time... self.clear_logs() idx = 0 self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match(re.escape( "Trying to restart module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Trying to initialize module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Test - Example in init" ), idx) idx += 1 self.assert_log_match(re.escape( "Initialization of the example module" ), idx) idx += 1 self.assert_log_match(re.escape( "Module mod-example is initialized" ), idx) idx += 1 self.assert_log_match(re.escape( "Restarting mod-example..." ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external process for module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "mod-example is now started (pid=" ), idx) idx += 1 self.assert_log_count(8) # Here the module instance should be alive again assert my_module.process.is_alive() # No more module to restart... assert [] == self.modules_manager.to_restart # And we clear all now self.clear_logs() idx = 0 self.modules_manager.stop_all() self.show_logs() self.assert_log_match(re.escape( "Shutting down modules..." ), idx) idx += 1 self.assert_log_match(re.escape( "Request external process to stop for mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "I'm stopping module 'mod-example'" ), idx) idx += 1 self.assert_log_match(re.escape( "Killing external module " ), idx) idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 break log_num += 1 break self.assert_log_match(re.escape( "External module killed" ), idx) idx += 1 self.assert_log_match(re.escape( "External process stopped." ), idx) idx += 1 # self.assert_log_count(6) def test_modulemanager_several_modules(self): """ Module manager manages its modules Test if the module manager manages correctly all the modules Configured with several modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # for mod in self._arbiter.conf.modules: # print (mod.__dict__) # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'foo', 'option2': 'bar', 'option3': 1 }) mod2 = Module({ 'module_alias': 'mod-example-2', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'faa', 'option2': 'bor', 'option3': 1 }) # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) print("Modules: %s" % self._broker_daemon.modules) # Load an initialize the modules: # - load python module # - get module properties and instances assert self.modules_manager.load_and_init([mod, mod2]) print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in self.modules_manager.instances])) self.show_logs() self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_example' (mod-example)" )) self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example-2..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example-2" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_example' (mod-example-2)" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.assert_any_log_match(re.escape( "configuration, foo, bar, 1" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example-2" )) self.assert_any_log_match(re.escape( "configuration, faa, bor, 1" )) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) my_module = self.modules_manager.instances[0] my_module2 = self.modules_manager.instances[1] assert my_module.is_external assert my_module2.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module, my_module2] == self.modules_manager.get_external_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [my_module, my_module2] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.modules_manager.start_external_instances() # Starting external module logs self.assert_any_log_match(re.escape( "Starting external module mod-example" )) self.assert_any_log_match(re.escape( "Starting external process for module mod-example" )) self.assert_any_log_match(re.escape( "mod-example is now started (pid=" )) # Check alive assert my_module.process is not None assert my_module.process.is_alive() assert my_module2.process is not None assert my_module2.process.is_alive() # Kill the external module (normal stop is .stop_process) self.clear_logs() print("Killing a module") my_module.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape( "Killing external module " )) self.assert_any_log_match(re.escape( "External module killed" )) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None self.clear_logs() print("Killing another module") my_module2.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape( "Killing external module " )) self.assert_any_log_match(re.escape( "External module killed" )) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None # Nothing special ... self.clear_logs() self.modules_manager.check_alive_instances() # Try to restart the dead modules print("Trying to restart dead modules") # We lie on the last restart try time my_module.last_init_try = time.time() my_module2.last_init_try = time.time() self.modules_manager.try_to_restart_deads() self.show_logs() # In fact it's too early, so it won't do it # Here the module instances should still be dead assert not my_module.process.is_alive() assert not my_module2.process.is_alive() # We lie on the last restart try time my_module.last_init_try = 0 my_module2.last_init_try = 0 self.modules_manager.check_alive_instances() self.modules_manager.try_to_restart_deads() # Here the module instances should be alive again assert my_module.process.is_alive() assert my_module2.process.is_alive() # Kill the module again self.clear_logs() my_module.kill() self.show_logs() time.sleep(0.2) assert not my_module.process.is_alive() # And we clear all now self.modules_manager.stop_all() # Stopping module logs self.assert_any_log_match(re.escape( "I'm stopping module " ))
class TestModuleWsHostLivestate(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ[ 'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test' # Delete used mongo DBs print("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split('mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'])) assert exit_code == 0 fnull = open(os.devnull, 'w') cls.p = subprocess.Popen([ 'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid' ], stdout=fnull, stderr=fnull) time.sleep(3) endpoint = 'http://127.0.0.1:5000' test_dir = os.path.dirname(os.path.realpath(__file__)) print("Current test directory: %s" % test_dir) print("Feeding Alignak backend...") print('alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir) exit_code = subprocess.call(shlex.split( 'alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir), stdout=fnull, stderr=fnull) assert exit_code == 0 print("Fed") # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = { 'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id } response = requests.post(endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print("Created a new user: %s" % resp) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = { 'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag'] } data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' cls.modulemanager = None @classmethod def tearDownClass(cls): if cls.modulemanager: cls.modulemanager.stop_all() cls.p.kill() @classmethod def tearDown(cls): """Delete resources in backend :return: None """ for resource in ['logcheckresult']: requests.delete('http://127.0.0.1:5000/' + resource, auth=cls.auth) def test_module_zzz_host_livestate(self): """Test the module /host API - host creation and livestate :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Send a log_check_result to the alignak backend 'alignak_backend_old_lcr': '1', # Do not give feedback data 'give_feedback': '0', 'give_result': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Alignak backend # --- self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Do not allow GET request on /host - not authorized response = requests.get('http://127.0.0.1:8888/host') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Create a new host with an host livestate (heartbeat / host is alive): livestate data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"Requested host 'new_host_0' does not exist.", u"Requested host 'new_host_0' created.", u"PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", ] }) # No errors! # Get new host in the backend response = requests.get( self.endpoint + '/host', auth=self.auth, params={'where': json.dumps({'name': 'new_host_0'})}) resp = response.json() new_host_0 = resp['_items'][0] self.assertEqual('new_host_0', new_host_0['name']) # Get backend check results - no check result sent to the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] self.assertEqual(len(rl), 0) #Â ----- # Send an host livestate data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", ] }) # No errors! # Get backend check results - no check result sent to the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] self.assertEqual(len(rl), 0) #Â ----- # Send an host livestate with a timestamp in the past now = int(time.time()) - 3600 data = { "name": "new_host_0", "livestate": { # Timestamp in the past "timestamp": now, "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"[%d] PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output..." % now, ] }) # No errors! # Get backend check results - a check result was recorded in the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] # A log check result was recorded... self.assertEqual(len(rl), 1) rl = resp['_items'][0] print("LCR: %s" % rl) # ...with the correct timestamp self.assertEqual(rl['host_name'], "new_host_0") self.assertEqual(rl['last_check'], now) #Â ----- # Send an host livestate with a timestamp in the past but sooner than the former one now = now + 1800 data = { "name": "new_host_0", "livestate": { # Timestamp in the past "timestamp": now, "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"[%d] PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output..." % now, ] }) # No errors! # Get backend check results - one more check result was recorded in the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] # A log check result was recorded... self.assertEqual(len(rl), 2) # Get the second LCR rl = resp['_items'][1] print("LCR: %s" % rl) # ...with the correct timestamp self.assertEqual(rl['host_name'], "new_host_0") self.assertEqual(rl['last_check'], now) # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all() def test_module_zzz_service_livestate(self): """Test the module /host API - service creation and livestate :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Send a log_check_result to the alignak backend 'alignak_backend_old_lcr': '1', # Do not give feedback data 'give_feedback': '0', 'give_result': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Alignak backend # --- self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Do not allow GET request on /host - not authorized response = requests.get('http://127.0.0.1:8888/host') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Request to create an host - create a new host headers = {'Content-Type': 'application/json'} data = { "name": "new_host_for_services_0", "template": { "_realm": 'All', "check_command": "_internal_host_up" } } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_for_services_0 is alive :)', u"Requested host 'new_host_for_services_0' does not exist.", u"Requested host 'new_host_for_services_0' created." ] }) # No errors! # Get new host in the backend response = requests.get( self.endpoint + '/host', auth=self.auth, params={'where': json.dumps({'name': 'new_host_for_services_0'})}) resp = response.json() new_host_for_services_0 = resp['_items'][0] self.assertEqual('new_host_for_services_0', new_host_for_services_0['name']) # Get backend check results - no check result sent to the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] self.assertEqual(len(rl), 0) # Request to create an host - create a new service without any template data headers = {'Content-Type': 'application/json'} data = { "name": "new_host_for_services_0", "services": [{ "name": "test_empty_0", # "template": { # "_realm": 'All', # "check_command": "_echo" # }, "livestate": { "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", }, "variables": { 'test1': 'string', 'test2': 1, 'test3': 5.0 }, }] } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_for_services_0 is alive :)', u"Requested service 'new_host_for_services_0/test_empty_0' does not exist.", u"Requested service 'new_host_for_services_0/test_empty_0' created.", u"PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output...", u"Service 'new_host_for_services_0/test_empty_0' updated", ] }) # No errors! # Get new host to confirm creation response = requests.get( self.endpoint + '/host', auth=self.auth, params={'where': json.dumps({'name': 'new_host_for_services_0'})}) resp = response.json() new_host_for_services_0 = resp['_items'][0] self.assertEqual('new_host_for_services_0', new_host_for_services_0['name']) # Get services data to confirm update response = requests.get(self.endpoint + '/service', auth=self.auth, params={ 'where': json.dumps({ 'host': new_host_for_services_0['_id'], 'name': 'test_empty_0' }) }) resp = response.json() service = resp['_items'][0] expected = {u'_TEST3': 5.0, u'_TEST2': 1, u'_TEST1': u'string'} self.assertEqual(expected, service['customs']) # Send a service livestate, no timestamp headers = {'Content-Type': 'application/json'} data = { "name": "new_host_for_services_0", "services": [{ "name": "test_empty_0", "livestate": { # No timestamp in the livestate "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } }] } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_for_services_0 is alive :)', u"PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output...", ] }) # No errors! # Get backend check results - no check result sent to the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] self.assertEqual(len(rl), 0) # Send a service livestate, timestamp in the past headers = {'Content-Type': 'application/json'} now = int(time.time()) - 3600 data = { "name": "new_host_for_services_0", "services": [{ "name": "test_empty_0", "livestate": { # Timestamp in the past "timestamp": now, "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } }] } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_for_services_0 is alive :)', u"[%d] PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output..." % now, ] }) # No errors! # Get backend check results - a check result was recorded in the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] # A log check result was recorded... self.assertEqual(len(rl), 1) rl = resp['_items'][0] print("LCR: %s" % rl) # ...with the correct timestamp self.assertEqual(rl['host_name'], "new_host_for_services_0") self.assertEqual(rl['service_name'], "test_empty_0") self.assertEqual(rl['last_check'], now) # Send a service livestate with a timestamp in the past but sooner than the former one now = now + 1800 data = { "name": "new_host_for_services_0", "services": [{ "name": "test_empty_0", "livestate": { # Timestamp in the past "timestamp": now, "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } }] } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_for_services_0 is alive :)', u"[%d] PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output..." % now, ] }) # No errors! # Get backend check results - a check result was recorded in the backend response = requests.get(self.endpoint + '/logcheckresult', auth=self.auth) resp = response.json() rl = resp['_items'] # A log check result was recorded... self.assertEqual(len(rl), 2) rl = resp['_items'][1] print("LCR: %s" % rl) # ...with the correct timestamp self.assertEqual(rl['host_name'], "new_host_for_services_0") self.assertEqual(rl['service_name'], "test_empty_0") self.assertEqual(rl['last_check'], now) # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
class TestModules(AlignakTest): """ This class contains the tests for the modules """ def setUp(self): super(TestModules, self).setUp() self.set_unit_tests_logger_level('INFO') def test_module_loading(self): """ Test arbiter, broker, ... detecting configured modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct self.show_configuration_logs() self.show_logs() # arbiter modules modules = [ m.module_alias for m in self._arbiter.link_to_myself.modules ] assert modules == ['Example'] modules = [m.name for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] # broker modules modules = [m.module_alias for m in self._broker_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._broker_daemon.modules] assert modules == ['Example'] # # The only existing poller module is Example declared in the configuration # modules = [m.module_alias for m in self.pollers['poller-master'].modules] # assert modules == ['Example'] # # # The only existing receiver module is Example declared in the configuration # modules = [m.module_alias for m in self.receivers['receiver-master'].modules] # assert modules == ['Example'] # # # The only existing reactionner module is Example declared in the configuration # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules] # assert modules == ['Example'] # No scheduler modules created modules = [m.module_alias for m in self._scheduler_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._scheduler_daemon.modules] assert modules == ['Example'] self.show_logs() # Loading module logs self.assert_any_log_match( re.escape( u"Importing Python module 'alignak_module_example' for Example..." )) self.assert_any_log_match( re.escape(u"Imported 'alignak_module_example' for Example")) self.assert_any_log_match( re.escape( u"Give an instance of alignak_module_example for alias: Example" )) self.assert_any_log_match( re.escape(u"I correctly loaded my modules: [Example]")) def test_arbiter_configuration_module(self): """ Test arbiter configuration loading :return: """ self.setup_with_file('./cfg/modules/arbiter_modules.cfg') assert self.conf_is_correct self.show_configuration_logs() self.show_logs() # The arbiter module is 'backend_arbiter' declared in the configuration modules = [ m.module_alias for m in self._arbiter.link_to_myself.modules ] assert modules == ['Example'] def test_module_on_module(self): """ No module configuration for modules Check that the feature is detected as disabled :return: """ self.setup_with_file('cfg/modules/alignak_module_with_submodules.cfg') assert self.conf_is_correct self.show_configuration_logs() # arbiter modules modules = [ m.module_alias for m in self._arbiter.link_to_myself.modules ] assert modules == ['Example'] modules = [m.name for m in self._arbiter.link_to_myself.modules] assert modules == ['Example'] # broker modules modules = [m.module_alias for m in self._broker_daemon.modules] assert modules == ['Example'] modules = [m.name for m in self._broker_daemon.modules] assert modules == ['Example'] # # The only existing poller module is Example declared in the configuration # modules = [m.module_alias for m in self.pollers['poller-master'].modules] # assert modules == ['Example'] # # # The only existing receiver module is Example declared in the configuration # modules = [m.module_alias for m in self.receivers['receiver-master'].modules] # assert modules == ['Example'] # # # The only existing reactionner module is Example declared in the configuration # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules] # assert modules == ['Example'] # No scheduler modules created modules = [m.module_alias for m in self._scheduler_daemon.modules] assert modules == ['Example', 'inner-retention'] modules = [m.name for m in self._scheduler_daemon.modules] assert modules == ['Example', 'inner-retention'] def test_modulemanager_1(self): """ Module manager manages its modules - old form Test if the module manager manages correctly all the modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example' }) self.run_modulemanager(mod) def test_modulemanager_2(self): """ Module manager manages its modules - new form Test if the module manager manages correctly all the modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # Create an Alignak module mod = Module({ 'name': 'mod-example', 'type': 'example', 'python_name': 'alignak_module_example' }) self.run_modulemanager(mod) def run_modulemanager(self, mod): # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([mod]) # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.clear_logs() my_module = self.modules_manager.instances[0] assert my_module.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module] == self.modules_manager.get_external_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [my_module ] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.show_logs() # Starting external module logs idx = 0 self.assert_log_match( re.escape("Trying to initialize module: mod-example"), idx) idx += 1 self.assert_log_match(re.escape("Test - Example in init"), idx) idx += 1 self.assert_log_match( re.escape("Initialization of the example module"), idx) idx += 1 self.assert_log_match(re.escape("Module mod-example is initialized"), idx) idx += 1 self.assert_log_match( re.escape("Starting external module mod-example"), idx) idx += 1 self.assert_log_match( re.escape("Starting external process for module mod-example"), idx) idx += 1 self.assert_log_match(re.escape("mod-example is now started (pid="), idx) idx += 1 self.assert_log_count(7) # Check alive assert my_module.process is not None assert my_module.process.is_alive() self.clear_logs() # Check the alive module instances... self.modules_manager.check_alive_instances() # Try to restart the dead modules, if any self.modules_manager.try_to_restart_deads() self.assert_log_count(0) # Kill the external module (normal stop is .stop_process) self.clear_logs() my_module.kill() idx = 0 self.assert_log_match(re.escape("Killing external module "), idx) idx += 1 self.show_logs() # self.assert_log_match(re.escape( # "mod-example is still living " # ), idx) # idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time normal_kill = True logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 normal_kill = False break log_num += 1 break self.assert_log_match(re.escape("External module killed"), idx) idx += 1 self.assert_log_count(idx) # The module is dead (not normally stopped...) so this module inner # process reference is not None! assert my_module.process is not None # Check the alive module instances... self.clear_logs() idx = 0 self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_match( re.escape("The external module mod-example died unexpectedly!"), idx) idx += 1 self.assert_log_match( re.escape("Setting the module mod-example to restart"), idx) self.assert_log_count(2) idx += 1 if normal_kill: # Try to restart the dead modules, if any # Indeed, it's too early, so it won't do it self.clear_logs() idx = 0 print("try init: %d" % my_module.init_try) self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match( re.escape("Trying to restart module: mod-example"), idx) idx += 1 self.assert_log_match( re.escape( "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD), idx) idx += 1 self.assert_log_count(2) # Here the module instance is still dead assert not my_module.process.is_alive() # Wait for a minimum delay time.sleep(MODULE_INIT_PERIOD + 1) # my_module.last_init_try = -5 self.clear_logs() self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_count(0) # Try to restart the dead modules, if any # Now it is time... self.clear_logs() idx = 0 self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match( re.escape("Trying to restart module: mod-example"), idx) idx += 1 self.assert_log_match( re.escape("Trying to initialize module: mod-example"), idx) idx += 1 self.assert_log_match(re.escape("Test - Example in init"), idx) idx += 1 self.assert_log_match( re.escape("Initialization of the example module"), idx) idx += 1 self.assert_log_match(re.escape("Module mod-example is initialized"), idx) idx += 1 self.assert_log_match(re.escape("Restarting mod-example..."), idx) idx += 1 self.assert_log_match( re.escape("Starting external process for module mod-example"), idx) idx += 1 self.assert_log_match(re.escape("mod-example is now started (pid="), idx) idx += 1 self.assert_log_count(8) # Here the module instance should be alive again assert my_module.process.is_alive() # No more module to restart... assert [] == self.modules_manager.to_restart # And we clear all now self.clear_logs() idx = 0 self.modules_manager.stop_all() self.show_logs() self.assert_log_match(re.escape("Shutting down modules..."), idx) idx += 1 self.assert_log_match( re.escape("Request external process to stop for mod-example"), idx) idx += 1 self.assert_log_match(re.escape("I'm stopping module 'mod-example'"), idx) idx += 1 self.assert_log_match(re.escape("Killing external module "), idx) idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 break log_num += 1 break self.assert_log_match(re.escape("External module killed"), idx) idx += 1 self.assert_log_match(re.escape("External process stopped."), idx) idx += 1 # self.assert_log_count(6) def test_modulemanager_several_modules(self): """ Module manager manages its modules Test if the module manager manages correctly all the modules Configured with several modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # for mod in self._arbiter.conf.modules: # print (mod.__dict__) # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'foo', 'option2': 'bar', 'option3': 1 }) mod2 = Module({ 'module_alias': 'mod-example-2', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'faa', 'option2': 'bor', 'option3': 1 }) # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) print("Modules: %s" % self._broker_daemon.modules) # Load an initialize the modules: # - load python module # - get module properties and instances assert self.modules_manager.load_and_init([mod, mod2]) print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in self.modules_manager.instances])) self.show_logs() self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example")) self.assert_any_log_match( re.escape( "Loaded Python module 'alignak_module_example' (mod-example)")) self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example-2..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example-2")) self.assert_any_log_match( re.escape( "Loaded Python module 'alignak_module_example' (mod-example-2)" )) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.assert_any_log_match(re.escape("configuration, foo, bar, 1")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example-2" )) self.assert_any_log_match(re.escape("configuration, faa, bor, 1")) # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) my_module = self.modules_manager.instances[0] my_module2 = self.modules_manager.instances[1] assert my_module.is_external assert my_module2.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module, my_module2] == self.modules_manager.get_external_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [my_module, my_module2 ] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.modules_manager.start_external_instances() # Starting external module logs self.assert_any_log_match( re.escape("Starting external module mod-example")) self.assert_any_log_match( re.escape("Starting external process for module mod-example")) self.assert_any_log_match( re.escape("mod-example is now started (pid=")) # Check alive assert my_module.process is not None assert my_module.process.is_alive() assert my_module2.process is not None assert my_module2.process.is_alive() # Kill the external module (normal stop is .stop_process) self.clear_logs() print("Killing a module") my_module.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape("Killing external module ")) self.assert_any_log_match(re.escape("External module killed")) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None self.clear_logs() print("Killing another module") my_module2.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape("Killing external module ")) self.assert_any_log_match(re.escape("External module killed")) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None # Nothing special ... self.clear_logs() self.modules_manager.check_alive_instances() # Try to restart the dead modules print("Trying to restart dead modules") # We lie on the last restart try time my_module.last_init_try = time.time() my_module2.last_init_try = time.time() self.modules_manager.try_to_restart_deads() self.show_logs() # In fact it's too early, so it won't do it # Here the module instances should still be dead assert not my_module.process.is_alive() assert not my_module2.process.is_alive() # We lie on the last restart try time my_module.last_init_try = 0 my_module2.last_init_try = 0 self.modules_manager.check_alive_instances() self.modules_manager.try_to_restart_deads() # Here the module instances should be alive again assert my_module.process.is_alive() assert my_module2.process.is_alive() # Kill the module again self.clear_logs() my_module.kill() self.show_logs() time.sleep(0.2) assert not my_module.process.is_alive() # And we clear all now self.modules_manager.stop_all() # Stopping module logs self.assert_any_log_match(re.escape("I'm stopping module "))
def run_modulemanager(self, mod): # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([mod]) # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.clear_logs() my_module = self.modules_manager.instances[0] assert my_module.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module] == self.modules_manager.get_external_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [my_module ] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.show_logs() # Starting external module logs idx = 0 self.assert_log_match( re.escape("Trying to initialize module: mod-example"), idx) idx += 1 self.assert_log_match(re.escape("Test - Example in init"), idx) idx += 1 self.assert_log_match( re.escape("Initialization of the example module"), idx) idx += 1 self.assert_log_match(re.escape("Module mod-example is initialized"), idx) idx += 1 self.assert_log_match( re.escape("Starting external module mod-example"), idx) idx += 1 self.assert_log_match( re.escape("Starting external process for module mod-example"), idx) idx += 1 self.assert_log_match(re.escape("mod-example is now started (pid="), idx) idx += 1 self.assert_log_count(7) # Check alive assert my_module.process is not None assert my_module.process.is_alive() self.clear_logs() # Check the alive module instances... self.modules_manager.check_alive_instances() # Try to restart the dead modules, if any self.modules_manager.try_to_restart_deads() self.assert_log_count(0) # Kill the external module (normal stop is .stop_process) self.clear_logs() my_module.kill() idx = 0 self.assert_log_match(re.escape("Killing external module "), idx) idx += 1 self.show_logs() # self.assert_log_match(re.escape( # "mod-example is still living " # ), idx) # idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time normal_kill = True logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 normal_kill = False break log_num += 1 break self.assert_log_match(re.escape("External module killed"), idx) idx += 1 self.assert_log_count(idx) # The module is dead (not normally stopped...) so this module inner # process reference is not None! assert my_module.process is not None # Check the alive module instances... self.clear_logs() idx = 0 self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_match( re.escape("The external module mod-example died unexpectedly!"), idx) idx += 1 self.assert_log_match( re.escape("Setting the module mod-example to restart"), idx) self.assert_log_count(2) idx += 1 if normal_kill: # Try to restart the dead modules, if any # Indeed, it's too early, so it won't do it self.clear_logs() idx = 0 print("try init: %d" % my_module.init_try) self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match( re.escape("Trying to restart module: mod-example"), idx) idx += 1 self.assert_log_match( re.escape( "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD), idx) idx += 1 self.assert_log_count(2) # Here the module instance is still dead assert not my_module.process.is_alive() # Wait for a minimum delay time.sleep(MODULE_INIT_PERIOD + 1) # my_module.last_init_try = -5 self.clear_logs() self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_count(0) # Try to restart the dead modules, if any # Now it is time... self.clear_logs() idx = 0 self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match( re.escape("Trying to restart module: mod-example"), idx) idx += 1 self.assert_log_match( re.escape("Trying to initialize module: mod-example"), idx) idx += 1 self.assert_log_match(re.escape("Test - Example in init"), idx) idx += 1 self.assert_log_match( re.escape("Initialization of the example module"), idx) idx += 1 self.assert_log_match(re.escape("Module mod-example is initialized"), idx) idx += 1 self.assert_log_match(re.escape("Restarting mod-example..."), idx) idx += 1 self.assert_log_match( re.escape("Starting external process for module mod-example"), idx) idx += 1 self.assert_log_match(re.escape("mod-example is now started (pid="), idx) idx += 1 self.assert_log_count(8) # Here the module instance should be alive again assert my_module.process.is_alive() # No more module to restart... assert [] == self.modules_manager.to_restart # And we clear all now self.clear_logs() idx = 0 self.modules_manager.stop_all() self.show_logs() self.assert_log_match(re.escape("Shutting down modules..."), idx) idx += 1 self.assert_log_match( re.escape("Request external process to stop for mod-example"), idx) idx += 1 self.assert_log_match(re.escape("I'm stopping module 'mod-example'"), idx) idx += 1 self.assert_log_match(re.escape("Killing external module "), idx) idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 break log_num += 1 break self.assert_log_match(re.escape("External module killed"), idx) idx += 1 self.assert_log_match(re.escape("External process stopped."), idx) idx += 1
class TestModuleWsHostgroup(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ[ 'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test' # Delete used mongo DBs print("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split('mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'])) assert exit_code == 0 fnull = open(os.devnull, 'w') cls.p = subprocess.Popen([ 'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid' ], stdout=fnull, stderr=fnull) time.sleep(3) endpoint = 'http://127.0.0.1:5000' test_dir = os.path.dirname(os.path.realpath(__file__)) print("Current test directory: %s" % test_dir) print("Feeding Alignak backend... %s" % test_dir) exit_code = subprocess.call(shlex.split( 'alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir), stdout=fnull, stderr=fnull) assert exit_code == 0 print("Fed") # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = { 'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id } response = requests.post(endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print("Created a new user: %s" % resp) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = { 'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag'] } data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' @classmethod def tearDownClass(cls): cls.p.kill() def setUp(self): """Create resources in backend :return: None """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) self.my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(self.my_module.process) self.assertTrue(self.my_module.process.is_alive()) time.sleep(1) def tearDown(self): if self.modulemanager: time.sleep(1) self.modulemanager.stop_all() def test_module_zzz_hostgroup_get(self): """Test the module /hostgroup API - hostgroup get information :return: """ # Do not allow GET request on /hostgroup - not yet authorized! response = requests.get('http://127.0.0.1:8888/hostgroup') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Get a non-existing host - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/hostgroup', auth=self.auth, params={'name': 'fake-hostgroup'}) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested hostgroup 'fake-hostgroup' does not exist"] }) # Get a non-existing host - 2nd: use hostgroup name in the URI response = session.get( 'http://127.0.0.1:8888/hostgroup/fake-hostgroup', auth=self.auth) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested hostgroup 'fake-hostgroup' does not exist"] }) #Â ----- # Get all hostgroups ... no parameters! response = session.get('http://127.0.0.1:8888/hostgroup', auth=self.auth) result = response.json() # from pprint import pprint # pprint(result) self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(len(result['_result']), 13) #Â ----- # Get a specific hostgroup - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/hostgroup', auth=self.auth, params={'name': 'hostgroup_01'}) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(result['_result'][0]['name'], 'hostgroup_01') # Get a specific hostgroup - 2nd: use hostgroup name in the URI response = session.get('http://127.0.0.1:8888/hostgroup/hostgroup_01', auth=self.auth) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) # Comparing is tricky because of the changing objects _id ... # self.assertEqual(result['_result'][0], { # u'_level': 1, u'name': u'hostgroup_01', u'notes': u'', u'hostgroups': [], # u'_parent': {u'alias': u'All hosts', u'name': u'All'}, u'alias': u'hostgroup_alias_01', # u'hosts': [{u'alias': u'up_0', u'name': u'test_host_0'}], # u'_tree_parents': [{u'alias': u'All hosts', u'name': u'All'}], # u'_realm': {u'alias': u'All', u'name': u'All'} # }) # Get a specific hostgroup - embed related items response = session.get('http://127.0.0.1:8888/hostgroup/hostgroup_01', auth=self.auth, params={'embedded': True}) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) print(result['_result'][0]) result['_result'][0].pop('_id') result['_result'][0].pop('_created') result['_result'][0].pop('_updated') self.assertEqual( result['_result'][0], { u'_level': 1, u'name': u'hostgroup_01', u'notes': u'', u'hostgroups': [], u'_parent': { u'alias': u'All hosts', u'name': u'All' }, u'alias': u'hostgroup_alias_01', u'hosts': [{ u'alias': u'up_0', u'name': u'test_host_0' }], u'_tree_parents': [{ u'alias': u'All hosts', u'name': u'All' }], u'_realm': { u'alias': u'All', u'name': u'All' } }) #Â ----- # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out')
def setUp(self): """Create resources in backend :return: None """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) self.my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(self.my_module.process) self.assertTrue(self.my_module.process.is_alive()) time.sleep(1)
def test_module_zzz_command(self): """ Test the WS /command endpoint :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Do not allow GET request on /command - not yet authorized response = requests.get('http://127.0.0.1:8888/command') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Allowed request on /command response = session.get('http://127.0.0.1:8888/command') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must only POST on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have a command parameter when POSTing on /command headers = {'Content-Type': 'application/json'} data = { # "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') # Result error message self.assertEqual(result['_error'], 'Missing command parameter') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1') # Request to execute an external command with timestamp - bad value headers = {'Content-Type': 'application/json'} data = { "command": "Command", "timestamp": "text", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, { u'_status': u'ERR', u'_error': u'Timestamp must be an integer value' }) # Request to execute an external command with timestamp headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "timestamp": "1234", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = session.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
class TestMetricsSetup(AlignakTest): """ This class tests the inner metrics module set-up """ def setUp(self): super(TestMetricsSetup, self).setUp() # Log at DEBUG level self.set_unit_tests_logger_level() self.clear_logs() # Create a fake server self.fake_carbon = FakeCarbonServer(port=2004) if os.path.exists('/tmp/alignak-metrics.log'): os.remove('/tmp/alignak-metrics.log') def tearDown(self): super(TestMetricsSetup, self).tearDown() self.fake_carbon.stop() self.fake_carbon.join() def test_default_is_disabled(self): """ Test that default configuration is metrics disabled :return: None """ self.setup_with_file('cfg/cfg_default.cfg') # Default configuration do not enable the module assert True == self._scheduler.pushed_conf.process_performance_data assert self._scheduler.pushed_conf.host_perfdata_command is None assert self._scheduler.pushed_conf.service_perfdata_command is None assert self._scheduler.pushed_conf.host_perfdata_file == '' assert self._scheduler.pushed_conf.service_perfdata_file == '' assert self._broker_daemon.modules == [] def test_inner_module_enabled(self): """ Test that inner metrics module may be enabled If configuration parameters host_perfdata_command or service_perfdata_command are declared and not empty and if process_performance_data is set, the inner metrics module is configured and enabled to push performance data to the Alignak configured StatsD / Graphite interface. :return: None """ self.setup_with_file('cfg/cfg_metrics.cfg') # Specific configuration enables the module assert True == self._scheduler.pushed_conf.process_performance_data assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts' assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services' assert 1 == len(self._broker_daemon.modules) self.show_logs() def test_inner_module_configuration(self): """ Test that inner metrics module may be configured in Alignak configuration Withi this configuration, hosts/services cache is enabled and tested. Broks for unknown hosts/services are ignored. :return: None """ self.setup_with_file('cfg/cfg_metrics.cfg', 'cfg/inner_metrics/alignak.ini') # Specific configuration enables the module assert True == self._scheduler.pushed_conf.process_performance_data assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts' assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services' assert 1 == len(self._broker_daemon.modules) self.show_logs() # The declared module instance my_module = self._broker_daemon.modules[0] print(my_module) # Generic stuff assert my_module.python_name == 'alignak.modules.inner_metrics' assert my_module.type == 'metrics' assert my_module.alias == 'inner-metrics' assert my_module.enabled is True # Specific stuff - the content of the configuration parameters # When the module is configured in Alignak configuration, it does not exist! # assert my_module.host_perfdata_file == 'go-hosts' # assert my_module.service_perfdata_file == 'go-services' self.clear_logs() # Module is not yet initialized, let's do it in place of the daemon. # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([my_module]) self.show_logs() # Module is an internal one (no external process) in the broker daemon modules manager my_module = self._broker_daemon.modules_manager.instances[0] assert my_module.is_external is False # Known hosts/services cache is empty assert my_module.hosts_cache == {} assert my_module.services_cache == {} # When the broker daemon receives a Brok, it is propagated to the module # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(1) self.assert_log_match("received host check result for an unknown host", 0) # Service check result self.clear_logs() scr = { "host_name": "srv001", "service_description": "ping", "command_name": "ping", "attempt": 1, "execution_time": 3.1496069431000002, "latency": 0.2317881584, "return_code": 2, "state": "OK", "state_type": "HARD", "state_id": 0, "state_type_id": 1, "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms", "long_output": "Long output ...", "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0", "passive_check": False, "problem_has_been_acknowledged": False, "acknowledgement_type": 1, "in_scheduled_downtime": False, "last_chk": 1473597375, "last_state_change": 1444427108.147903, "last_state_id": 0, "last_state": "UNKNOWN", "last_state_type": "HARD", "last_hard_state_change": 0.0, "last_time_unknown": 0, "last_time_unreachable": 0, "last_time_critical": 1473597376, "last_time_warning": 0, "last_time_ok": 0, "retry_interval": 2, "percent_state_change": 4.1, "check_interval": 5, "in_checking": False, "early_timeout": 0, "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc", "current_event_id": 1, "last_event_id": 0, "current_problem_id": 1, "last_problem_id": 0, "timeout": 0, "has_been_checked": 1, "start_time": 0, "end_time": 0 } b = Brok({'data': scr, 'type': 'service_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(1) self.assert_log_match("received service check result for an unknown host", 0) # Initial host status self.clear_logs() hcr = { "host_name": "srv001", } b = Brok({'data': hcr, 'type': 'initial_host_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert my_module.services_cache == {} # Initial service status self.clear_logs() hcr = { "host_name": "srv001", "service_description": "ping" } b = Brok({'data': hcr, 'type': 'initial_service_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert 'srv001/ping' in my_module.services_cache assert my_module.services_cache['srv001/ping'] == {} # Now the host srv001 is known in the module, let's raise an host brok # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) # 5 log events because the Graphite server do not respond! self.show_logs() # self.assert_any_log_match(re.escape('Exception: [Errno 111] Connection refused')) self.assert_log_count(0) # File output assert os.path.exists('/tmp/alignak-metrics.log') def test_inner_module_broks(self): """ Test that inner metrics module is managing broks with the default configuration :return: None """ self.setup_with_file('cfg/cfg_metrics.cfg') # Specific configuration enables the module assert True == self._scheduler.pushed_conf.process_performance_data assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts' assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services' assert 1 == len(self._broker_daemon.modules) self.show_logs() # The declared module instance my_module = self._broker_daemon.modules[0] # Generic stuff assert my_module.python_name == 'alignak.modules.inner_metrics' assert my_module.type == 'metrics' assert my_module.alias == 'inner-metrics' assert my_module.enabled is True # Specific stuff - the content of the configuration parameters assert my_module.host_perfdata_file == 'go-hosts' assert my_module.service_perfdata_file == 'go-services' self.clear_logs() # Module is not yet initialized, let's do it in place of the daemon. # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([my_module]) self.show_logs() # Module is an internal one (no external process) in the broker daemon modules manager my_module = self._broker_daemon.modules_manager.instances[0] assert my_module.is_external is False # Known hosts/services cache is empty assert my_module.hosts_cache == {} assert my_module.services_cache == {} # When the broker daemon receives a Brok, it is propagated to the module # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(0) # Service check result self.clear_logs() scr = { "host_name": "srv001", "service_description": "ping", "command_name": "ping", "attempt": 1, "execution_time": 3.1496069431000002, "latency": 0.2317881584, "return_code": 2, "state": "OK", "state_type": "HARD", "state_id": 0, "state_type_id": 1, "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms", "long_output": "Long output ...", "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0", "passive_check": False, "problem_has_been_acknowledged": False, "acknowledgement_type": 1, "in_scheduled_downtime": False, "last_chk": 1473597375, "last_state_change": 1444427108.147903, "last_state_id": 0, "last_state": "UNKNOWN", "last_state_type": "HARD", "last_hard_state_change": 0.0, "last_time_unknown": 0, "last_time_unreachable": 0, "last_time_critical": 1473597376, "last_time_warning": 0, "last_time_ok": 0, "retry_interval": 2, "percent_state_change": 4.1, "check_interval": 5, "in_checking": False, "early_timeout": 0, "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc", "current_event_id": 1, "last_event_id": 0, "current_problem_id": 1, "last_problem_id": 0, "timeout": 0, "has_been_checked": 1, "start_time": 0, "end_time": 0 } b = Brok({'data': scr, 'type': 'service_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(0) # Initial host status self.clear_logs() hcr = { "host_name": "srv001", } b = Brok({'data': hcr, 'type': 'initial_host_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert my_module.services_cache == {} # Initial service status self.clear_logs() hcr = { "host_name": "srv001", "service_description": "ping" } b = Brok({'data': hcr, 'type': 'initial_service_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert 'srv001/ping' in my_module.services_cache assert my_module.services_cache['srv001/ping'] == {}
def test_inner_module_broks(self): """ Test that inner metrics module is managing broks with the default configuration :return: None """ self.setup_with_file('cfg/cfg_metrics.cfg') # Specific configuration enables the module assert True == self._scheduler.pushed_conf.process_performance_data assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts' assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services' assert 1 == len(self._broker_daemon.modules) self.show_logs() # The declared module instance my_module = self._broker_daemon.modules[0] # Generic stuff assert my_module.python_name == 'alignak.modules.inner_metrics' assert my_module.type == 'metrics' assert my_module.alias == 'inner-metrics' assert my_module.enabled is True # Specific stuff - the content of the configuration parameters assert my_module.host_perfdata_file == 'go-hosts' assert my_module.service_perfdata_file == 'go-services' self.clear_logs() # Module is not yet initialized, let's do it in place of the daemon. # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([my_module]) self.show_logs() # Module is an internal one (no external process) in the broker daemon modules manager my_module = self._broker_daemon.modules_manager.instances[0] assert my_module.is_external is False # Known hosts/services cache is empty assert my_module.hosts_cache == {} assert my_module.services_cache == {} # When the broker daemon receives a Brok, it is propagated to the module # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(0) # Service check result self.clear_logs() scr = { "host_name": "srv001", "service_description": "ping", "command_name": "ping", "attempt": 1, "execution_time": 3.1496069431000002, "latency": 0.2317881584, "return_code": 2, "state": "OK", "state_type": "HARD", "state_id": 0, "state_type_id": 1, "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms", "long_output": "Long output ...", "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0", "passive_check": False, "problem_has_been_acknowledged": False, "acknowledgement_type": 1, "in_scheduled_downtime": False, "last_chk": 1473597375, "last_state_change": 1444427108.147903, "last_state_id": 0, "last_state": "UNKNOWN", "last_state_type": "HARD", "last_hard_state_change": 0.0, "last_time_unknown": 0, "last_time_unreachable": 0, "last_time_critical": 1473597376, "last_time_warning": 0, "last_time_ok": 0, "retry_interval": 2, "percent_state_change": 4.1, "check_interval": 5, "in_checking": False, "early_timeout": 0, "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc", "current_event_id": 1, "last_event_id": 0, "current_problem_id": 1, "last_problem_id": 0, "timeout": 0, "has_been_checked": 1, "start_time": 0, "end_time": 0 } b = Brok({'data': scr, 'type': 'service_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(0) # Initial host status self.clear_logs() hcr = { "host_name": "srv001", } b = Brok({'data': hcr, 'type': 'initial_host_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert my_module.services_cache == {} # Initial service status self.clear_logs() hcr = { "host_name": "srv001", "service_description": "ping" } b = Brok({'data': hcr, 'type': 'initial_service_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {} assert 'srv001/ping' in my_module.services_cache assert my_module.services_cache['srv001/ping'] == {}
class TestModules(AlignakTest): """ This class contains the tests for the module """ def test_module_loading(self): """ Test arbiter, broker, ... auto-generated modules Alignak module loading :return: """ self.print_header() self.setup_with_file('./cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) self.show_configuration_logs() # No arbiter modules created modules = [m.module_alias for m in self.arbiter.myself.modules] self.assertListEqual(modules, []) # The only existing broker module is logs declared in the configuration modules = [m.module_alias for m in self.brokers['broker-master'].modules] self.assertListEqual(modules, []) # No poller module modules = [m.module_alias for m in self.pollers['poller-master'].modules] self.assertListEqual(modules, []) # No receiver module modules = [m.module_alias for m in self.receivers['receiver-master'].modules] self.assertListEqual(modules, ['web-services']) # No reactionner module modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules] self.assertListEqual(modules, []) # No scheduler modules modules = [m.module_alias for m in self.schedulers['scheduler-master'].modules] self.assertListEqual(modules, []) def test_module_manager(self): """ Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load and initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_ws' for web-services..." )) self.assert_any_log_match(re.escape( "Module properties: {'daemons': ['receiver'], 'phases': ['running'], " "'type': 'web-services', 'external': True}" )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_ws' for web-services" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_ws' (web-services)" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_ws for alias: web-services" )) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([], self.modulemanager.get_internal_instances()) for phase in ['configuration', 'late_configuration', 'running', 'retention']: self.assertListEqual([], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([my_module], self.modulemanager.get_external_instances()) for phase in ['configuration', 'late_configuration', 'retention']: self.assertListEqual([], self.modulemanager.get_external_instances(phase)) for phase in ['running']: self.assertListEqual([my_module], self.modulemanager.get_external_instances(phase)) # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) # Clear logs self.clear_logs() # Kill the external module (normal stop is .stop_process) my_module.kill() time.sleep(0.1) self.assert_log_match("Killing external module", 0) self.assert_log_match("External module killed", 1) # Should be dead (not normally stopped...) but we still know a process for this module! self.assertIsNotNone(my_module.process) # Nothing special ... self.modulemanager.check_alive_instances() self.assert_log_match("The external module web-services died unexpectedly!", 2) self.assert_log_match("Setting the module web-services to restart", 3) # Try to restart the dead modules self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 4) # In fact it's too early, so it won't do it # The module instance is still dead self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 5) # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("I'm stopping module 'web-services'", 6) self.assert_log_match("Starting external process for module web-services", 7) self.assert_log_match("web-services is now started", 8) # There is nothing else to restart in the module manager self.assertEqual([], self.modulemanager.to_restart) # Clear logs self.clear_logs() # Now we look for time restart so we kill it again my_module.kill() time.sleep(0.2) self.assertFalse(my_module.process.is_alive()) self.assert_log_match("Killing external module", 0) self.assert_log_match("External module killed", 1) # Should be too early self.modulemanager.check_alive_instances() self.assert_log_match("The external module web-services died unexpectedly!", 2) self.assert_log_match("Setting the module web-services to restart", 3) self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 4) # In fact it's too early, so it won't do it # The module instance is still dead self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 5) # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("I'm stopping module 'web-services'", 6) self.assert_log_match("Starting external process for module web-services", 7) self.assert_log_match("web-services is now started", 8) # And we clear all now self.modulemanager.stop_all() # Stopping module logs self.assert_log_match("Request external process to stop for web-services", 9) self.assert_log_match(re.escape("I'm stopping module 'web-services' (pid="), 10) self.assert_log_match( re.escape("'web-services' is still alive after normal kill, I help it to die"), 11 ) self.assert_log_match("Killing external module ", 12) self.assert_log_match("External module killed", 13) self.assert_log_match("External process stopped.", 14) def test_module_start_default(self): """ Test the module initialization function, no parameters, using default :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Default initialization # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws' }) instance = alignak_module_ws.get_instance(mod) self.assertIsInstance(instance, BaseModule) self.assert_log_match( re.escape("Give an instance of alignak_module_ws for " "alias: web-services"), 0) self.assert_log_match( re.escape("configuration, Alignak Arbiter: 127.0.0.1:7770"), 1) self.assert_log_match( re.escape("configuration, listening on: 0.0.0.0:8888"), 2) self.assert_log_match( re.escape("SSL is not enabled, this is not recommended. " "You should consider enabling SSL!"), 3) def test_module_start_parameters(self): """ Test the module initialization function, no parameters, provide parameters :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', 'use_ssl': '1', 'alignak_host': 'my_host', 'alignak_port': 80, 'host': 'me', 'port': 8080, }) instance = alignak_module_ws.get_instance(mod) self.assertIsInstance(instance, BaseModule) self.assert_log_match( re.escape("Give an instance of alignak_module_ws for " "alias: web-services"), 0) self.assert_log_match( re.escape("configuration, Alignak Arbiter: my_host:80"), 1) self.assert_log_match( re.escape("configuration, listening on: me:8080"), 2) self.assert_log_match( re.escape("Error : the CA certificate /usr/local/etc/alignak/certs/ca.pem is " "missing (ca_cert).Please fix it in your configuration"), 3) self.assert_log_match( re.escape("SSL is not enabled, this is not recommended. " "You should consider enabling SSL!"), 4) def test_module_zzz_run(self): """ Test the module API :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Get the module API list and request on each endpoint response = requests.get('http://127.0.0.1:8888') api_list = response.json() for endpoint in api_list: print("Trying %s" % (endpoint)) response = requests.get('http://127.0.0.1:8888/' + endpoint) print("Response %d: %s" % (response.status_code, response.content)) self.assertEqual(response.status_code, 200) if response.status_code == 200: print("Got %s: %s" % (endpoint, response.json())) else: print("Error %s: %s" % (response.status_code, response.content)) time.sleep(1) # Do not allow GET request on /command response = requests.get('http://127.0.0.1:8888/command') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ko') self.assertEqual(result['_result'], 'You must only POST on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ko') self.assertEqual(result['_result'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND;test_host;abc;1') # Not during unit tests ... because module queues are not functional! # time.sleep(1) # self.assertEqual(my_module.received_commands, 1) # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') self.modulemanager.stop_all()
def test_inner_module_configuration(self): """ Test that inner metrics module may be configured in Alignak configuration With this configuration, hosts/services cache is enabled and tested. Broks for unknown hosts/services are ignored. :return: None """ with requests_mock.mock() as mr: mr.get("http://localhost:8086/ping", json={ "results":[{ "statement_id":0, "version":"1.7.2" }] }, status_code=204, headers={"x-influxdb-version": "1.7.2"}) mr.get("http://localhost:8086/query?q=SHOW+DATABASES&db=alignak", json={ "results":[{ "statement_id":0, "series":[ {"name":"databases","columns":["name"],"values":[["_internal"]]} ] }] }) mr.get("http://localhost:8086/query?q=SHOW+DATABASES&db=alignak", json={"results": [{"statement_id": 0}]}) mr.post("http://localhost:8086/query?q=CREATE+DATABASE+%22alignak%22&db=alignak", json={"results":[{ "statement_id":0 }]}) mr.post("http://localhost:8086/query?q=CREATE+RETENTION+POLICY+%22alignak%22+ON+%22alignak%22+DURATION+1y+REPLICATION+1+SHARD+DURATION+0s&db=alignak", json={"results":[{ "statement_id":0 }]}) mr.post("http://localhost:8086/write?db=alignak", status_code=204, json={"results":[{ "statement_id":0 }]}) self.setup_with_file('cfg/cfg_metrics.cfg', 'cfg/inner_metrics/alignak.ini') # Specific configuration enables the module assert self._scheduler.pushed_conf.process_performance_data is True assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts' assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services' assert 1 == len(self._broker_daemon.modules) self.show_logs() # The declared module instance my_module = self._broker_daemon.modules[0] print(my_module) # Generic stuff assert my_module.python_name == 'alignak.modules.inner_metrics' assert my_module.type == 'metrics' # assert my_module.alias == 'inner-metrics' assert my_module.enabled is True # Specific stuff - the content of the configuration parameters # When the module is configured in Alignak configuration, it does not exist! # assert my_module.host_perfdata_file == 'go-hosts' # assert my_module.service_perfdata_file == 'go-services' assert my_module.output_file == '/tmp/alignak-metrics.log' self.clear_logs() # Module is not yet initialized, let's do it in place of the daemon. # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([my_module]) self.show_logs() # self.assert_log_match( # "Targets configuration: graphite: True, influxdb: True, " # "file: /tmp/alignak-metrics.log", 10) # self.assert_log_match( "targets configuration: graphite: True, influxdb: True, " "file: /tmp/alignak-metrics.log", 11) self.assert_log_match( "Storing metrics in an output file is configured. Do not forget " "to regularly clean this file to avoid important disk usage!", 12) self.assert_log_match("Trying to initialize module: inner-metrics", 24) self.assert_log_match("testing storage to /tmp/alignak-metrics.log ...", 25) self.assert_log_match("Ok", 26) self.assert_log_match("testing connection to InfluxDB localhost:8086 ...", 27) self.assert_log_match("connected, InfluxDB version 1.7.2", 28) self.assert_log_match("testing connection to Graphite localhost:2004 ...", 29) self.assert_log_match("Ok", 30) self.assert_log_match("creating database alignak...", 31) # self.assert_log_match("creating database retention policy: alignak - 1y - 1...", 32) # self.assert_log_match("Ok", 33) self.assert_log_match("Module inner-metrics is initialized.", 32) # Module is an internal one (no external process) in the broker daemon modules manager my_module = self._broker_daemon.modules_manager.instances[0] assert my_module.is_external is False # Known hosts/services cache is empty assert my_module.hosts_cache == {} assert my_module.services_cache == {} # File output - we still got a metric for the connection test! assert os.path.exists('/tmp/alignak-metrics.log') with open('/tmp/alignak-metrics.log') as f: lines = f.readlines() first_line = False for line in lines: assert 3 == len(line.split(';')) if not first_line: line = line.strip() metric = line.split(';') assert metric[0] == metric[2] assert metric[1] == 'connection-test' print(line) # Some metrics were stored assert 2 == len(lines) # When the broker daemon receives a Brok, it is propagated to the module # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(2) self.assert_log_match("host check result: srv001", 0) self.assert_log_match("received host check result for an unknown host: srv001", 1) # Service check result self.clear_logs() scr = { "host_name": "srv001", "service_description": "ping", "command_name": "ping", "attempt": 1, "execution_time": 3.1496069431000002, "latency": 0.2317881584, "return_code": 2, "state": "OK", "state_type": "HARD", "state_id": 0, "state_type_id": 1, "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms", "long_output": "Long output ...", "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0", "passive_check": False, "problem_has_been_acknowledged": False, "acknowledgement_type": 1, "in_scheduled_downtime": False, "last_chk": 1473597375, "last_state_change": 1444427108.147903, "last_state_id": 0, "last_state": "UNKNOWN", "last_state_type": "HARD", "last_hard_state_change": 0.0, "last_time_unknown": 0, "last_time_unreachable": 0, "last_time_critical": 1473597376, "last_time_warning": 0, "last_time_ok": 0, "retry_interval": 2, "percent_state_change": 4.1, "check_interval": 5, "in_checking": False, "early_timeout": 0, "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc", "current_event_id": 1, "last_event_id": 0, "current_problem_id": 1, "last_problem_id": 0, "timeout": 0, "has_been_checked": 1, "start_time": 0, "end_time": 0 } b = Brok({'data': scr, 'type': 'service_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(2) self.assert_log_match("service check result: srv001/ping", 0) self.assert_log_match("received service check result for an unknown host", 1) # Initial host status self.clear_logs() hcr = { "host_name": "srv001", } b = Brok({'data': hcr, 'type': 'initial_host_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {'realm_name': 'All'} assert my_module.services_cache == {} # Initial service status self.clear_logs() hcr = { "host_name": "srv001", "service_description": "disks" } b = Brok({'data': hcr, 'type': 'initial_service_status'}, False) self._broker_daemon.manage_brok(b) self.show_logs() # The module inner cache stored the host assert 'srv001' in my_module.hosts_cache assert my_module.hosts_cache['srv001'] == {'realm_name': 'All'} assert 'srv001/disks' in my_module.services_cache assert my_module.services_cache['srv001/disks'] == {} # Now the host srv001 is known in the module, let's raise an host brok # Host check result self.clear_logs() hcr = { "host_name": "srv001", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_host_alive", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "DOWN", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "CRITICAL - Plugin timed out after 10 seconds", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "uptime=1200 rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0" } b = Brok({'data': hcr, 'type': 'host_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(9) self.assert_log_match("host check result: srv001", 0) self.assert_log_match("service: host_check, metric: ", 1) self.assert_log_match("service: host_check, metric: ", 2) self.assert_log_match("service: host_check, metric: ", 3) self.assert_log_match("Metrics: host_check - ", 4) self.assert_log_match("Data: ", 5) self.assert_log_match("Flushing 1 metrics to Graphite/carbon", 6) self.assert_log_match("Flushing 1 metrics to InfluxDB", 7) self.assert_log_match("Storing 1 metrics to /tmp/alignak-metrics.log", 8) # Service check result self.clear_logs() scr = { "host_name": "srv001", "service_description": "disks", "last_time_unreachable": 0, "last_problem_id": 0, "passive_check": False, "retry_interval": 1, "last_event_id": 0, "problem_has_been_acknowledged": False, "command_name": "pm-check_linux_disks", "last_state": "UP", "latency": 0.2317881584, "last_state_type": "HARD", "last_hard_state_change": 1444427108, "last_time_up": 0, "percent_state_change": 0.0, "state": "OK", "last_chk": 1444427104, "last_state_id": 0, "end_time": 0, "timeout": 0, "current_event_id": 10, "execution_time": 3.1496069431000002, "start_time": 0, "return_code": 2, "state_type": "SOFT", "output": "DISK OK - free space: / 3326 MB (56%); / 15272 MB (77%);/boot 68 MB (69%);/home 69357 MB (27%);/var/log 819 MB (84%);", "in_checking": True, "early_timeout": 0, "in_scheduled_downtime": False, "attempt": 0, "state_type_id": 1, "acknowledgement_type": 1, "last_state_change": 1444427108.040841, "last_time_down": 1444427108, "instance_id": 0, "long_output": "", "current_problem_id": 0, "check_interval": 5, "state_id": 2, "has_been_checked": 1, "perf_data": "/=2643MB;5948;5958;0;5968 /boot=68MB;88;93;0;98 /home=69357MB;253404;253409;0;253414 /var/log=818MB;970;975;0;980" } b = Brok({'data': scr, 'type': 'service_check_result'}, False) self._broker_daemon.manage_brok(b) self.show_logs() self.assert_log_count(10) self.assert_log_match("service check result: srv001/disks", 0) self.assert_log_match(re.escape("service: disks, metric: "), 1) self.assert_log_match(re.escape("service: disks, metric: "), 2) self.assert_log_match(re.escape("service: disks, metric: "), 3) self.assert_log_match(re.escape("service: disks, metric: "), 4) self.assert_log_match(re.escape("Metrics: disks - "), 5) self.assert_log_match("Data: ", 6) self.assert_log_match("Flushing 1 metrics to Graphite/carbon", 7) self.assert_log_match("Flushing 1 metrics to InfluxDB", 8) self.assert_log_match("Storing 1 metrics to /tmp/alignak-metrics.log", 9) # Metrics count # File output assert os.path.exists('/tmp/alignak-metrics.log') with open('/tmp/alignak-metrics.log') as f: lines = f.readlines() first_line = False for line in lines: line = line.strip() assert 3 == len(line.split(';')) print(line) if not first_line: first_line = True metric = line.split(';') assert metric[0] == metric[2] assert metric[1] == 'connection-test' # Some metrics were stored! assert 33 == len(lines)
def test_module_manager(self): """ Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'nrpe-booster', 'module_types': 'nrpe-booster', 'python_name': 'alignak_module_nrpe_booster' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('poller', None) # Clear logs self.clear_logs() # Load and initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module logs self.assert_log_match( re.escape( "Importing Python module 'alignak_module_nrpe_booster' for nrpe-booster..." ), 0) self.assert_log_match( re.escape( "Module properties: {'daemons': ['poller'], 'phases': ['running'], " "'type': 'nrpe_poller', 'external': False, 'worker_capable': True}" ), 1) self.assert_log_match( re.escape( "Imported 'alignak_module_nrpe_booster' for nrpe-booster"), 2) self.assert_log_match( re.escape( "Loaded Python module 'alignak_module_nrpe_booster' (nrpe-booster)" ), 3) self.assert_log_match( re.escape( "Give an instance of alignak_module_nrpe_booster for alias: nrpe-booster" ), 4) # Starting internal module logs self.assert_log_match("Trying to initialize module: nrpe-booster", 5) self.assert_log_match("Initialization of the NRPE poller module", 6) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([my_module], self.modulemanager.get_internal_instances()) for phase in ['configuration', 'late_configuration', 'retention']: self.assertListEqual( [], self.modulemanager.get_internal_instances(phase)) for phase in ['running']: self.assertListEqual( [my_module], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([], self.modulemanager.get_external_instances()) for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: self.assertListEqual( [], self.modulemanager.get_external_instances(phase)) # Clear logs self.clear_logs() # Nothing special ... self.modulemanager.check_alive_instances() # And we clear all now self.modulemanager.stop_all() # Stopping module logs self.assert_log_match("Ending the NRPE poller module", 0)
def test_modulemanager_several_modules(self): """ Module manager manages its modules Test if the module manager manages correctly all the modules Configured with several modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # for mod in self._arbiter.conf.modules: # print (mod.__dict__) # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'foo', 'option2': 'bar', 'option3': 1 }) mod2 = Module({ 'module_alias': 'mod-example-2', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'faa', 'option2': 'bor', 'option3': 1 }) # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) print("Modules: %s" % self._broker_daemon.modules) # Load an initialize the modules: # - load python module # - get module properties and instances assert self.modules_manager.load_and_init([mod, mod2]) print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in self.modules_manager.instances])) self.show_logs() self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example")) self.assert_any_log_match( re.escape( "Loaded Python module 'alignak_module_example' (mod-example)")) self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example-2..." )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for mod-example-2")) self.assert_any_log_match( re.escape( "Loaded Python module 'alignak_module_example' (mod-example-2)" )) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.assert_any_log_match(re.escape("configuration, foo, bar, 1")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: mod-example-2" )) self.assert_any_log_match(re.escape("configuration, faa, bor, 1")) # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) my_module = self.modules_manager.instances[0] my_module2 = self.modules_manager.instances[1] assert my_module.is_external assert my_module2.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module, my_module2] == self.modules_manager.get_external_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [my_module, my_module2 ] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.modules_manager.start_external_instances() # Starting external module logs self.assert_any_log_match( re.escape("Starting external module mod-example")) self.assert_any_log_match( re.escape("Starting external process for module mod-example")) self.assert_any_log_match( re.escape("mod-example is now started (pid=")) # Check alive assert my_module.process is not None assert my_module.process.is_alive() assert my_module2.process is not None assert my_module2.process.is_alive() # Kill the external module (normal stop is .stop_process) self.clear_logs() print("Killing a module") my_module.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape("Killing external module ")) self.assert_any_log_match(re.escape("External module killed")) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None self.clear_logs() print("Killing another module") my_module2.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape("Killing external module ")) self.assert_any_log_match(re.escape("External module killed")) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None # Nothing special ... self.clear_logs() self.modules_manager.check_alive_instances() # Try to restart the dead modules print("Trying to restart dead modules") # We lie on the last restart try time my_module.last_init_try = time.time() my_module2.last_init_try = time.time() self.modules_manager.try_to_restart_deads() self.show_logs() # In fact it's too early, so it won't do it # Here the module instances should still be dead assert not my_module.process.is_alive() assert not my_module2.process.is_alive() # We lie on the last restart try time my_module.last_init_try = 0 my_module2.last_init_try = 0 self.modules_manager.check_alive_instances() self.modules_manager.try_to_restart_deads() # Here the module instances should be alive again assert my_module.process.is_alive() assert my_module2.process.is_alive() # Kill the module again self.clear_logs() my_module.kill() self.show_logs() time.sleep(0.2) assert not my_module.process.is_alive() # And we clear all now self.modules_manager.stop_all() # Stopping module logs self.assert_any_log_match(re.escape("I'm stopping module "))
def run_modulemanager(self, mod): # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modules_manager.load_and_init([mod]) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.clear_logs() my_module = self.modules_manager.instances[0] assert my_module.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module] == self.modules_manager.get_external_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [my_module] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.show_logs() # Starting external module logs idx = 0 self.assert_log_match(re.escape( "Trying to initialize module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Test - Example in init" ), idx) idx += 1 self.assert_log_match(re.escape( "Initialization of the example module" ), idx) idx += 1 self.assert_log_match(re.escape( "Module mod-example is initialized" ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external process for module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "mod-example is now started (pid=" ), idx) idx += 1 self.assert_log_count(7) # Check alive assert my_module.process is not None assert my_module.process.is_alive() self.clear_logs() # Check the alive module instances... self.modules_manager.check_alive_instances() # Try to restart the dead modules, if any self.modules_manager.try_to_restart_deads() self.assert_log_count(0) # Kill the external module (normal stop is .stop_process) self.clear_logs() my_module.kill() idx = 0 self.assert_log_match(re.escape( "Killing external module " ), idx) idx += 1 self.show_logs() # self.assert_log_match(re.escape( # "mod-example is still living " # ), idx) # idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time normal_kill = True logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 normal_kill = False break log_num += 1 break self.assert_log_match(re.escape( "External module killed" ), idx) idx += 1 self.assert_log_count(idx) # The module is dead (not normally stopped...) so this module inner # process reference is not None! assert my_module.process is not None # Check the alive module instances... self.clear_logs() idx = 0 self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_match(re.escape( "The external module mod-example died unexpectedly!" ), idx) idx += 1 self.assert_log_match(re.escape( "Setting the module mod-example to restart" ), idx) self.assert_log_count(2) idx += 1 if normal_kill: # Try to restart the dead modules, if any # Indeed, it's too early, so it won't do it self.clear_logs() idx = 0 print("try init: %d" % my_module.init_try) self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match(re.escape( "Trying to restart module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD ), idx) idx += 1 self.assert_log_count(2) # Here the module instance is still dead assert not my_module.process.is_alive() # Wait for a minimum delay time.sleep(MODULE_INIT_PERIOD + 1) # my_module.last_init_try = -5 self.clear_logs() self.modules_manager.check_alive_instances() self.show_logs() self.assert_log_count(0) # Try to restart the dead modules, if any # Now it is time... self.clear_logs() idx = 0 self.modules_manager.try_to_restart_deads() self.show_logs() self.assert_log_match(re.escape( "Trying to restart module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Trying to initialize module: mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "Test - Example in init" ), idx) idx += 1 self.assert_log_match(re.escape( "Initialization of the example module" ), idx) idx += 1 self.assert_log_match(re.escape( "Module mod-example is initialized" ), idx) idx += 1 self.assert_log_match(re.escape( "Restarting mod-example..." ), idx) idx += 1 self.assert_log_match(re.escape( "Starting external process for module mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "mod-example is now started (pid=" ), idx) idx += 1 self.assert_log_count(8) # Here the module instance should be alive again assert my_module.process.is_alive() # No more module to restart... assert [] == self.modules_manager.to_restart # And we clear all now self.clear_logs() idx = 0 self.modules_manager.stop_all() self.show_logs() self.assert_log_match(re.escape( "Shutting down modules..." ), idx) idx += 1 self.assert_log_match(re.escape( "Request external process to stop for mod-example" ), idx) idx += 1 self.assert_log_match(re.escape( "I'm stopping module 'mod-example'" ), idx) idx += 1 self.assert_log_match(re.escape( "Killing external module " ), idx) idx += 1 # Specific case because sometimes the module is not killed within the expected 10s time logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME) for handler in logger_.handlers: if not isinstance(handler, CollectorHandler): continue regex = re.compile('mod-example is still living') log_num = 0 found = False for log in handler.collector: if idx == log_num: if regex.search(log): idx += 1 break log_num += 1 break self.assert_log_match(re.escape( "External module killed" ), idx) idx += 1 self.assert_log_match(re.escape( "External process stopped." ), idx) idx += 1
class TestModuleNrpeBooster(AlignakTest): """ This class contains the tests for the module """ def test_module_loading(self): """ Alignak module loading :return: """ self.print_header() self.setup_with_file('./cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) self.show_configuration_logs() # No arbiter modules created modules = [m.module_alias for m in self.arbiter.myself.modules] self.assertListEqual(modules, []) # The only existing broker module is logs declared in the configuration modules = [ m.module_alias for m in self.brokers['broker-master'].modules ] self.assertListEqual(modules, []) # No poller module modules = [ m.module_alias for m in self.pollers['poller-master'].modules ] self.assertListEqual(modules, ['nrpe-booster']) # No receiver module modules = [ m.module_alias for m in self.receivers['receiver-master'].modules ] self.assertListEqual(modules, []) # No reactionner module modules = [ m.module_alias for m in self.reactionners['reactionner-master'].modules ] self.assertListEqual(modules, []) # No scheduler modules modules = [ m.module_alias for m in self.schedulers['scheduler-master'].modules ] self.assertListEqual(modules, []) def test_module_manager(self): """ Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'nrpe-booster', 'module_types': 'nrpe-booster', 'python_name': 'alignak_module_nrpe_booster' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('poller', None) # Clear logs self.clear_logs() # Load and initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module logs self.assert_log_match( re.escape( "Importing Python module 'alignak_module_nrpe_booster' for nrpe-booster..." ), 0) self.assert_log_match( re.escape( "Module properties: {'daemons': ['poller'], 'phases': ['running'], " "'type': 'nrpe_poller', 'external': False, 'worker_capable': True}" ), 1) self.assert_log_match( re.escape( "Imported 'alignak_module_nrpe_booster' for nrpe-booster"), 2) self.assert_log_match( re.escape( "Loaded Python module 'alignak_module_nrpe_booster' (nrpe-booster)" ), 3) self.assert_log_match( re.escape( "Give an instance of alignak_module_nrpe_booster for alias: nrpe-booster" ), 4) # Starting internal module logs self.assert_log_match("Trying to initialize module: nrpe-booster", 5) self.assert_log_match("Initialization of the NRPE poller module", 6) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([my_module], self.modulemanager.get_internal_instances()) for phase in ['configuration', 'late_configuration', 'retention']: self.assertListEqual( [], self.modulemanager.get_internal_instances(phase)) for phase in ['running']: self.assertListEqual( [my_module], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([], self.modulemanager.get_external_instances()) for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: self.assertListEqual( [], self.modulemanager.get_external_instances(phase)) # Clear logs self.clear_logs() # Nothing special ... self.modulemanager.check_alive_instances() # And we clear all now self.modulemanager.stop_all() # Stopping module logs self.assert_log_match("Ending the NRPE poller module", 0) def test_module_start_default(self): """ Test the module initialization function, no parameters, using default :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Default initialization # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'nrpe-booster', 'module_types': 'nrpe-booster', 'python_name': 'alignak_module_nrpe_booster' }) instance = alignak_module_nrpe_booster.get_instance(mod) self.assertIsInstance(instance, BaseModule) self.assert_log_match( re.escape("Give an instance of alignak_module_nrpe_booster for " "alias: nrpe-booster"), 0)
class TestModuleManager(AlignakTest): def setUp(self): self.setup_with_file([]) time_hacker.set_real_time() # Try to see if the module manager can manage modules def test_modulemanager(self): mod = Module({'module_name': 'mod-example', 'module_type': 'example'}) path = sys.modules['alignak'].__path__[0] + '/modules' self.modulemanager = ModulesManager('broker', path, []) self.modulemanager.set_modules([mod]) self.modulemanager.load_and_init() # And start external ones, like our LiveStatus self.modulemanager.start_external_instances() print "I correctly loaded the modules: %s " % ([inst.get_name() for inst in self.modulemanager.instances]) print "*** First kill ****" # Now I will try to kill the livestatus module ls = self.modulemanager.instances[0] ls._BaseModule__kill() time.sleep(1) print "Check alive?" print "Is alive?", ls.process.is_alive() # Should be dead self.assertFalse(ls.process.is_alive()) self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # In fact it's too early, so it won't do it # Here the inst should still be dead print "Is alive?", ls.process.is_alive() self.assertFalse(ls.process.is_alive()) # So we lie ls.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # In fact it's too early, so it won't do it # Here the inst should be alive again print "Is alive?", ls.process.is_alive() self.assertTrue(ls.process.is_alive()) # should be nothing more in to_restart of # the module manager self.assertEqual([], self.modulemanager.to_restart) # Now we look for time restart so we kill it again ls._BaseModule__kill() time.sleep(1) self.assertFalse(ls.process.is_alive()) # Should be too early self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() print "Is alive or not", ls.process.is_alive() self.assertFalse(ls.process.is_alive()) # We lie for the test again ls.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # Here the inst should be alive again print "Is alive?", ls.process.is_alive() self.assertTrue(ls.process.is_alive()) # And we clear all now print "Ask to die" self.modulemanager.stop_all() print "Died"
def test_module_manager(self): """ Test if the module manager manages correctly all the modules :return: """ self.setup_with_file('./cfg/alignak.cfg') self.assertTrue(self.conf_is_correct) self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'nsca', 'module_types': 'nsca', 'python_name': 'alignak_module_nsca' }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager(self._broker_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module nsca print("Load and init") self.show_logs() i = 0 self.assert_log_match( re.escape( "Importing Python module 'alignak_module_nsca' for nsca..."), i) i += 1 # Dict order is problematic :/ # self.assert_log_match(re.escape( # "Module properties: {'daemons': ['broker'], 'phases': ['running'], " # "'type': 'nsca', 'external': True}" # ), i) i += 1 self.assert_log_match( re.escape("Imported 'alignak_module_nsca' for nsca"), i) i += 1 self.assert_log_match( re.escape("Loaded Python module 'alignak_module_nsca' (nsca)"), i) i += 1 self.assert_log_match(re.escape("Alignak starting module 'nsca'"), i) i += 1 self.assert_log_match( re.escape( "Give an instance of alignak_module_nsca for alias: nsca"), i) i += 1 self.assert_log_match( re.escape( "configuration, allowed hosts : '127.0.0.1'(5667), buffer length: 4096, " "payload length: -1, encryption: 0, max packet age: 30, " "check future packet: True, backlog: 10"), i) time.sleep(1) # Reload the module print("Reload") self.modulemanager.load([mod]) self.modulemanager.get_instances() # # Loading module nsca self.show_logs() i = 0 self.assert_log_match( re.escape( "Importing Python module 'alignak_module_nsca' for nsca..."), i) i += 1 # self.assert_log_match(re.escape( # "Module properties: {'daemons': ['broker'], 'phases': ['running'], " # "'type': 'nsca', 'external': True}" # ), i) i += 1 self.assert_log_match( re.escape("Imported 'alignak_module_nsca' for nsca"), i) i += 1 self.assert_log_match( re.escape("Loaded Python module 'alignak_module_nsca' (nsca)"), i) i += 1 self.assert_log_match(re.escape("Alignak starting module 'nsca'"), i) i += 1 self.assert_log_match( re.escape( "Give an instance of alignak_module_nsca for alias: nsca"), i) i += 1 self.assert_log_match( re.escape( "configuration, allowed hosts : '127.0.0.1'(5667), buffer length: 4096, " "payload length: -1, encryption: 0, max packet age: 30, " "check future packet: True, backlog: 10"), i) i += 1 self.assert_log_match( re.escape( "Importing Python module 'alignak_module_nsca' for nsca..."), i) i += 1 # self.assert_log_match(re.escape( # "Module properties: {'daemons': ['broker'], 'phases': ['running'], " # "'type': 'nsca', 'external': True}" # ), i) i += 1 self.assert_log_match( re.escape("Imported 'alignak_module_nsca' for nsca"), i) i += 1 self.assert_log_match( re.escape("Loaded Python module 'alignak_module_nsca' (nsca)"), i) i += 1 self.assert_log_match( re.escape("Request external process to stop for nsca"), i) i += 1 self.assert_log_match(re.escape("External process stopped."), i) i += 1 self.assert_log_match(re.escape("Alignak starting module 'nsca'"), i) i += 1 # self.assert_log_match(re.escape( # "Give an instance of alignak_module_nsca for alias: nsca" # ), i) # i += 1 self.assert_log_match( re.escape( "Give an instance of alignak_module_nsca for alias: nsca"), i) i += 1 self.assert_log_match( re.escape( "configuration, allowed hosts : '127.0.0.1'(5667), buffer length: 4096, " "payload length: -1, encryption: 0, max packet age: 30, " "check future packet: True, backlog: 10"), i) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([], self.modulemanager.get_internal_instances()) for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: self.assertListEqual( [], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([my_module], self.modulemanager.get_external_instances()) for phase in ['configuration', 'late_configuration', 'retention']: self.assertListEqual( [], self.modulemanager.get_external_instances(phase)) for phase in ['running']: self.assertListEqual( [my_module], self.modulemanager.get_external_instances(phase)) # Clear nsca self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module nsca self.assert_log_match("Trying to initialize module: nsca", 0) self.assert_log_match("Starting external module nsca", 1) self.assert_log_match("Starting external process for module nsca", 2) self.assert_log_match("nsca is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) # Clear nsca self.clear_logs() # Kill the external module (normal stop is .stop_process) my_module.kill() time.sleep(0.1) index = 0 self.assert_log_match("Killing external module", index) index = index + 1 # todo: This log is not expected! But it is probably because of the py.test ... # Indeed the receiver daemon that the module is attached to is receiving a SIGTERM !!! self.assert_log_match( re.escape( "nsca is still living 10 seconds after a normal kill, I help it to die" ), index) index = index + 1 self.assert_log_match("External module killed", index) index = index + 1 # Should be dead (not normally stopped...) but we still know a process for this module! self.assertIsNotNone(my_module.process) # Nothing special ... self.modulemanager.check_alive_instances() self.assert_log_match("The external module nsca died unexpectedly!", index) index = index + 1 self.assert_log_match("Setting the module nsca to restart", index) index = index + 1 # # Try to restart the dead modules # self.modulemanager.try_to_restart_deads() # self.assert_log_match("Trying to restart module: nsca", index) # index = index +1 # self.assert_log_match("Too early to retry initialization, retry period is 5 seconds", index) # index = index +1 # # # In fact it's too early, so it won't do it # # The module instance is still dead # self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to restart module: nsca", index) index = index + 1 self.assert_log_match("Trying to initialize module: nsca", index) index = index + 1 self.assert_log_match("Restarting nsca...", index) index = index + 1 # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("Starting external process for module nsca", index) index = index + 1 self.assert_log_match("nsca is now started", index) index = index + 1 # There is nothing else to restart in the module manager self.assertEqual([], self.modulemanager.to_restart) # Clear nsca self.clear_logs() # Let the module start and then kill it again time.sleep(3.0) my_module.kill() # time.sleep(5.0) self.show_logs() print("My module PID 2: %s" % my_module.process.pid) time.sleep(0.2) self.assertFalse(my_module.process.is_alive()) index = 0 self.assert_log_match("Killing external module", index) index = index + 1 # # todo: This log is not expected! But it is probably because of the py.test ... # # Indeed the receiver daemon that the module is attached to is receiving a SIGTERM !!! # self.assert_log_match(re.escape("'web-services' is still living 10 seconds after a normal kill, I help it to die"), index) # index = index +1 self.assert_log_match("External module killed", index) index = index + 1 # The module is dead but the modules manager do not know yet! self.modulemanager.check_alive_instances() self.assert_log_match("The external module nsca died unexpectedly!", index) index = index + 1 self.assert_log_match("Setting the module nsca to restart", index) index = index + 1 self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to restart module: nsca", index) index = index + 1 self.assert_log_match( "Too early to retry initialization, retry period is 5 seconds", index) index = index + 1 # In fact it's too early, so it won't do it # The module instance is still dead self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to restart module: nsca", index) index = index + 1 self.assert_log_match("Trying to initialize module: nsca", index) index = index + 1 self.assert_log_match("Restarting nsca...", index) index = index + 1 # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("Starting external process for module nsca", index) index = index + 1 self.assert_log_match("nsca is now started", index) index = index + 1 time.sleep(1.0) print("My module PID: %s" % my_module.process.pid) # Clear nsca self.clear_logs() # And we clear all now self.modulemanager.stop_all() # Stopping module nsca index = 0 self.assert_log_match("Shutting down modules...", index) index = index + 1 self.assert_log_match("Request external process to stop for nsca", index) index = index + 1 self.assert_log_match(re.escape("I'm stopping module 'nsca' (pid="), index) index = index + 1 # self.assert_log_match(re.escape("'nsca' is still living after a normal kill, I help it to die"), index) # index = index +1 self.assert_log_match(re.escape("Killing external module (pid"), index) index = index + 1 self.assert_log_match(re.escape("External module killed"), index) index = index + 1 self.assert_log_match("External process stopped.", index) index = index + 1
def test_module_zzz_command_unauthorized(self): """ Test the WS /command endpoint - unauthorized access mode :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend - not configured 'alignak_backend': '', 'username': '', 'password': '', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Disable authorization 'authorization': '0' }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) session = requests.Session() # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have a command parameter when POSTing on /command headers = {'Content-Type': 'application/json'} data = { # "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') # Result error message self.assertEqual(result['_error'], 'Missing command parameter') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 1) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1') # Request to execute an external command with timestamp - bad value headers = {'Content-Type': 'application/json'} data = { "command": "Command", "timestamp": "text", "element": "test_host", "parameters": "abc;1" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, { '_status': 'ERR', '_error': 'Timestamp must be an integer value' }) self.assertEqual(my_module.received_commands, 1) # Request to execute an external command with timestamp headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "timestamp": "1234", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 2) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 3) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 4) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 5) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 6) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') self.modulemanager.stop_all()
def test_modulemanager_several_modules(self): """ Module manager manages its modules Test if the module manager manages correctly all the modules Configured with several modules :return: """ self.setup_with_file('cfg/cfg_default_with_modules.cfg', 'cfg/default_with_modules/alignak.ini') assert self.conf_is_correct # for mod in self._arbiter.conf.modules: # print (mod.__dict__) # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'foo', 'option2': 'bar', 'option3': 1 }) mod2 = Module({ 'module_alias': 'mod-example-2', 'module_types': 'example', 'python_name': 'alignak_module_example', 'option1': 'faa', 'option2': 'bor', 'option3': 1 }) # Force the daemon SyncManager to None for unit tests! self._broker_daemon.sync_manager = None # Create the modules manager for a daemon type self.modules_manager = ModulesManager(self._broker_daemon) print("Modules: %s" % self._broker_daemon.modules) # Load an initialize the modules: # - load python module # - get module properties and instances assert self.modules_manager.load_and_init([mod, mod2]) print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in self.modules_manager.instances])) self.show_logs() self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_example' (mod-example)" )) self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example-2..." )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_example' for mod-example-2" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_example' (mod-example-2)" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example" )) self.assert_any_log_match(re.escape( "configuration, foo, bar, 1" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_example for alias: mod-example-2" )) self.assert_any_log_match(re.escape( "configuration, faa, bor, 1" )) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_example' for mod-example..." )) my_module = self.modules_manager.instances[0] my_module2 = self.modules_manager.instances[1] assert my_module.is_external assert my_module2.is_external # Get list of not external modules assert [] == self.modules_manager.get_internal_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [] == self.modules_manager.get_internal_instances(phase) # Get list of external modules assert [my_module, my_module2] == self.modules_manager.get_external_instances() for phase in ['configuration', 'late_configuration', 'running', 'retention']: assert [my_module, my_module2] == self.modules_manager.get_external_instances(phase) # Start external modules self.modules_manager.start_external_instances() self.modules_manager.start_external_instances() # Starting external module logs self.assert_any_log_match(re.escape( "Starting external module mod-example" )) self.assert_any_log_match(re.escape( "Starting external process for module mod-example" )) self.assert_any_log_match(re.escape( "mod-example is now started (pid=" )) # Check alive assert my_module.process is not None assert my_module.process.is_alive() assert my_module2.process is not None assert my_module2.process.is_alive() # Kill the external module (normal stop is .stop_process) self.clear_logs() print("Killing a module") my_module.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape( "Killing external module " )) self.assert_any_log_match(re.escape( "External module killed" )) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None self.clear_logs() print("Killing another module") my_module2.kill() time.sleep(0.1) self.show_logs() # Stopping module logs self.assert_any_log_match(re.escape( "Killing external module " )) self.assert_any_log_match(re.escape( "External module killed" )) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None # Nothing special ... self.clear_logs() self.modules_manager.check_alive_instances() # Try to restart the dead modules print("Trying to restart dead modules") # We lie on the last restart try time my_module.last_init_try = time.time() my_module2.last_init_try = time.time() self.modules_manager.try_to_restart_deads() self.show_logs() # In fact it's too early, so it won't do it # Here the module instances should still be dead assert not my_module.process.is_alive() assert not my_module2.process.is_alive() # We lie on the last restart try time my_module.last_init_try = 0 my_module2.last_init_try = 0 self.modules_manager.check_alive_instances() self.modules_manager.try_to_restart_deads() # Here the module instances should be alive again assert my_module.process.is_alive() assert my_module2.process.is_alive() # Kill the module again self.clear_logs() my_module.kill() self.show_logs() time.sleep(0.2) assert not my_module.process.is_alive() # And we clear all now self.modules_manager.stop_all() # Stopping module logs self.assert_any_log_match(re.escape( "I'm stopping module " ))
class TestModuleWsCommand(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): #Â Simulate an Alignak receiver daemon cls.ws_endpoint = 'http://127.0.0.1:7773/ws' import cherrypy class ReceiverItf(object): @cherrypy.expose def index(self): return "I am the Receiver daemon!" from alignak.http.daemon import HTTPDaemon as AlignakDaemon http_daemon1 = AlignakDaemon('0.0.0.0', 7773, ReceiverItf(), False, None, None, None, None, 10, '/tmp/alignak-cherrypy.log') def run_http_server(): http_daemon1.run() import threading cls.http_thread1 = threading.Thread(target=run_http_server, name='http_server_receiver') cls.http_thread1.daemon = True cls.http_thread1.start() print("Thread started") # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ[ 'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-command' # Delete used mongo DBs print("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split('mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'])) assert exit_code == 0 fnull = open(os.devnull, 'w') cls.p = subprocess.Popen([ 'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid' ], stdout=fnull, stderr=fnull) time.sleep(3) endpoint = 'http://127.0.0.1:5000' test_dir = os.path.dirname(os.path.realpath(__file__)) print(("Current test directory: %s" % test_dir)) print(("Feeding Alignak backend... %s" % test_dir)) exit_code = subprocess.call( shlex.split( 'alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir), # stdout=fnull, stderr=fnull ) assert exit_code == 0 print("Fed") # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = { 'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id } response = requests.post(endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print(("Created a new user: %s" % resp)) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = { 'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag'] } data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' @classmethod def tearDownClass(cls): cls.p.kill() def setUp(self): super(TestModuleWsCommand, self).setUp() def tearDown(self): super(TestModuleWsCommand, self).tearDown() if self.modulemanager: time.sleep(1) self.modulemanager.stop_all() def test_module_zzz_command(self): """ Test the WS /command endpoint :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, 'authorization': '1' }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Do not allow GET request on /command - not yet authorized response = requests.get(self.ws_endpoint + '/command') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Allowed request on /command response = session.get(self.ws_endpoint + '/command') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must only POST on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have a command parameter when POSTing on /command headers = {'Content-Type': 'application/json'} data = { # "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') # Result error message self.assertEqual(result['_error'], 'Missing command parameter') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1') # Request to execute an external command with timestamp - bad value headers = {'Content-Type': 'application/json'} data = { "command": "Command", "timestamp": "text", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 1) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, { '_status': 'ERR', '_error': 'Timestamp must be an integer value' }) # Request to execute an external command with timestamp headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "timestamp": "1234", "element": "test_host;test_service", "parameters": "1;abc;2" } self.assertEqual(my_module.received_commands, 1) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 3) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 4) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 5) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 6) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') # Logout response = session.get(self.ws_endpoint + '/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all() def test_module_zzz_command_unauthorized(self): """ Test the WS /command endpoint - unauthorized access mode :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend - not configured 'alignak_backend': '', 'username': '', 'password': '', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Disable authorization 'authorization': '0' }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) session = requests.Session() # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_error'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have a command parameter when POSTing on /command headers = {'Content-Type': 'application/json'} data = { # "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') # Result error message self.assertEqual(result['_error'], 'Missing command parameter') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 1) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1') # Request to execute an external command with timestamp - bad value headers = {'Content-Type': 'application/json'} data = { "command": "Command", "timestamp": "text", "element": "test_host", "parameters": "abc;1" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, { '_status': 'ERR', '_error': 'Timestamp must be an integer value' }) self.assertEqual(my_module.received_commands, 1) # Request to execute an external command with timestamp headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "timestamp": "1234", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 2) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 3) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 4) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 5) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual(result['_command'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = session.post(self.ws_endpoint + '/command', json=data, headers=headers) self.assertEqual(my_module.received_commands, 6) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') # Result is uppercase command, parameters are ordered self.assertEqual( result['_command'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') self.modulemanager.stop_all()
def test_modulemanager(self): mod = Module({'module_alias': 'mod-example', 'python_name': 'alignak_module_example'}) self.modulemanager = ModulesManager('broker', None) self.modulemanager.load_and_init([mod]) # And start external ones, like our LiveStatus self.modulemanager.start_external_instances() print "I correctly loaded the modules: %s " % ([inst.get_name() for inst in self.modulemanager.instances]) print "*** First kill ****" # Now I will try to kill the livestatus module ls = self.modulemanager.instances[0] " :type: alignak.basemodule.BaseModule " ls.kill() time.sleep(0.1) print "Check alive?" print "Is alive?", ls.process.is_alive() # Should be dead self.assertFalse(ls.process.is_alive()) self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # In fact it's too early, so it won't do it # Here the inst should still be dead print "Is alive?", ls.process.is_alive() self.assertFalse(ls.process.is_alive()) # So we lie ls.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # In fact it's too early, so it won't do it # Here the inst should be alive again print "Is alive?", ls.process.is_alive() self.assertTrue(ls.process.is_alive()) # should be nothing more in to_restart of # the module manager self.assertEqual([], self.modulemanager.to_restart) # Now we look for time restart so we kill it again ls.kill() time.sleep(0.2) self.assertFalse(ls.process.is_alive()) # Should be too early self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() print "Is alive or not", ls.process.is_alive() self.assertFalse(ls.process.is_alive()) # We lie for the test again ls.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # Here the inst should be alive again print "Is alive?", ls.process.is_alive() self.assertTrue(ls.process.is_alive()) # And we clear all now print "Ask to die" self.modulemanager.stop_all() print "Died"
def test_module_zzz_event(self): """Test the module /event endpoint :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, 'authorization': '1', }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Prepare the backend content... self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Get default realm response = requests.get(self.endpoint + '/realm', auth=self.auth) resp = response.json() self.realm_all = resp['_items'][0]['_id'] # --- # Do not allow GET request on /event - not yet authorized response = requests.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Do not allow GET request on /event response = session.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must only POST on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /event headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must POST parameters on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # Notify an host event - missing host or service headers = {'Content-Type': 'application/json'} data = { "fake": "" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing host and/or service parameter.']}) # Notify an host event - missing comment headers = {'Content-Type': 'application/json'} data = { "host": "test_host", } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing comment. If you do not have any comment, ' 'do not comment ;)']}) # Notify an host event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_HOST_COMMENT;test_host;1;' 'Alignak WS;My comment']}) # Notify an host event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_HOST_COMMENT;test_host;1;' 'Me;My comment']}) # Notify a service event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "service": "test_service", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_SVC_COMMENT;test_host;test_service;1;' 'Alignak WS;My comment']}) # Notify a service event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "service": "test_service", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_SVC_COMMENT;test_host;test_service;' '1;Me;My comment']}) # Get history to confirm that backend is ready # --- response = session.get(self.endpoint + '/history', auth=self.auth, params={"sort": "-_id", "max_results": 25, "page": 1}) resp = response.json() print(("Response: %s" % resp)) for item in resp['_items']: assert item['type'] in ['webui.comment'] # Got 4 notified events, so we get 4 comments in the backend self.assertEqual(len(resp['_items']), 4) # --- # Logout response = session.get(self.ws_endpoint + '/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
def test_module_host_livestate_unauthorized(self): """Test the module /host API - host livestate - unauthorized access :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': '', 'username': '', 'password': '', # Do not set a timestamp in the built external commands 'set_timestamp': '0', # Do not give feedback data 'give_feedback': '0', 'give_result': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Set module to listen on all interfaces 'host': '0.0.0.0', 'port': 8888, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1', # Force Alignak backend update by the module (default is not force!) 'alignak_backend_livestate_update': '0', # Disable authorization 'authorization': '0' }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) session = requests.Session() headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Update an host with an host livestate (heartbeat / host is alive): livestate # Because there is no backend configured, only an external command is raised # to Alignak for the host data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } } self.assertEqual(my_module.received_commands, 0) response = session.patch(self.ws_endpoint + '/host', json=data, headers=headers) print(response) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { '_status': 'OK', '_result': [ 'new_host_0 is alive :)', "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", ] }) # No errors - an extrenal command was raised for the host livestate #Â ----- # Update an host with an host livestate (heartbeat / host is alive): livestate # Because there is no backend configured, only an external command is raised # to Alignak for the host data = { "name": "new_host_0", "livestate": { # No timestamp in the livestate "state": "UP", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", }, "services": [{ "name": "test_svc_0", "livestate": { "state": "OK", "output": "Output...", "long_output": "Long output...", "perf_data": "'counter'=1", } }] } self.assertEqual(my_module.received_commands, 1) response = session.patch(self.ws_endpoint + '/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { '_status': 'OK', '_result': [ 'new_host_0 is alive :)', "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...", "PROCESS_SERVICE_CHECK_RESULT;new_host_0;test_svc_0;0;Output...|'counter'=1\nLong output..." ] }) # No errors - an extrenal command was raised for the host livestate self.modulemanager.stop_all()
class TestModuleWsEvent(AlignakTest): """This class contains the tests for the module""" @classmethod def setUpClass(cls): #Â Simulate an Alignak receiver daemon cls.ws_endpoint = 'http://127.0.0.1:7773/ws' import cherrypy class ReceiverItf(object): @cherrypy.expose def index(self): return "I am the Receiver daemon!" from alignak.http.daemon import HTTPDaemon as AlignakDaemon http_daemon1 = AlignakDaemon('0.0.0.0', 7773, ReceiverItf(), False, None, None, None, None, 10, '/tmp/alignak-cherrypy.log') def run_http_server(): http_daemon1.run() import threading cls.http_thread1 = threading.Thread(target=run_http_server, name='http_server_receiver') cls.http_thread1.daemon = True cls.http_thread1.start() print("Thread started") # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-event' # Delete used mongo DBs print ("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split( 'mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME']) ) assert exit_code == 0 fnull = open(os.devnull, 'w') cls.p = subprocess.Popen(['uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid', '--logto', '/tmp/uwsgi.log'], # stdout=fnull, stderr=fnull ) time.sleep(3) endpoint = 'http://127.0.0.1:5000' test_dir = os.path.dirname(os.path.realpath(__file__)) print("Current test directory: %s" % test_dir) print("Feeding Alignak backend... %s" % test_dir) exit_code = subprocess.call( shlex.split('alignak-backend-import --delete %s/cfg/cfg_default.cfg' % test_dir), # stdout=fnull, stderr=fnull ) assert exit_code == 0 print("Fed") # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = {'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id} response = requests.post(endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print(("Created a new user: %s" % resp)) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = {'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag']} data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' @classmethod def tearDownClass(cls): cls.p.kill() def setUp(self): super(TestModuleWsEvent, self).setUp() def tearDown(self): super(TestModuleWsEvent, self).tearDown() if self.modulemanager: time.sleep(1) self.modulemanager.stop_all() def test_module_zzz_event(self): """Test the module /event endpoint :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, 'authorization': '1', }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Prepare the backend content... self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Get default realm response = requests.get(self.endpoint + '/realm', auth=self.auth) resp = response.json() self.realm_all = resp['_items'][0]['_id'] # --- # Do not allow GET request on /event - not yet authorized response = requests.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Do not allow GET request on /event response = session.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must only POST on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /event headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must POST parameters on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # Notify an host event - missing host or service headers = {'Content-Type': 'application/json'} data = { "fake": "" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing host and/or service parameter.']}) # Notify an host event - missing comment headers = {'Content-Type': 'application/json'} data = { "host": "test_host", } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing comment. If you do not have any comment, ' 'do not comment ;)']}) # Notify an host event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_HOST_COMMENT;test_host;1;' 'Alignak WS;My comment']}) # Notify an host event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_HOST_COMMENT;test_host;1;' 'Me;My comment']}) # Notify a service event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "service": "test_service", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_SVC_COMMENT;test_host;test_service;1;' 'Alignak WS;My comment']}) # Notify a service event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "service": "test_service", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_SVC_COMMENT;test_host;test_service;' '1;Me;My comment']}) # Get history to confirm that backend is ready # --- response = session.get(self.endpoint + '/history', auth=self.auth, params={"sort": "-_id", "max_results": 25, "page": 1}) resp = response.json() print(("Response: %s" % resp)) for item in resp['_items']: assert item['type'] in ['webui.comment'] # Got 4 notified events, so we get 4 comments in the backend self.assertEqual(len(resp['_items']), 4) # --- # Logout response = session.get(self.ws_endpoint + '/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all() def test_module_zzz_event(self): """Test the module /event endpoint :return: """ # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, 'authorization': '1', }) # Create a receiver daemon args = {'env_file': '', 'daemon_name': 'receiver-master'} self._receiver_daemon = Receiver(**args) # Create the modules manager for the daemon self.modulemanager = ModulesManager(self._receiver_daemon) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Prepare the backend content... self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Get default realm response = requests.get(self.endpoint + '/realm', auth=self.auth) resp = response.json() self.realm_all = resp['_items'][0]['_id'] # --- # Do not allow GET request on /event - not yet authorized response = requests.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post(self.ws_endpoint + '/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # Do not allow GET request on /event response = session.get(self.ws_endpoint + '/event') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must only POST on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /event headers = {'Content-Type': 'application/json'} data = {} response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ERR') self.assertEqual(result['_issues'], ['You must POST parameters on this endpoint.']) self.assertEqual(my_module.received_commands, 0) # Notify an host event - missing host or service headers = {'Content-Type': 'application/json'} data = { "fake": "" } self.assertEqual(my_module.received_commands, 0) response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing host and/or service parameter.']}) # Notify an host event - missing comment headers = {'Content-Type': 'application/json'} data = { "host": "test_host", } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'ERR', '_issues': ['Missing comment. If you do not have any comment, ' 'do not comment ;)']}) # Notify an host event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_HOST_COMMENT;test_host;1;' 'Alignak WS;My comment']}) # Notify an host event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_HOST_COMMENT;test_host;1;' 'Me;My comment']}) # Notify a service event - default author headers = {'Content-Type': 'application/json'} data = { "host": "test_host", "service": "test_service", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['ADD_SVC_COMMENT;test_host;test_service;1;' 'Alignak WS;My comment']}) # Notify a service event - default author and timestamp headers = {'Content-Type': 'application/json'} data = { "timestamp": 1234567890, "host": "test_host", "service": "test_service", "author": "Me", "comment": "My comment" } response = session.post(self.ws_endpoint + '/event', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result, {'_status': 'OK', '_result': ['[1234567890] ADD_SVC_COMMENT;test_host;test_service;' '1;Me;My comment']}) # Get history to confirm that backend is ready # --- response = session.get(self.endpoint + '/history', auth=self.auth, params={"sort": "-_id", "max_results": 25, "page": 1}) resp = response.json() print(("Response: %s" % resp)) for item in resp['_items']: assert item['type'] in ['webui.comment'] # Got 4 notified events, so we get 4 comments in the backend self.assertEqual(len(resp['_items']), 4) # --- # Logout response = session.get(self.ws_endpoint + '/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
def test_module_zzz_host_get(self): """Test the module /host API - host creation and get information :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Alignak backend 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Do not set a timestamp in the built external commands 'set_timestamp': '0', 'give_result': '1', 'give_feedback': '1', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Allow host/service creation 'allow_host_creation': '1', 'allow_service_creation': '1', # Errors for unknown host/service 'ignore_unknown_host': '0', 'ignore_unknown_service': '0', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match( "Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Do not allow GET request on /host - not yet authorized! response = requests.get('http://127.0.0.1:8888/host') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() #Â ----- # Get a non-existing host - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/host', auth=self.auth, params={'name': 'new_host_2'}) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested host 'new_host_2' does not exist"] }) # Get a non-existing host - 2nd: use host name in the URI response = session.get('http://127.0.0.1:8888/host/new_host_2', auth=self.auth) result = response.json() self.assertEqual( result, { u'_status': u'ERR', u'_result': [], u'_issues': ["Requested host 'new_host_2' does not exist"] }) #Â ----- # Request to create an host - no provided data (default) headers = {'Content-Type': 'application/json'} data = { "name": "new_host_0", } self.assertEqual(my_module.received_commands, 0) response = session.patch('http://127.0.0.1:8888/host', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual( result, { u'_status': u'OK', u'_result': [ u'new_host_0 is alive :)', u"Requested host 'new_host_0' does not exist.", u"Requested host 'new_host_0' created." ], u'_feedback': { u'name': u'new_host_0' } }) # Host created with default check_command and in default user realm #Â ----- # Get new host to confirm creation - 1st: use parameters in the request response = session.get('http://127.0.0.1:8888/host', auth=self.auth, params={'name': 'new_host_0'}) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(result['_result'][0]['name'], 'new_host_0') # Get new host to confirm creation - 2nd: use host name in the URI response = session.get('http://127.0.0.1:8888/host/new_host_0', auth=self.auth) result = response.json() from pprint import pprint pprint(result['_result']) # [{u'2d_coords': u'', # u'3d_coords': u'', # u'_created': u'Thu, 01 Jun 2017 10:58:30 GMT', # u'_etag': u'691c3f4a7cc8996c1d047932421759c020d00857', # u'_id': u'592ff35606fd4b7eec395625', # u'_is_template': False, # u'_links': {u'self': {u'href': u'host/592ff35606fd4b7eec395625', # u'title': u'Host'}}, # u'_overall_state_id': 3, # u'_realm': {u'_all_children': [], # u'_children': [], # u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'_etag': u'26b3830c017b4fca8553365246f21267aece46a7', # u'_id': u'592ff35006fd4b7eec3955eb', # u'_level': 0, # u'_parent': None, # u'_tree_parents': [], # u'_updated': u'Thu, 01 Jun 2017 10:58:27 GMT', # u'alias': u'', # u'default': True, # u'definition_order': 100, # u'global_critical_threshold': 5, # u'global_warning_threshold': 3, # u'hosts_critical_threshold': 5, # u'hosts_warning_threshold': 3, # u'imported_from': u'unknown', # u'name': u'All', # u'notes': u'', # u'services_critical_threshold': 5, # u'services_warning_threshold': 3}, # u'_sub_realm': True, # u'_template_fields': {}, # u'_templates': [], # u'_templates_with_services': True, # u'_updated': u'Thu, 01 Jun 2017 10:58:30 GMT', # u'action_url': u'', # u'active_checks_enabled': True, # u'address': u'', # u'address6': u'', # u'alias': u'', # u'business_impact': 2, # u'business_impact_modulations': [], # u'business_rule_downtime_as_ack': False, # u'business_rule_host_notification_options': [u'd', u'u', u'r', u'f', u's'], # u'business_rule_output_template': u'', # u'business_rule_service_notification_options': [u'w', # u'u', # u'c', # u'r', # u'f', # u's'], # u'business_rule_smart_notifications': False, # u'check_command': {u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'_etag': u'356d02479ca7dbebe85e22b9b43e95dc9d5d037c', # u'_id': u'592ff35006fd4b7eec3955f1', # u'_realm': u'592ff35006fd4b7eec3955eb', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 10:58:24 GMT', # u'alias': u'Host/service is always UP/OK', # u'command_line': u'_internal_host_up', # u'definition_order': 100, # u'enable_environment_macros': False, # u'imported_from': u'unknown', # u'module_type': u'fork', # u'name': u'_internal_host_up', # u'notes': u'', # u'poller_tag': u'', # u'reactionner_tag': u'', # u'timeout': -1}, # u'check_command_args': u'', # u'check_freshness': False, # u'check_interval': 5, # u'checkmodulations': [], # u'custom_views': [], # u'customs': {}, # u'definition_order': 100, # u'display_name': u'', # u'escalations': [], # u'event_handler': None, # u'event_handler_args': u'', # u'event_handler_enabled': False, # u'failure_prediction_enabled': False, # u'first_notification_delay': 0, # u'flap_detection_enabled': True, # u'flap_detection_options': [u'o', u'd', u'x'], # u'freshness_state': u'x', # u'freshness_threshold': 0, # u'high_flap_threshold': 50, # u'icon_image': u'', # u'icon_image_alt': u'', # u'icon_set': u'', # u'imported_from': u'unknown', # u'initial_state': u'x', # u'labels': [], # u'location': {u'coordinates': [48.858293, 2.294601], u'type': u'Point'}, # u'low_flap_threshold': 25, # u'ls_acknowledged': False, # u'ls_acknowledgement_type': 1, # u'ls_attempt': 0, # u'ls_current_attempt': 0, # u'ls_downtimed': False, # u'ls_execution_time': 0.0, # u'ls_grafana': False, # u'ls_grafana_panelid': 0, # u'ls_impact': False, # u'ls_last_check': 0, # u'ls_last_hard_state_changed': 0, # u'ls_last_notification': 0, # u'ls_last_state': u'OK', # u'ls_last_state_changed': 0, # u'ls_last_state_type': u'HARD', # u'ls_last_time_down': 0, # u'ls_last_time_unknown': 0, # u'ls_last_time_unreachable': 0, # u'ls_last_time_up': 0, # u'ls_latency': 0.0, # u'ls_long_output': u'', # u'ls_max_attempts': 0, # u'ls_next_check': 0, # u'ls_output': u'', # u'ls_passive_check': False, # u'ls_perf_data': u'', # u'ls_state': u'UNREACHABLE', # u'ls_state_id': 3, # u'ls_state_type': u'HARD', # u'macromodulations': [], # u'max_check_attempts': 1, # u'name': u'new_host_0', # u'notes': u'', # u'notes_url': u'', # u'notification_interval': 60, # u'notification_options': [u'd', u'x', u'r', u'f', u's'], # u'notifications_enabled': True, # u'obsess_over_host': False, # u'parents': [], # u'passive_checks_enabled': True, # u'poller_tag': u'', # u'process_perf_data': True, # u'reactionner_tag': u'', # u'resultmodulations': [], # u'retry_interval': 0, # u'service_excludes': [], # u'service_includes': [], # u'service_overrides': [], # u'snapshot_criteria': [u'd', u'x'], # u'snapshot_enabled': False, # u'snapshot_interval': 5, # u'stalking_options': [], # u'statusmap_image': u'', # u'tags': [], # u'time_to_orphanage': 300, # u'trending_policies': [], # u'trigger_broker_raise_enabled': False, # u'trigger_name': u'', # u'usergroups': [], # u'users': [], # u'vrml_image': u''}] # self.assertEqual(result['_status'], 'OK') self.assertIsNot(result['_result'], {}) self.assertEqual(result['_result'][0]['name'], 'new_host_0') #Â ----- # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') self.modulemanager.stop_all()
def _get_history(self, username, password): # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Alignak backend URL 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Activate CherryPy file logs 'log_access': '/tmp/alignak-module-ws-access.log', 'log_error': '/tmp/alignak-module-ws-error.log', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) time.sleep(1) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Prepare the backend content... self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Get default realm response = requests.get(self.endpoint + '/realm', auth=self.auth) resp = response.json() self.realm_all = resp['_items'][0]['_id'] # --- # ------------------------------------------- # Add a check result for an host data = { "last_check": 1496332753, "host": self.rh[0]['_id'], "service": None, 'acknowledged': False, 'state_id': 0, 'state': 'UP', 'state_type': 'HARD', 'last_state_id': 0, 'last_state': 'UP', 'last_state_type': 'HARD', 'state_changed': False, 'latency': 0, 'execution_time': 0.12, 'output': 'Check output', 'long_output': 'Check long_output', 'perf_data': 'perf_data', "_realm": self.realm_all } response = requests.post( self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth ) resp = response.json() self.assertEqual(resp['_status'], 'OK') # ------------------------------------------- # Add a check result for a service data = { "last_check": 1496332754, "host": self.rh[0]['_id'], "service": self.rs[0]['_id'], 'acknowledged': False, 'state_id': 0, 'state': 'UP', 'state_type': 'HARD', 'last_state_id': 0, 'last_state': 'UP', 'last_state_type': 'HARD', 'state_changed': False, 'latency': 0, 'execution_time': 0.12, 'output': 'Check output', 'long_output': 'Check long_output', 'perf_data': 'perf_data', "_realm": self.realm_all } response = requests.post( self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth ) resp = response.json() self.assertEqual(resp['_status'], 'OK') # Add an history event data = { "host_name": "chazay", "service_name": "Processus", "user_name": "Alignak", "type": "check.result", "message": "OK[HARD] (False,False): All is ok", "_realm": self.realm_all, "_sub_realm": True } time.sleep(1) requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # Add an history event time.sleep(1) data = { "host_name": "denice", "service_name": "Zombies", "user_name": "Alignak", "type": "check.result", "message": "OK[HARD] (False,False): All is ok", "_realm": self.realm_all, "_sub_realm": True } requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # Add an history event time.sleep(1) data = { "host_name": "denice", "user_name": "Me", "type": "monitoring.alert", "message": "HOST ALERT ....", "_realm": self.realm_all, "_sub_realm": True } requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # --- # --- # Get history to confirm that backend is ready # --- response = requests.get(self.endpoint + '/history', auth=self.auth, params={"sort": "-_id", "max_results": 25, "page": 1, 'embedded': json.dumps({"logcheckresult": 1})}) resp = response.json() pprint(resp['_items']) self.assertEqual(len(resp['_items']), 5) # Backend real history # The commented fields are the one existing in the backend but filtered by the WS backend_real_history = [ { u'_created': u'Thu, 01 Jun 2017 15:59:16 GMT', # u'_etag': u'9f07c7285b37bb3d336a96ede3d3fd2a774c4c4c', u'_id': u'593039d406fd4b3bf0e27d9f', # u'_links': {u'self': {u'href': u'history/593039d406fd4b3bf0e27d9f', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:16 GMT', u'host_name': u'denice', u'message': u'HOST ALERT ....', u'type': u'monitoring.alert', u'user_name': u'Me' }, { u'_created': u'Thu, 01 Jun 2017 15:59:15 GMT', # u'_etag': u'24cd486a1a28859a0177fbe15d1ead61f78f7b2c', u'_id': u'593039d306fd4b3bf0e27d9e', # u'_links': {u'self': {u'href': u'history/593039d306fd4b3bf0e27d9e', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:15 GMT', u'host_name': u'denice', u'message': u'OK[HARD] (False,False): All is ok', u'service_name': u'Zombies', u'type': u'check.result', u'user_name': u'Alignak' }, { u'_created': u'Thu, 01 Jun 2017 15:59:14 GMT', # u'_etag': u'4c4ee43a4fac0b91dcfddb011619007dedb1cd95', u'_id': u'593039d206fd4b3bf0e27d9d', # u'_links': {u'self': {u'href': u'history/593039d206fd4b3bf0e27d9d', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:14 GMT', u'host_name': u'chazay', u'message': u'OK[HARD] (False,False): All is ok', u'service_name': u'Processus', u'type': u'check.result', u'user_name': u'Alignak' }, {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'76dd35f575244848dd41f67ad3109cf6f1f9a33c', u'_id': u'593039d106fd4b3bf0e27d9c', # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9c', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'host': u'593039cc06fd4b3bf0e27d90', u'host_name': u'srv001', u'logcheckresult': { u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'10a3935b1158fe4c8f62962a14b1050fef32df4b', # u'_id': u'593039d106fd4b3bf0e27d9b', # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', u'acknowledged': False, u'acknowledgement_type': 1, u'downtimed': False, u'execution_time': 0.12, # u'host': u'593039cc06fd4b3bf0e27d90', # u'host_name': u'srv001', u'last_check': 1496332753, u'last_state': u'UP', u'last_state_changed': 0, u'last_state_id': 0, u'last_state_type': u'HARD', u'latency': 0.0, u'long_output': u'Check long_output', u'output': u'Check output', u'passive_check': False, u'perf_data': u'perf_data', # u'service': u'593039cf06fd4b3bf0e27d98', # u'service_name': u'ping', u'state': u'UP', u'state_changed': False, u'state_id': 0, u'state_type': u'HARD' }, u'message': u'UP[HARD] (False/False): Check output', # u'service': u'593039cf06fd4b3bf0e27d98', u'service_name': u'ping', u'type': u'check.result', # u'user': None, u'user_name': u'Alignak' }, {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'c3cd29587ad328325dc48af677b3a36157361a84', u'_id': u'593039d106fd4b3bf0e27d9a', # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9a', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'host': u'593039cc06fd4b3bf0e27d90', u'host_name': u'srv001', u'logcheckresult': { u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'0ea4c16f1e651a02772aa2bfa83070b47e7f6531', # u'_id': u'593039d106fd4b3bf0e27d99', # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', u'acknowledged': False, u'acknowledgement_type': 1, u'downtimed': False, u'execution_time': 0.12, # u'host': u'593039cc06fd4b3bf0e27d90', # u'host_name': u'srv001', u'last_check': 1496332754, u'last_state': u'UP', u'last_state_changed': 0, u'last_state_id': 0, u'last_state_type': u'HARD', u'latency': 0.0, u'long_output': u'Check long_output', u'output': u'Check output', u'passive_check': False, u'perf_data': u'perf_data', # u'service': None, # u'service_name': u'', u'state': u'UP', u'state_changed': False, u'state_id': 0, u'state_type': u'HARD' }, u'message': u'UP[HARD] (False/False): Check output', # u'service': None, u'service_name': u'', u'type': u'check.result', # u'user': None, u'user_name': u'Alignak' } ] # --- # --- # # Directly call the module function # search = { # 'page': 1, # 'max_results': 25 # } # result = my_module.getBackendHistory(search) # print(result) # print("Page: %d, got: %d items" % (search["page"], len(result['items']))) # for item in result['items']: # print(item) # assert len(result['items']) == 5 # --- # Do not allow GET request on /alignak_logs - not yet authorized! response = requests.get('http://127.0.0.1:8888/alignak_logs') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': username, 'password': password} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # --- # Get the alignak default history response = session.get('http://127.0.0.1:8888/alignak_logs') self.assertEqual(response.status_code, 200) result = response.json() # Remove fields that will obviously be different! for item in result['items']: del(item['_id']) del(item['_created']) # if 'logcheckresult' in item: # del (item['logcheckresult']['_created']) for item in backend_real_history: del(item['_id']) del(item['_created']) if 'logcheckresult' in item: del (item['logcheckresult']['_created']) self.assertEqual(len(result['items']), 5) # Too complex comparison!!! # self.assertEqual(backend_real_history, result['items']) # assert cmp(backend_real_history, result['items']) == 0 # --- # --- # Get the alignak default history, filter to get only check.result response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:check.result') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 4) # --- # --- # Get the alignak default history, filter to get only for a user response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Alignak') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 4) response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Me') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # --- # --- # Get the alignak default history, filter to get only for an host response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:chazay') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 1) # Implicit host_name response = session.get('http://127.0.0.1:8888/alignak_logs?search=chazay') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 1) # Unknown search field response = session.get('http://127.0.0.1:8888/alignak_logs?search=name:chazay') self.assertEqual(response.status_code, 200) result = response.json() # All history items because name is not aknown search field! So we get all items... self.assertEqual(len(result['items']), 5) # Some other hosts... response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 2) response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:srv001') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 2) # Several hosts... response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice host_name:srv001') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 4) # 2 for each host # Not an host... # TODO: looks that ths criteria is not correctly implemented :( # response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!denice') # self.assertEqual(response.status_code, 200) # result = response.json() # self.assertEqual(len(result['items']), 3) # --- # --- # Get the alignak default history, NOT for an host # todo: temporarily skipped # response = requests.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!Chazay') # self.assertEqual(response.status_code, 200) # result = response.json() # for item in result['items']: # print(item) # self.assertEqual(len(result['items']), 2) # --- # --- # Get the alignak default history, only for a service response = session.get('http://127.0.0.1:8888/alignak_logs?search=service_name:Processus') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # --- # --- # Get the alignak default history, for an host and a service # todo multi search query to be improved! # response = session.get('http://127.0.0.1:8888/alignak_logs?search="host_name:chazay service_name=Processus"') # self.assertEqual(response.status_code, 200) # result = response.json() # for item in result['items']: # print(item) # self.assertEqual(len(result['items']), 3) # --- # --- # Get the alignak default history, unknown event type response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:XXX') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) # --- # --- # Get the alignak default history, page count response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=2&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=3&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=4&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # Over the limits ! response = session.get('http://127.0.0.1:8888/alignak_logs?start=5&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) response = session.get('http://127.0.0.1:8888/alignak_logs?start=50&count=50') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) # --- # --- # Get the alignak history, page count greater than the number of items response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=25') self.assertEqual(response.status_code, 200) result = response.json() pprint(result) self.assertEqual(len(result['items']), 5) # Got 5 items self.assertEqual(result['_meta']['max_results'], 25) self.assertEqual(result['_meta']['page'], 1) self.assertEqual(result['_meta']['total'], 5) response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=50') self.assertEqual(response.status_code, 200) result = response.json() pprint(result) self.assertEqual(len(result['items']), 5) # Got 5 items self.assertEqual(result['_meta']['max_results'], 50) self.assertEqual(result['_meta']['page'], 1) self.assertEqual(result['_meta']['total'], 5) # --- # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out')
def test_module_zzz_run(self): """ Test the module API :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # Get the module API list and request on each endpoint response = requests.get('http://127.0.0.1:8888') api_list = response.json() for endpoint in api_list: print("Trying %s" % (endpoint)) response = requests.get('http://127.0.0.1:8888/' + endpoint) print("Response %d: %s" % (response.status_code, response.content)) self.assertEqual(response.status_code, 200) if response.status_code == 200: print("Got %s: %s" % (endpoint, response.json())) else: print("Error %s: %s" % (response.status_code, response.content)) time.sleep(1) # Do not allow GET request on /command response = requests.get('http://127.0.0.1:8888/command') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ko') self.assertEqual(result['_result'], 'You must only POST on this endpoint.') self.assertEqual(my_module.received_commands, 0) # You must have parameters when POSTing on /command headers = {'Content-Type': 'application/json'} data = {} response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ko') self.assertEqual(result['_result'], 'You must POST parameters on this endpoint.') self.assertEqual(my_module.received_commands, 0) # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "Command", "element": "test_host", "parameters": "abc;1" } self.assertEqual(my_module.received_commands, 0) response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND;test_host;abc;1') # Not during unit tests ... because module queues are not functional! # time.sleep(1) # self.assertEqual(my_module.received_commands, 1) # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host;test_service", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "element": "test_host/test_service", # Accept / as an host/service separator "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2') # Request to execute an external command (Alignak modern syntax) headers = {'Content-Type': 'application/json'} data = { "command": "command_command", "host": "test_host", "service": "test_service", "user": "******", "parameters": "1;abc;2" } response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers) self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'ok') # Result is uppercase command, parameters are ordered self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2') self.modulemanager.stop_all()
class TestModuleWsHistory(AlignakTest): @classmethod def setUpClass(cls): # Set test mode for alignak backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test' # Delete used mongo DBs print ("Deleting Alignak backend DB...") exit_code = subprocess.call( shlex.split( 'mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME']) ) assert exit_code == 0 cls.p = subprocess.Popen(['uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid']) time.sleep(3) cls.endpoint = 'http://127.0.0.1:5000' # Backend authentication headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # Get admin user token (force regenerate) response = requests.post(cls.endpoint + '/login', json=params, headers=headers) resp = response.json() cls.token = resp['token'] cls.auth = requests.auth.HTTPBasicAuth(cls.token, '') # Get admin user response = requests.get(cls.endpoint + '/user', auth=cls.auth) resp = response.json() cls.user_admin = resp['_items'][0] # Get realms response = requests.get(cls.endpoint + '/realm', auth=cls.auth) resp = response.json() cls.realmAll_id = resp['_items'][0]['_id'] # Add a user data = {'name': 'test', 'password': '******', 'back_role_super_admin': False, 'host_notification_period': cls.user_admin['host_notification_period'], 'service_notification_period': cls.user_admin['service_notification_period'], '_realm': cls.realmAll_id} response = requests.post(cls.endpoint + '/user', json=data, headers=headers, auth=cls.auth) resp = response.json() print("Created a new user: %s" % resp) # Get new user restrict role params = {'where': json.dumps({'user': resp['_id']})} response = requests.get(cls.endpoint + '/userrestrictrole', params=params, auth=cls.auth) resp = response.json() # Update user's rights - set full CRUD rights headers = {'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag']} data = {'crud': ['create', 'read', 'update', 'delete', 'custom']} resp = requests.patch(cls.endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'], json=data, headers=headers, auth=cls.auth) resp = resp.json() assert resp['_status'] == 'OK' # Add command data = { "name": "ping", "command_line": "check_ping -H $HOSTADDRESS$", "_realm": cls.realmAll_id } requests.post(cls.endpoint + '/command', json=data, headers=headers, auth=cls.auth) response = requests.get(cls.endpoint + '/command', auth=cls.auth) resp = response.json() cls.rc = resp['_items'] # Add an host data = { "name": "srv001", "address": "192.168.0.2", "business_impact": 5, "check_command": cls.rc[0]['_id'], "_realm": cls.realmAll_id } response = requests.post(cls.endpoint + '/host', json=data, headers=headers, auth=cls.auth) response = requests.get(cls.endpoint + '/host?where={"name":"srv001"}', auth=cls.auth) resp = response.json() cls.rh = resp['_items'] # Add a service data = { "name": "ping", "host": cls.rh[0]['_id'], "check_command": cls.rc[0]['_id'], "business_impact": 4, "_realm": cls.realmAll_id } response = requests.post(cls.endpoint + '/service', json=data, headers=headers, auth=cls.auth) response = requests.get(cls.endpoint + '/service', auth=cls.auth) resp = response.json() cls.rs = resp['_items'] cls.modulemanager = None @classmethod def tearDownClass(cls): cls.p.kill() def setUp(self): """Create resources in backend :return: None """ def tearDown(self): for resource in ['logcheckresult', 'history']: requests.delete('http://127.0.0.1:5000/' + resource, auth=self.auth) if self.modulemanager: time.sleep(1) self.modulemanager.stop_all() def file_dump(self, data, filename): # pylint: disable=no-self-use """Dump the data to a JSON formatted file :param data: data to be dumped :param filename: name of the file to use. Only the file name, not the full path! :return: dumped file absolute file name """ dump = json.dumps(data, indent=4, separators=(',', ': '), sort_keys=True) path = os.path.join(self.folder or os.getcwd(), filename) try: dfile = open(path, "wt") dfile.write(dump) dfile.close() return path except (OSError, IndexError) as exp: # pragma: no cover, should never happen print("Error when writing the list dump file %s : %s" % (path, str(exp))) assert False return None def test_module_zzz_get_history_admin(self): """Test the module log collection functions :return: """ self.print_header() self._get_history("admin", "admin") def test_module_zzz_get_history_test(self): """Test the module log collection functions :return: """ self.print_header() self._get_history("test", "test") def _get_history(self, username, password): # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Alignak backend URL 'alignak_backend': 'http://127.0.0.1:5000', 'username': '******', 'password': '******', # Activate CherryPy file logs 'log_access': '/tmp/alignak-module-ws-access.log', 'log_error': '/tmp/alignak-module-ws-error.log', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) time.sleep(1) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Prepare the backend content... self.endpoint = 'http://127.0.0.1:5000' headers = {'Content-Type': 'application/json'} params = {'username': '******', 'password': '******'} # get token response = requests.post(self.endpoint + '/login', json=params, headers=headers) resp = response.json() self.token = resp['token'] self.auth = requests.auth.HTTPBasicAuth(self.token, '') # Get default realm response = requests.get(self.endpoint + '/realm', auth=self.auth) resp = response.json() self.realm_all = resp['_items'][0]['_id'] # --- # ------------------------------------------- # Add a check result for an host data = { "last_check": 1496332753, "host": self.rh[0]['_id'], "service": None, 'acknowledged': False, 'state_id': 0, 'state': 'UP', 'state_type': 'HARD', 'last_state_id': 0, 'last_state': 'UP', 'last_state_type': 'HARD', 'state_changed': False, 'latency': 0, 'execution_time': 0.12, 'output': 'Check output', 'long_output': 'Check long_output', 'perf_data': 'perf_data', "_realm": self.realm_all } response = requests.post( self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth ) resp = response.json() self.assertEqual(resp['_status'], 'OK') # ------------------------------------------- # Add a check result for a service data = { "last_check": 1496332754, "host": self.rh[0]['_id'], "service": self.rs[0]['_id'], 'acknowledged': False, 'state_id': 0, 'state': 'UP', 'state_type': 'HARD', 'last_state_id': 0, 'last_state': 'UP', 'last_state_type': 'HARD', 'state_changed': False, 'latency': 0, 'execution_time': 0.12, 'output': 'Check output', 'long_output': 'Check long_output', 'perf_data': 'perf_data', "_realm": self.realm_all } response = requests.post( self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth ) resp = response.json() self.assertEqual(resp['_status'], 'OK') # Add an history event data = { "host_name": "chazay", "service_name": "Processus", "user_name": "Alignak", "type": "check.result", "message": "OK[HARD] (False,False): All is ok", "_realm": self.realm_all, "_sub_realm": True } time.sleep(1) requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # Add an history event time.sleep(1) data = { "host_name": "denice", "service_name": "Zombies", "user_name": "Alignak", "type": "check.result", "message": "OK[HARD] (False,False): All is ok", "_realm": self.realm_all, "_sub_realm": True } requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # Add an history event time.sleep(1) data = { "host_name": "denice", "user_name": "Me", "type": "monitoring.alert", "message": "HOST ALERT ....", "_realm": self.realm_all, "_sub_realm": True } requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth) # --- # --- # Get history to confirm that backend is ready # --- response = requests.get(self.endpoint + '/history', auth=self.auth, params={"sort": "-_id", "max_results": 25, "page": 1, 'embedded': json.dumps({"logcheckresult": 1})}) resp = response.json() pprint(resp['_items']) self.assertEqual(len(resp['_items']), 5) # Backend real history # The commented fields are the one existing in the backend but filtered by the WS backend_real_history = [ { u'_created': u'Thu, 01 Jun 2017 15:59:16 GMT', # u'_etag': u'9f07c7285b37bb3d336a96ede3d3fd2a774c4c4c', u'_id': u'593039d406fd4b3bf0e27d9f', # u'_links': {u'self': {u'href': u'history/593039d406fd4b3bf0e27d9f', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:16 GMT', u'host_name': u'denice', u'message': u'HOST ALERT ....', u'type': u'monitoring.alert', u'user_name': u'Me' }, { u'_created': u'Thu, 01 Jun 2017 15:59:15 GMT', # u'_etag': u'24cd486a1a28859a0177fbe15d1ead61f78f7b2c', u'_id': u'593039d306fd4b3bf0e27d9e', # u'_links': {u'self': {u'href': u'history/593039d306fd4b3bf0e27d9e', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:15 GMT', u'host_name': u'denice', u'message': u'OK[HARD] (False,False): All is ok', u'service_name': u'Zombies', u'type': u'check.result', u'user_name': u'Alignak' }, { u'_created': u'Thu, 01 Jun 2017 15:59:14 GMT', # u'_etag': u'4c4ee43a4fac0b91dcfddb011619007dedb1cd95', u'_id': u'593039d206fd4b3bf0e27d9d', # u'_links': {u'self': {u'href': u'history/593039d206fd4b3bf0e27d9d', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:14 GMT', u'host_name': u'chazay', u'message': u'OK[HARD] (False,False): All is ok', u'service_name': u'Processus', u'type': u'check.result', u'user_name': u'Alignak' }, {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'76dd35f575244848dd41f67ad3109cf6f1f9a33c', u'_id': u'593039d106fd4b3bf0e27d9c', # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9c', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'host': u'593039cc06fd4b3bf0e27d90', u'host_name': u'srv001', u'logcheckresult': { u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'10a3935b1158fe4c8f62962a14b1050fef32df4b', # u'_id': u'593039d106fd4b3bf0e27d9b', # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', u'acknowledged': False, u'acknowledgement_type': 1, u'downtimed': False, u'execution_time': 0.12, # u'host': u'593039cc06fd4b3bf0e27d90', # u'host_name': u'srv001', u'last_check': 1496332753, u'last_state': u'UP', u'last_state_changed': 0, u'last_state_id': 0, u'last_state_type': u'HARD', u'latency': 0.0, u'long_output': u'Check long_output', u'output': u'Check output', u'passive_check': False, u'perf_data': u'perf_data', # u'service': u'593039cf06fd4b3bf0e27d98', # u'service_name': u'ping', u'state': u'UP', u'state_changed': False, u'state_id': 0, u'state_type': u'HARD' }, u'message': u'UP[HARD] (False/False): Check output', # u'service': u'593039cf06fd4b3bf0e27d98', u'service_name': u'ping', u'type': u'check.result', # u'user': None, u'user_name': u'Alignak' }, {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'c3cd29587ad328325dc48af677b3a36157361a84', u'_id': u'593039d106fd4b3bf0e27d9a', # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9a', # u'title': u'History'}}, # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'host': u'593039cc06fd4b3bf0e27d90', u'host_name': u'srv001', u'logcheckresult': { u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT', # u'_etag': u'0ea4c16f1e651a02772aa2bfa83070b47e7f6531', # u'_id': u'593039d106fd4b3bf0e27d99', # u'_realm': u'593039cc06fd4b3bf0e27d88', # u'_sub_realm': True, # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT', u'acknowledged': False, u'acknowledgement_type': 1, u'downtimed': False, u'execution_time': 0.12, # u'host': u'593039cc06fd4b3bf0e27d90', # u'host_name': u'srv001', u'last_check': 1496332754, u'last_state': u'UP', u'last_state_changed': 0, u'last_state_id': 0, u'last_state_type': u'HARD', u'latency': 0.0, u'long_output': u'Check long_output', u'output': u'Check output', u'passive_check': False, u'perf_data': u'perf_data', # u'service': None, # u'service_name': u'', u'state': u'UP', u'state_changed': False, u'state_id': 0, u'state_type': u'HARD' }, u'message': u'UP[HARD] (False/False): Check output', # u'service': None, u'service_name': u'', u'type': u'check.result', # u'user': None, u'user_name': u'Alignak' } ] # --- # --- # # Directly call the module function # search = { # 'page': 1, # 'max_results': 25 # } # result = my_module.getBackendHistory(search) # print(result) # print("Page: %d, got: %d items" % (search["page"], len(result['items']))) # for item in result['items']: # print(item) # assert len(result['items']) == 5 # --- # Do not allow GET request on /alignak_logs - not yet authorized! response = requests.get('http://127.0.0.1:8888/alignak_logs') self.assertEqual(response.status_code, 401) session = requests.Session() # Login with username/password (real backend login) headers = {'Content-Type': 'application/json'} params = {'username': username, 'password': password} response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers) assert response.status_code == 200 resp = response.json() # --- # Get the alignak default history response = session.get('http://127.0.0.1:8888/alignak_logs') self.assertEqual(response.status_code, 200) result = response.json() # Remove fields that will obviously be different! for item in result['items']: del(item['_id']) del(item['_created']) # if 'logcheckresult' in item: # del (item['logcheckresult']['_created']) for item in backend_real_history: del(item['_id']) del(item['_created']) if 'logcheckresult' in item: del (item['logcheckresult']['_created']) self.assertEqual(len(result['items']), 5) # Too complex comparison!!! # self.assertEqual(backend_real_history, result['items']) # assert cmp(backend_real_history, result['items']) == 0 # --- # --- # Get the alignak default history, filter to get only check.result response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:check.result') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 4) # --- # --- # Get the alignak default history, filter to get only for a user response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Alignak') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 4) response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Me') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # --- # --- # Get the alignak default history, filter to get only for an host response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:chazay') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 1) # Implicit host_name response = session.get('http://127.0.0.1:8888/alignak_logs?search=chazay') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 1) # Unknown search field response = session.get('http://127.0.0.1:8888/alignak_logs?search=name:chazay') self.assertEqual(response.status_code, 200) result = response.json() # All history items because name is not aknown search field! So we get all items... self.assertEqual(len(result['items']), 5) # Some other hosts... response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 2) response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:srv001') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 2) # Several hosts... response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice host_name:srv001') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(len(result['items']), 4) # 2 for each host # Not an host... # TODO: looks that ths criteria is not correctly implemented :( # response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!denice') # self.assertEqual(response.status_code, 200) # result = response.json() # self.assertEqual(len(result['items']), 3) # --- # --- # Get the alignak default history, NOT for an host # todo: temporarily skipped # response = requests.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!Chazay') # self.assertEqual(response.status_code, 200) # result = response.json() # for item in result['items']: # print(item) # self.assertEqual(len(result['items']), 2) # --- # --- # Get the alignak default history, only for a service response = session.get('http://127.0.0.1:8888/alignak_logs?search=service_name:Processus') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # --- # --- # Get the alignak default history, for an host and a service # todo multi search query to be improved! # response = session.get('http://127.0.0.1:8888/alignak_logs?search="host_name:chazay service_name=Processus"') # self.assertEqual(response.status_code, 200) # result = response.json() # for item in result['items']: # print(item) # self.assertEqual(len(result['items']), 3) # --- # --- # Get the alignak default history, unknown event type response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:XXX') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) # --- # --- # Get the alignak default history, page count response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=2&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=3&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) response = session.get('http://127.0.0.1:8888/alignak_logs?start=4&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 1) # Over the limits ! response = session.get('http://127.0.0.1:8888/alignak_logs?start=5&count=1') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) response = session.get('http://127.0.0.1:8888/alignak_logs?start=50&count=50') self.assertEqual(response.status_code, 200) result = response.json() for item in result['items']: print(item) self.assertEqual(len(result['items']), 0) # --- # --- # Get the alignak history, page count greater than the number of items response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=25') self.assertEqual(response.status_code, 200) result = response.json() pprint(result) self.assertEqual(len(result['items']), 5) # Got 5 items self.assertEqual(result['_meta']['max_results'], 25) self.assertEqual(result['_meta']['page'], 1) self.assertEqual(result['_meta']['total'], 5) response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=50') self.assertEqual(response.status_code, 200) result = response.json() pprint(result) self.assertEqual(len(result['items']), 5) # Got 5 items self.assertEqual(result['_meta']['max_results'], 50) self.assertEqual(result['_meta']['page'], 1) self.assertEqual(result['_meta']['total'], 5) # --- # Logout response = session.get('http://127.0.0.1:8888/logout') self.assertEqual(response.status_code, 200) result = response.json() self.assertEqual(result['_status'], 'OK') self.assertEqual(result['_result'], 'Logged out') @pytest.mark.skip("Internal function to get from an existing backend") def _get_from_backend(self, backend_url='http://127.0.01:5000', host_name='test', file_name='history.json'): """Get the all history for an host in an existing backend. Dumps the resulting information as a JSON array to a file :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Alignak backend URL 'alignak_backend': backend_url, 'username': '******', 'password': '******', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) time.sleep(2) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Start with first page ... max_results=3 page = 1 count = 25 items = [] search = { 'page': page, 'max_results': count } where = Helper.decode_search(host_name) if where: search.update({'where': json.dumps(where)}) while count > 0: result = my_module.getBackendHistory(search) count = len(result['items']) print("Page: %d, got: %d items" % (search["page"], count)) for item in result['items']: sys.stdout.write('.') # print(item) items.extend(result['items']) search["page"] += 1 print("Got: %d items" % len(items)) self.folder = '/tmp' self.file_dump(items, file_name)
def test_module_manager(self): """ Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load and initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) # Loading module logs self.assert_any_log_match(re.escape( "Importing Python module 'alignak_module_ws' for web-services..." )) self.assert_any_log_match(re.escape( "Module properties: {'daemons': ['receiver'], 'phases': ['running'], " "'type': 'web-services', 'external': True}" )) self.assert_any_log_match(re.escape( "Imported 'alignak_module_ws' for web-services" )) self.assert_any_log_match(re.escape( "Loaded Python module 'alignak_module_ws' (web-services)" )) self.assert_any_log_match(re.escape( "Give an instance of alignak_module_ws for alias: web-services" )) my_module = self.modulemanager.instances[0] # Get list of not external modules self.assertListEqual([], self.modulemanager.get_internal_instances()) for phase in ['configuration', 'late_configuration', 'running', 'retention']: self.assertListEqual([], self.modulemanager.get_internal_instances(phase)) # Get list of external modules self.assertListEqual([my_module], self.modulemanager.get_external_instances()) for phase in ['configuration', 'late_configuration', 'retention']: self.assertListEqual([], self.modulemanager.get_external_instances(phase)) for phase in ['running']: self.assertListEqual([my_module], self.modulemanager.get_external_instances(phase)) # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) # Clear logs self.clear_logs() # Kill the external module (normal stop is .stop_process) my_module.kill() time.sleep(0.1) self.assert_log_match("Killing external module", 0) self.assert_log_match("External module killed", 1) # Should be dead (not normally stopped...) but we still know a process for this module! self.assertIsNotNone(my_module.process) # Nothing special ... self.modulemanager.check_alive_instances() self.assert_log_match("The external module web-services died unexpectedly!", 2) self.assert_log_match("Setting the module web-services to restart", 3) # Try to restart the dead modules self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 4) # In fact it's too early, so it won't do it # The module instance is still dead self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 5) # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("I'm stopping module 'web-services'", 6) self.assert_log_match("Starting external process for module web-services", 7) self.assert_log_match("web-services is now started", 8) # There is nothing else to restart in the module manager self.assertEqual([], self.modulemanager.to_restart) # Clear logs self.clear_logs() # Now we look for time restart so we kill it again my_module.kill() time.sleep(0.2) self.assertFalse(my_module.process.is_alive()) self.assert_log_match("Killing external module", 0) self.assert_log_match("External module killed", 1) # Should be too early self.modulemanager.check_alive_instances() self.assert_log_match("The external module web-services died unexpectedly!", 2) self.assert_log_match("Setting the module web-services to restart", 3) self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 4) # In fact it's too early, so it won't do it # The module instance is still dead self.assertFalse(my_module.process.is_alive()) # So we lie, on the restart tries ... my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() self.assert_log_match("Trying to initialize module: web-services", 5) # The module instance is now alive again self.assertTrue(my_module.process.is_alive()) self.assert_log_match("I'm stopping module 'web-services'", 6) self.assert_log_match("Starting external process for module web-services", 7) self.assert_log_match("web-services is now started", 8) # And we clear all now self.modulemanager.stop_all() # Stopping module logs self.assert_log_match("Request external process to stop for web-services", 9) self.assert_log_match(re.escape("I'm stopping module 'web-services' (pid="), 10) self.assert_log_match( re.escape("'web-services' is still alive after normal kill, I help it to die"), 11 ) self.assert_log_match("Killing external module ", 12) self.assert_log_match("External module killed", 13) self.assert_log_match("External process stopped.", 14)
def _get_from_backend(self, backend_url='http://127.0.01:5000', host_name='test', file_name='history.json'): """Get the all history for an host in an existing backend. Dumps the resulting information as a JSON array to a file :return: """ self.print_header() # Obliged to call to get a self.logger... self.setup_with_file('cfg/cfg_default.cfg') self.assertTrue(self.conf_is_correct) # ----- # Provide parameters - logger configuration file (exists) # ----- # Clear logs self.clear_logs() # Create an Alignak module mod = Module({ 'module_alias': 'web-services', 'module_types': 'web-services', 'python_name': 'alignak_module_ws', # Set Arbiter address as empty to not poll the Arbiter else the test will fail! 'alignak_host': '', 'alignak_port': 7770, # Alignak backend URL 'alignak_backend': backend_url, 'username': '******', 'password': '******', }) # Create the modules manager for a daemon type self.modulemanager = ModulesManager('receiver', None) # Load an initialize the modules: # - load python module # - get module properties and instances self.modulemanager.load_and_init([mod]) my_module = self.modulemanager.instances[0] # Clear logs self.clear_logs() # Start external modules self.modulemanager.start_external_instances() # Starting external module logs self.assert_log_match("Trying to initialize module: web-services", 0) self.assert_log_match("Starting external module web-services", 1) self.assert_log_match("Starting external process for module web-services", 2) self.assert_log_match("web-services is now started", 3) time.sleep(2) # Check alive self.assertIsNotNone(my_module.process) self.assertTrue(my_module.process.is_alive()) time.sleep(1) # --- # Start with first page ... max_results=3 page = 1 count = 25 items = [] search = { 'page': page, 'max_results': count } where = Helper.decode_search(host_name) if where: search.update({'where': json.dumps(where)}) while count > 0: result = my_module.getBackendHistory(search) count = len(result['items']) print("Page: %d, got: %d items" % (search["page"], count)) for item in result['items']: sys.stdout.write('.') # print(item) items.extend(result['items']) search["page"] += 1 print("Got: %d items" % len(items)) self.folder = '/tmp' self.file_dump(items, file_name)