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()
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 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()
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 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_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"
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 TestModules(AlignakTest): """ This class contains the tests for the module """ def test_module_loading(self): """ Test module loading Alignak module loading :return: """ self.setup_with_file('./cfg/alignak.cfg') self.assertTrue(self.conf_is_correct) self.show_configuration_logs() # No arbiter modules created modules = [ m.module_alias for m in self._arbiter.link_to_myself.modules ] self.assertListEqual(modules, []) # No broker modules modules = [m.module_alias for m in self._broker_daemon.modules] self.assertListEqual(modules, []) # No scheduler modules modules = [m.module_alias for m in self._scheduler_daemon.modules] self.assertListEqual(modules, ['inner-retention']) # A receiver module modules = [m.module_alias for m in self._receiver.modules] self.assertListEqual(modules, ['nsca']) 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_start_default(self): """Test the module initialization function, no parameters, using default :return: """ # Obliged to call to get a self.logger... self.setup_with_file('./cfg/alignak.cfg') self.assertTrue(self.conf_is_correct) # Clear nsca self.clear_logs() # ----- # Default initialization # ----- # Create an Alignak module mod = Module({ 'module_alias': 'nsca', 'module_types': 'passive', 'python_name': 'alignak_module_nsca' }) instance = alignak_module_nsca.get_instance(mod) self.assertIsInstance(instance, BaseModule) self.show_logs() # self.assert_log_match( # re.escape("Give an instance of alignak_module_nsca for alias: nsca"), 0) self.assert_log_match( re.escape( "Give an instance of alignak_module_nsca for alias: nsca"), 0) 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"), 1)
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()
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)
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()
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')
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 test_module_loading(self): """ Test arbiter, broker, ... detecting configured modules :return: """ self.print_header() self.setup_with_file('./cfg/cfg_default_with_modules.cfg') assert self.conf_is_correct self.show_configuration_logs() # The only existing arbiter module is Example declared in the configuration modules = [m.module_alias for m in self.arbiter.myself.modules] assert modules == ['Example'] # The only existing broker module is Example declared in the configuration modules = [ m.module_alias for m in self.brokers['broker-master'].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.schedulers['scheduler-master'].modules ] assert modules == ['Example'] # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for Example..." )) self.assert_any_log_match( re.escape( "Module properties: {'daemons': ['arbiter', 'broker', 'scheduler', 'poller', " "'receiver', 'reactionner'], 'phases': ['configuration', 'late_configuration', " "'running', 'retention'], 'type': 'example', 'external': True}" )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for Example")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: Example" )) self.assert_any_log_match( re.escape("I correctly loaded my modules: [Example]")) def test_arbiter_configuration_module(self): """ Test arbiter configuration loading :return: """ self.print_header() self.setup_with_file('./cfg/cfg_arbiter_configuration_module.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.myself.modules] assert modules == ['backend_arbiter'] def test_missing_module_detection(self): """ Detect missing module configuration Alignak configuration parser detects that some modules are required because some specific parameters are included in the configuration files. If the modules are not present in the configuration, it logs warning message to alert the user about this! :return: """ self.print_header() with pytest.raises(SystemExit): self.setup_with_file( 'cfg/modules/alignak_modules_nagios_parameters.cfg') assert not self.conf_is_correct self.show_configuration_logs() # Log missing module self.assert_any_log_match( re.escape( "Your configuration parameters 'status_file = /var/status.dat' and " "'object_cache_file = /var/status.dat' need to use an external module such " "as 'retention' but I did not found one!")) self.assert_any_log_match( re.escape( "Your configuration parameter 'log_file = /test/file' needs to use an external " "module such as 'logs' but I did not found one!")) self.assert_any_log_match( re.escape( "Your configuration parameter 'use_syslog = True' needs to use an external " "module such as 'logs' but I did not found one!")) self.assert_any_log_match( re.escape( "Your configuration parameters 'host_perfdata_file = /test/file' and " "'service_perfdata_file = /test/file' need to use an external module such as " "'retention' but I did not found one!")) self.assert_any_log_match( re.escape( "Your configuration parameters 'state_retention_file = /test/file' and " "'retention_update_interval = 100' need to use an external module such as " "'retention' but I did not found one!")) self.assert_any_log_match( re.escape( "Your configuration parameter 'command_file = /var/alignak.cmd' needs to use " "an external module such as 'logs' but I did not found one!")) def test_module_on_module(self): """ No module configuration for modules Check that the feature is detected as disabled :return: """ self.print_header() self.setup_with_file('cfg/modules/alignak_module_with_submodules.cfg') assert self.conf_is_correct self.show_configuration_logs() # No arbiter modules created modules = [m.module_alias for m in self.arbiter.myself.modules] assert modules == ['Example'] # The only existing broker module is Example declared in the configuration modules = [ m.module_alias for m in self.brokers['broker-master'].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.schedulers['scheduler-master'].modules ] assert modules == ['Example'] def test_modulemanager(self): """ Module manager manages its modules Test if the module manager manages correctly all the modules :return: """ self.print_header() self.setup_with_file('cfg/cfg_default_with_modules.cfg') assert self.conf_is_correct time_hacker.set_real_time() # Create an Alignak module mod = Module({ 'module_alias': 'mod-example', 'module_types': 'example', 'python_name': 'alignak_module_example' }) # 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]) # Loading module logs self.assert_any_log_match( re.escape( "Importing Python module 'alignak_module_example' for Example..." )) self.assert_any_log_match( re.escape( "Module properties: {'daemons': ['arbiter', 'broker', 'scheduler', 'poller', " "'receiver', 'reactionner'], 'phases': ['configuration', 'late_configuration', " "'running', 'retention'], 'type': 'example', 'external': True}" )) self.assert_any_log_match( re.escape("Imported 'alignak_module_example' for Example")) self.assert_any_log_match( re.escape( "Give an instance of alignak_module_example for alias: Example" )) self.assert_any_log_match( re.escape("I correctly loaded my modules: [Example]")) my_module = self.modulemanager.instances[0] assert my_module.is_external # Get list of not external modules assert [] == self.modulemanager.get_internal_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [] == self.modulemanager.get_internal_instances(phase) # Get list of external modules assert [my_module] == self.modulemanager.get_external_instances() for phase in [ 'configuration', 'late_configuration', 'running', 'retention' ]: assert [my_module ] == self.modulemanager.get_external_instances(phase) # Start external modules self.modulemanager.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() # Kill the external module (normal stop is .stop_process) my_module.kill() time.sleep(0.1) # Should be dead (not normally stopped...) but we still know a process for this module! assert my_module.process is not None # Stopping module logs self.assert_any_log_match(re.escape("Killing external module ")) self.assert_any_log_match(re.escape("External module killed")) # Nothing special ... self.modulemanager.check_alive_instances() # Try to restart the dead modules 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 assert not my_module.process.is_alive() # So we lie my_module.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 assert my_module.process.is_alive() # should be nothing more in to_restart of # the module manager assert [] == self.modulemanager.to_restart # Now we look for time restart so we kill it again my_module.kill() time.sleep(0.2) assert not my_module.process.is_alive() # Should be too early self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() assert not my_module.process.is_alive() # We lie for the test again my_module.last_init_try = -5 self.modulemanager.check_alive_instances() self.modulemanager.try_to_restart_deads() # Here the inst should be alive again assert my_module.process.is_alive() # And we clear all now self.modulemanager.stop_all() # Stopping module logs self.assert_any_log_match(re.escape("I'm stopping module "))
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_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"