def _setup_nrpe(self):
        # Create an Alignak module
        mod = Module({
            'module_alias': 'nrpe-booster',
            'module_types': 'nrpe-booster',
            'python_name': 'alignak_module_nrpe_booster'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('poller', None)
        # Load and initialize the modules
        self.modulemanager.load_and_init([mod])
        my_module = self.modulemanager.instances[0]
        return my_module
Example #2
0
    def test_conflicting_modules(self):

        # prepare 2 modconfs:
        modconfA = Module({
            'module_alias': 'whatever',
            'python_name': 'test_module_as_package_dir.modA'
        })
        modconfB = Module({
            'module_alias': '42',
            'python_name': 'test_module_as_package_dir.modB'
        })

        mods = (modconfA, modconfB)

        mm = self.modulemanager = ModulesManager('broker', None)

        mm.load_and_init(mods)

        modA = None
        modB = None
        for _, mod in mm.modules_assoc:
            if mod.__package__ == 'test_module_as_package_dir.modA':
                modA = mod
            elif mod.__package__ == 'test_module_as_package_dir.modB':
                modB = mod

            if mod.properties['type'].startswith("mod"):
                self.assertEqual(mod.expected_helpers_X, mod.helpers.X)
        self.assertIsNotNone(modA)
        self.assertIsNotNone(modB)
        self.assertNotEqual(modA.helpers.X, modB.helpers.X)
class NrpePollerTestMixin(object):
    def setUp(self):
        super(NrpePollerTestMixin, self).setUp()
        logger.setLevel(logging.DEBUG)

    def _setup_nrpe(self):
        # Create an Alignak module
        mod = Module({
            'module_alias': 'nrpe-booster',
            'module_types': 'nrpe-booster',
            'python_name': 'alignak_module_nrpe_booster'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('poller', None)
        # Load and initialize the modules
        self.modulemanager.load_and_init([mod])
        my_module = self.modulemanager.instances[0]
        return my_module
Example #4
0
    def get_module(self, mod_name):
        """Get and load a module

        :param mod_name: module name to get
        :type mod_name: str
        :return: module
        :rtype: object
        """
        if self.modules_dir and self.modules_dir not in sys.path:
            sys.path.append(self.modules_dir)
        if self.modules_dir:
            mod_dir = os.path.join(self.modules_dir, mod_name)
        else:
            mod_dir = None
        # to keep it back-compatible with previous Alignak module way,
        # we first try with "import `mod_name`.module" and if we succeed
        # then that's the one to actually use:
        mod = ModulesManager.try_best_load('.module', mod_name)
        if mod:
            return mod
        # otherwise simply try new and old style:
        return ModulesManager.try_load(mod_name, mod_dir)
Example #5
0
class TestModuleWsHostGet(AlignakTest):
    """This class contains the tests for the module"""
    @classmethod
    def setUpClass(cls):

        # Set test mode for alignak backend
        os.environ['TEST_ALIGNAK_BACKEND'] = '1'
        os.environ[
            'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test'

        # Delete used mongo DBs
        print("Deleting Alignak backend DB...")
        exit_code = subprocess.call(
            shlex.split('mongo %s --eval "db.dropDatabase()"' %
                        os.environ['ALIGNAK_BACKEND_MONGO_DBNAME']))
        assert exit_code == 0

        fnull = open(os.devnull, 'w')
        cls.p = subprocess.Popen([
            'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app',
            '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads',
            '--pidfile', '/tmp/uwsgi.pid'
        ],
                                 stdout=fnull,
                                 stderr=fnull)
        time.sleep(3)

        endpoint = 'http://127.0.0.1:5000'

        test_dir = os.path.dirname(os.path.realpath(__file__))
        print("Current test directory: %s" % test_dir)

        print("Feeding Alignak backend... %s" % test_dir)
        exit_code = subprocess.call(shlex.split(
            'alignak-backend-import --delete %s/cfg/cfg_default.cfg' %
            test_dir),
                                    stdout=fnull,
                                    stderr=fnull)
        assert exit_code == 0
        print("Fed")

        # Backend authentication
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # Get admin user token (force regenerate)
        response = requests.post(endpoint + '/login',
                                 json=params,
                                 headers=headers)
        resp = response.json()
        cls.token = resp['token']
        cls.auth = requests.auth.HTTPBasicAuth(cls.token, '')

        # Get admin user
        response = requests.get(endpoint + '/user', auth=cls.auth)
        resp = response.json()
        cls.user_admin = resp['_items'][0]

        # Get realms
        response = requests.get(endpoint + '/realm', auth=cls.auth)
        resp = response.json()
        cls.realmAll_id = resp['_items'][0]['_id']

        # Add a user
        data = {
            'name':
            'test',
            'password':
            '******',
            'back_role_super_admin':
            False,
            'host_notification_period':
            cls.user_admin['host_notification_period'],
            'service_notification_period':
            cls.user_admin['service_notification_period'],
            '_realm':
            cls.realmAll_id
        }
        response = requests.post(endpoint + '/user',
                                 json=data,
                                 headers=headers,
                                 auth=cls.auth)
        resp = response.json()
        print("Created a new user: %s" % resp)

        # Get new user restrict role
        params = {'where': json.dumps({'user': resp['_id']})}
        response = requests.get(endpoint + '/userrestrictrole',
                                params=params,
                                auth=cls.auth)
        resp = response.json()

        # Update user's rights - set full CRUD rights
        headers = {
            'Content-Type': 'application/json',
            'If-Match': resp['_items'][0]['_etag']
        }
        data = {'crud': ['create', 'read', 'update', 'delete', 'custom']}
        resp = requests.patch(endpoint + '/userrestrictrole/' +
                              resp['_items'][0]['_id'],
                              json=data,
                              headers=headers,
                              auth=cls.auth)
        resp = resp.json()
        assert resp['_status'] == 'OK'

    @classmethod
    def tearDownClass(cls):
        cls.p.kill()

    def test_module_zzz_host_get(self):
        """Test the module /host API - host creation and get information
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            'give_result': '1',
            'give_feedback': '1',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1',
            # Errors for unknown host/service
            'ignore_unknown_host': '0',
            'ignore_unknown_service': '0',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Do not allow GET request on /host - not yet authorized!
        response = requests.get('http://127.0.0.1:8888/host')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post('http://127.0.0.1:8888/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # -----
        # Get a non-existing host - 1st: use parameters in the request
        response = session.get('http://127.0.0.1:8888/host',
                               auth=self.auth,
                               params={'name': 'new_host_2'})
        result = response.json()
        self.assertEqual(
            result, {
                u'_status': u'ERR',
                u'_result': [],
                u'_issues': ["Requested host 'new_host_2' does not exist"]
            })

        # Get a non-existing host - 2nd: use host name in the URI
        response = session.get('http://127.0.0.1:8888/host/new_host_2',
                               auth=self.auth)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status': u'ERR',
                u'_result': [],
                u'_issues': ["Requested host 'new_host_2' does not exist"]
            })

        # -----
        # Request to create an host - no provided data (default)
        headers = {'Content-Type': 'application/json'}
        data = {
            "name": "new_host_0",
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"Requested host 'new_host_0' does not exist.",
                    u"Requested host 'new_host_0' created."
                ],
                u'_feedback': {
                    u'name': u'new_host_0'
                }
            })
        # Host created with default check_command and in default user realm

        # -----
        # Get new host to confirm creation - 1st: use parameters in the request
        response = session.get('http://127.0.0.1:8888/host',
                               auth=self.auth,
                               params={'name': 'new_host_0'})
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertIsNot(result['_result'], {})
        self.assertEqual(result['_result'][0]['name'], 'new_host_0')

        # Get new host to confirm creation - 2nd: use host name in the URI
        response = session.get('http://127.0.0.1:8888/host/new_host_0',
                               auth=self.auth)
        result = response.json()
        from pprint import pprint
        pprint(result['_result'])
        # [{u'2d_coords': u'',
        # u'3d_coords': u'',
        # u'_created': u'Thu, 01 Jun 2017 10:58:30 GMT',
        # u'_etag': u'691c3f4a7cc8996c1d047932421759c020d00857',
        # u'_id': u'592ff35606fd4b7eec395625',
        # u'_is_template': False,
        # u'_links': {u'self': {u'href': u'host/592ff35606fd4b7eec395625',
        #                       u'title': u'Host'}},
        # u'_overall_state_id': 3,
        # u'_realm': {u'_all_children': [],
        #             u'_children': [],
        #             u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #             u'_etag': u'26b3830c017b4fca8553365246f21267aece46a7',
        #             u'_id': u'592ff35006fd4b7eec3955eb',
        #             u'_level': 0,
        #             u'_parent': None,
        #             u'_tree_parents': [],
        #             u'_updated': u'Thu, 01 Jun 2017 10:58:27 GMT',
        #             u'alias': u'',
        #             u'default': True,
        #             u'definition_order': 100,
        #             u'global_critical_threshold': 5,
        #             u'global_warning_threshold': 3,
        #             u'hosts_critical_threshold': 5,
        #             u'hosts_warning_threshold': 3,
        #             u'imported_from': u'unknown',
        #             u'name': u'All',
        #             u'notes': u'',
        #             u'services_critical_threshold': 5,
        #             u'services_warning_threshold': 3},
        # u'_sub_realm': True,
        # u'_template_fields': {},
        # u'_templates': [],
        # u'_templates_with_services': True,
        # u'_updated': u'Thu, 01 Jun 2017 10:58:30 GMT',
        # u'action_url': u'',
        # u'active_checks_enabled': True,
        # u'address': u'',
        # u'address6': u'',
        # u'alias': u'',
        # u'business_impact': 2,
        # u'business_impact_modulations': [],
        # u'business_rule_downtime_as_ack': False,
        # u'business_rule_host_notification_options': [u'd', u'u', u'r', u'f', u's'],
        # u'business_rule_output_template': u'',
        # u'business_rule_service_notification_options': [u'w',
        #                                                 u'u',
        #                                                 u'c',
        #                                                 u'r',
        #                                                 u'f',
        #                                                 u's'],
        # u'business_rule_smart_notifications': False,
        # u'check_command': {u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #                    u'_etag': u'356d02479ca7dbebe85e22b9b43e95dc9d5d037c',
        #                    u'_id': u'592ff35006fd4b7eec3955f1',
        #                    u'_realm': u'592ff35006fd4b7eec3955eb',
        #                    u'_sub_realm': True,
        #                    u'_updated': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #                    u'alias': u'Host/service is always UP/OK',
        #                    u'command_line': u'_internal_host_up',
        #                    u'definition_order': 100,
        #                    u'enable_environment_macros': False,
        #                    u'imported_from': u'unknown',
        #                    u'module_type': u'fork',
        #                    u'name': u'_internal_host_up',
        #                    u'notes': u'',
        #                    u'poller_tag': u'',
        #                    u'reactionner_tag': u'',
        #                    u'timeout': -1},
        # u'check_command_args': u'',
        # u'check_freshness': False,
        # u'check_interval': 5,
        # u'checkmodulations': [],
        # u'custom_views': [],
        # u'customs': {},
        # u'definition_order': 100,
        # u'display_name': u'',
        # u'escalations': [],
        # u'event_handler': None,
        # u'event_handler_args': u'',
        # u'event_handler_enabled': False,
        # u'failure_prediction_enabled': False,
        # u'first_notification_delay': 0,
        # u'flap_detection_enabled': True,
        # u'flap_detection_options': [u'o', u'd', u'x'],
        # u'freshness_state': u'x',
        # u'freshness_threshold': 0,
        # u'high_flap_threshold': 50,
        # u'icon_image': u'',
        # u'icon_image_alt': u'',
        # u'icon_set': u'',
        # u'imported_from': u'unknown',
        # u'initial_state': u'x',
        # u'labels': [],
        # u'location': {u'coordinates': [48.858293, 2.294601], u'type': u'Point'},
        # u'low_flap_threshold': 25,
        # u'ls_acknowledged': False,
        # u'ls_acknowledgement_type': 1,
        # u'ls_attempt': 0,
        # u'ls_current_attempt': 0,
        # u'ls_downtimed': False,
        # u'ls_execution_time': 0.0,
        # u'ls_grafana': False,
        # u'ls_grafana_panelid': 0,
        # u'ls_impact': False,
        # u'ls_last_check': 0,
        # u'ls_last_hard_state_changed': 0,
        # u'ls_last_notification': 0,
        # u'ls_last_state': u'OK',
        # u'ls_last_state_changed': 0,
        # u'ls_last_state_type': u'HARD',
        # u'ls_last_time_down': 0,
        # u'ls_last_time_unknown': 0,
        # u'ls_last_time_unreachable': 0,
        # u'ls_last_time_up': 0,
        # u'ls_latency': 0.0,
        # u'ls_long_output': u'',
        # u'ls_max_attempts': 0,
        # u'ls_next_check': 0,
        # u'ls_output': u'',
        # u'ls_passive_check': False,
        # u'ls_perf_data': u'',
        # u'ls_state': u'UNREACHABLE',
        # u'ls_state_id': 3,
        # u'ls_state_type': u'HARD',
        # u'macromodulations': [],
        # u'max_check_attempts': 1,
        # u'name': u'new_host_0',
        # u'notes': u'',
        # u'notes_url': u'',
        # u'notification_interval': 60,
        # u'notification_options': [u'd', u'x', u'r', u'f', u's'],
        # u'notifications_enabled': True,
        # u'obsess_over_host': False,
        # u'parents': [],
        # u'passive_checks_enabled': True,
        # u'poller_tag': u'',
        # u'process_perf_data': True,
        # u'reactionner_tag': u'',
        # u'resultmodulations': [],
        # u'retry_interval': 0,
        # u'service_excludes': [],
        # u'service_includes': [],
        # u'service_overrides': [],
        # u'snapshot_criteria': [u'd', u'x'],
        # u'snapshot_enabled': False,
        # u'snapshot_interval': 5,
        # u'stalking_options': [],
        # u'statusmap_image': u'',
        # u'tags': [],
        # u'time_to_orphanage': 300,
        # u'trending_policies': [],
        # u'trigger_broker_raise_enabled': False,
        # u'trigger_name': u'',
        # u'usergroups': [],
        # u'users': [],
        # u'vrml_image': u''}]
        #
        self.assertEqual(result['_status'], 'OK')
        self.assertIsNot(result['_result'], {})
        self.assertEqual(result['_result'][0]['name'], 'new_host_0')

        # -----
        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

        self.modulemanager.stop_all()
    def test_module_manager_arbiter(self):
        """
        Test if the module manager manages correctly all the modules
        :return:
        """
        self.print_header()
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        time_hacker.set_real_time()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'SnmpBoosterArbiter',
            'module_types': 'checks',
            'python_name': 'alignak_module_snmp_booster.snmpbooster_arbiter',
            'loaded_by': 'arbiter',
            'datasource': './cfg/genDevConfig/example.ini',
            'db_host': 'localhost',
            'db_port': 6379
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('arbiter', None)

        # Clear logs
        self.clear_logs()

        # Load and initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        # Loading module logs
        self.assert_log_match(
            re.escape(
                "Importing Python module 'alignak_module_snmp_booster.snmpbooster_arbiter' for "
                "SnmpBoosterArbiter..."), 0)
        self.assert_log_match(
            re.escape(
                "Module properties: {'daemons': ['arbiter'], 'phases': ['running', "
                "'late_configuration'], 'type': 'snmp_booster', 'external': False, "
                "'worker_capable': True}"), 1)
        self.assert_log_match(
            re.escape(
                "Imported 'alignak_module_snmp_booster.snmpbooster_arbiter' for SnmpBoosterArbiter"
            ), 2)
        self.assert_log_match(
            re.escape(
                "Loaded Python module 'alignak_module_snmp_booster.snmpbooster_arbiter' "
                "(SnmpBoosterArbiter)"), 3)
        self.assert_log_match(
            re.escape(
                "Give an instance of alignak_module_snmp_booster.snmpbooster_arbiter "
                "for alias: SnmpBoosterArbiter"), 4)

        self.assert_log_match(
            re.escape(
                "[SnmpBooster] [code 0101] Loading SNMP Booster module for plugin SnmpBoosterArbiter"
            ), 5)
        self.assert_log_match(
            re.escape(
                "[SnmpBooster] [code 0902] Reading input configuration file: "
                "./cfg/genDevConfig/example.ini"), 6)

        # Starting internal module logs
        self.assert_log_match(
            re.escape("Trying to initialize module: SnmpBoosterArbiter"), 7)
        self.assert_log_match(
            re.escape(
                "[SnmpBooster] [code 1101] Initialization of the SNMP Booster 2.0.0"
            ), 8)

        my_module = self.modulemanager.instances[0]

        # Get list of not external modules
        self.assertListEqual([my_module],
                             self.modulemanager.get_internal_instances())
        for phase in ['configuration', 'retention']:
            self.assertListEqual(
                [], self.modulemanager.get_internal_instances(phase))
        for phase in ['late_configuration', 'running']:
            self.assertListEqual(
                [my_module], self.modulemanager.get_internal_instances(phase))

        # Get list of external modules
        self.assertListEqual([], self.modulemanager.get_external_instances())
        for phase in [
                'configuration', 'late_configuration', 'running', 'retention'
        ]:
            self.assertListEqual(
                [], self.modulemanager.get_external_instances(phase))

        # Clear logs
        self.clear_logs()

        # Nothing special ...
        self.modulemanager.check_alive_instances()

        # And we clear all now
        self.modulemanager.stop_all()
Example #7
0
class TestModuleNoBackend(AlignakTest):
    """This class contains the tests for the module"""
    @classmethod
    def setUpClass(cls):
        # Simulate an Alignak receiver daemon
        cls.ws_endpoint = 'http://127.0.0.1:7773/ws'
        import cherrypy

        class ReceiverItf(object):
            @cherrypy.expose
            def index(self):
                return "I am the Receiver daemon!"

        from alignak.http.daemon import HTTPDaemon as AlignakDaemon
        http_daemon1 = AlignakDaemon('0.0.0.0', 7773, ReceiverItf(), False,
                                     None, None, None, None, 10,
                                     '/tmp/alignak-cherrypy.log')

        def run_http_server():
            http_daemon1.run()

        import threading
        cls.http_thread1 = threading.Thread(target=run_http_server,
                                            name='http_server_receiver')
        cls.http_thread1.daemon = True
        cls.http_thread1.start()
        print("Thread started")

        cls.modulemanager = None

    def setUp(self):
        super(TestModuleNoBackend, self).setUp()

    def tearDown(self):
        """Delete resources in backend

        :return: None
        """
        super(TestModuleNoBackend, self).tearDown()
        if self.modulemanager:
            self.modulemanager.stop_all()

    def test_module_host_livestate_unauthorized(self):
        """Test the module /host API - host livestate - unauthorized access
        :return:
        """
        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': '',
            'username': '',
            'password': '',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            # Do not give feedback data
            'give_feedback': '0',
            'give_result': '1',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Set module to listen on all interfaces
            'host': '0.0.0.0',
            'port': 8888,

            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1',
            # Force Alignak backend update by the module (default is not force!)
            'alignak_backend_livestate_update': '0',

            # Disable authorization
            'authorization': '0'
        })

        # Create a receiver daemon
        args = {'env_file': '', 'daemon_name': 'receiver-master'}
        self._receiver_daemon = Receiver(**args)

        # Create the modules manager for the daemon
        self.modulemanager = ModulesManager(self._receiver_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        session = requests.Session()

        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post(self.ws_endpoint + '/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # -----
        # Update an host with an host livestate (heartbeat / host is alive): livestate
        # Because there is no backend configured, only an external command is raised
        # to Alignak for the host
        data = {
            "name": "new_host_0",
            "livestate": {
                # No timestamp in the livestate
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch(self.ws_endpoint + '/host',
                                 json=data,
                                 headers=headers)
        print(response)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                '_status':
                'OK',
                '_result': [
                    'new_host_0 is alive :)',
                    "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...",
                ]
            })
        # No errors - an extrenal command was raised for the host livestate

        # -----
        # Update an host with an host livestate (heartbeat / host is alive): livestate
        # Because there is no backend configured, only an external command is raised
        # to Alignak for the host
        data = {
            "name":
            "new_host_0",
            "livestate": {
                # No timestamp in the livestate
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            },
            "services": [{
                "name": "test_svc_0",
                "livestate": {
                    "state": "OK",
                    "output": "Output...",
                    "long_output": "Long output...",
                    "perf_data": "'counter'=1",
                }
            }]
        }
        self.assertEqual(my_module.received_commands, 1)
        response = session.patch(self.ws_endpoint + '/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                '_status':
                'OK',
                '_result': [
                    'new_host_0 is alive :)',
                    "PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...",
                    "PROCESS_SERVICE_CHECK_RESULT;new_host_0;test_svc_0;0;Output...|'counter'=1\nLong output..."
                ]
            })
        # No errors - an extrenal command was raised for the host livestate

        self.modulemanager.stop_all()
class TestModules(AlignakTest):
    """
    This class contains the tests for the modules
    """
    def setUp(self):
        super(TestModules, self).setUp()
        self.set_unit_tests_logger_level('INFO')

    def test_module_loading(self):
        """ Test arbiter, broker, ... detecting configured modules

        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct
        self.show_configuration_logs()
        self.show_logs()

        # arbiter modules
        modules = [m.module_alias for m in self._arbiter.link_to_myself.modules]
        assert modules == ['Example']
        modules = [m.name for m in self._arbiter.link_to_myself.modules]
        assert modules == ['Example']

        # broker modules
        modules = [m.module_alias for m in self._broker_daemon.modules]
        assert modules == ['Example']
        modules = [m.name for m in self._broker_daemon.modules]
        assert modules == ['Example']

        # # The only existing poller module is Example declared in the configuration
        # modules = [m.module_alias for m in self.pollers['poller-master'].modules]
        # assert modules == ['Example']
        #
        # # The only existing receiver module is Example declared in the configuration
        # modules = [m.module_alias for m in self.receivers['receiver-master'].modules]
        # assert modules == ['Example']
        #
        # # The only existing reactionner module is Example declared in the configuration
        # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules]
        # assert modules == ['Example']

        # No scheduler modules created
        modules = [m.module_alias for m in self._scheduler_daemon.modules]
        assert modules == ['Example']
        modules = [m.name for m in self._scheduler_daemon.modules]
        assert modules == ['Example']

        self.show_logs()

        # Loading module logs
        self.assert_any_log_match(re.escape(
            u"Importing Python module 'alignak_module_example' for Example..."
        ))
        self.assert_any_log_match(re.escape(
            u"Imported 'alignak_module_example' for Example"
        ))
        self.assert_any_log_match(re.escape(
            u"Give an instance of alignak_module_example for alias: Example"
        ))
        self.assert_any_log_match(re.escape(
            u"I correctly loaded my modules: [Example]"
        ))

    def test_arbiter_configuration_module(self):
        """ Test arbiter configuration loading

        :return:
        """
        self.setup_with_file('./cfg/modules/arbiter_modules.cfg')
        assert self.conf_is_correct
        self.show_configuration_logs()
        self.show_logs()

        # The arbiter module is 'backend_arbiter' declared in the configuration
        modules = [m.module_alias for m in self._arbiter.link_to_myself.modules]
        assert modules == ['Example']

    def test_module_on_module(self):
        """ No module configuration for modules

        Check that the feature is detected as disabled
        :return:
        """
        self.setup_with_file('cfg/modules/alignak_module_with_submodules.cfg')
        assert self.conf_is_correct
        self.show_configuration_logs()

        # arbiter modules
        modules = [m.module_alias for m in self._arbiter.link_to_myself.modules]
        assert modules == ['Example']
        modules = [m.name for m in self._arbiter.link_to_myself.modules]
        assert modules == ['Example']

        # broker modules
        modules = [m.module_alias for m in self._broker_daemon.modules]
        assert modules == ['Example']
        modules = [m.name for m in self._broker_daemon.modules]
        assert modules == ['Example']

        # # The only existing poller module is Example declared in the configuration
        # modules = [m.module_alias for m in self.pollers['poller-master'].modules]
        # assert modules == ['Example']
        #
        # # The only existing receiver module is Example declared in the configuration
        # modules = [m.module_alias for m in self.receivers['receiver-master'].modules]
        # assert modules == ['Example']
        #
        # # The only existing reactionner module is Example declared in the configuration
        # modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules]
        # assert modules == ['Example']

        # No scheduler modules created
        modules = [m.module_alias for m in self._scheduler_daemon.modules]
        assert modules == ['Example', 'inner-retention']
        modules = [m.name for m in self._scheduler_daemon.modules]
        assert modules == ['Example', 'inner-retention']

    def test_modulemanager_1(self):
        """ Module manager manages its modules - old form

        Test if the module manager manages correctly all the modules
        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct

        # Create an Alignak module
        mod = Module({
            'module_alias': 'mod-example',
            'module_types': 'example',
            'python_name': 'alignak_module_example'
        })
        self.run_modulemanager(mod)

    def test_modulemanager_2(self):
        """ Module manager manages its modules - new form

        Test if the module manager manages correctly all the modules
        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct

        # Create an Alignak module
        mod = Module({
            'name': 'mod-example',
            'type': 'example',
            'python_name': 'alignak_module_example'
        })
        self.run_modulemanager(mod)

    def run_modulemanager(self, mod):
        # Force the daemon SyncManager to None for unit tests!
        self._broker_daemon.sync_manager = None

        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modules_manager.load_and_init([mod])

        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example"
        ))

        self.clear_logs()

        my_module = self.modules_manager.instances[0]
        assert my_module.is_external

        # Get list of not external modules
        assert [] == self.modules_manager.get_internal_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [] == self.modules_manager.get_internal_instances(phase)

        # Get list of external modules
        assert [my_module] == self.modules_manager.get_external_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [my_module] == self.modules_manager.get_external_instances(phase)

        # Start external modules
        self.modules_manager.start_external_instances()

        self.show_logs()

        # Starting external module logs
        idx = 0
        self.assert_log_match(re.escape(
            "Trying to initialize module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Test - Example in init"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Initialization of the example module"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Module mod-example is initialized"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external process for module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "mod-example is now started (pid="
        ), idx)
        idx += 1
        self.assert_log_count(7)

        # Check alive
        assert my_module.process is not None
        assert my_module.process.is_alive()

        self.clear_logs()
        # Check the alive module instances...
        self.modules_manager.check_alive_instances()
        # Try to restart the dead modules, if any
        self.modules_manager.try_to_restart_deads()
        self.assert_log_count(0)

        # Kill the external module (normal stop is .stop_process)
        self.clear_logs()
        my_module.kill()
        idx = 0
        self.assert_log_match(re.escape(
            "Killing external module "
        ), idx)
        idx += 1
        self.show_logs()

        # self.assert_log_match(re.escape(
        #     "mod-example is still living "
        # ), idx)
        # idx += 1
        # Specific case because sometimes the module is not killed within the expected 10s time
        normal_kill = True
        logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME)
        for handler in logger_.handlers:
            if not isinstance(handler, CollectorHandler):
                continue
            regex = re.compile('mod-example is still living')

            log_num = 0
            found = False
            for log in handler.collector:
                if idx == log_num:
                    if regex.search(log):
                        idx += 1
                        normal_kill = False
                        break
                log_num += 1
            break

        self.assert_log_match(re.escape(
            "External module killed"
        ), idx)
        idx += 1
        self.assert_log_count(idx)

        # The module is dead (not normally stopped...) so this module inner
        # process reference is not None!
        assert my_module.process is not None

        # Check the alive module instances...
        self.clear_logs()
        idx = 0
        self.modules_manager.check_alive_instances()
        self.show_logs()
        self.assert_log_match(re.escape(
            "The external module mod-example died unexpectedly!"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Setting the module mod-example to restart"
        ), idx)
        self.assert_log_count(2)
        idx += 1

        if normal_kill:
            # Try to restart the dead modules, if any
            # Indeed, it's too early, so it won't do it
            self.clear_logs()
            idx = 0
            print("try init: %d" % my_module.init_try)
            self.modules_manager.try_to_restart_deads()
            self.show_logs()

            self.assert_log_match(re.escape(
                "Trying to restart module: mod-example"
            ), idx)
            idx += 1
            self.assert_log_match(re.escape(
                "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD
            ), idx)
            idx += 1
            self.assert_log_count(2)

            # Here the module instance is still dead
            assert not my_module.process.is_alive()

            # Wait for a minimum delay
            time.sleep(MODULE_INIT_PERIOD + 1)

        # my_module.last_init_try = -5
        self.clear_logs()
        self.modules_manager.check_alive_instances()
        self.show_logs()
        self.assert_log_count(0)

        # Try to restart the dead modules, if any
        # Now it is time...
        self.clear_logs()
        idx = 0
        self.modules_manager.try_to_restart_deads()
        self.show_logs()
        self.assert_log_match(re.escape(
            "Trying to restart module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Trying to initialize module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Test - Example in init"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Initialization of the example module"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Module mod-example is initialized"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Restarting mod-example..."
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external process for module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "mod-example is now started (pid="
        ), idx)
        idx += 1
        self.assert_log_count(8)

        # Here the module instance should be alive again
        assert my_module.process.is_alive()

        # No more module to restart...
        assert [] == self.modules_manager.to_restart

        # And we clear all now
        self.clear_logs()
        idx = 0
        self.modules_manager.stop_all()
        self.show_logs()
        self.assert_log_match(re.escape(
            "Shutting down modules..."
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Request external process to stop for mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "I'm stopping module 'mod-example'"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Killing external module "
        ), idx)
        idx += 1

        # Specific case because sometimes the module is not killed within the expected 10s time
        logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME)
        for handler in logger_.handlers:
            if not isinstance(handler, CollectorHandler):
                continue
            regex = re.compile('mod-example is still living')

            log_num = 0
            found = False
            for log in handler.collector:
                if idx == log_num:
                    if regex.search(log):
                        idx += 1
                        break
                log_num += 1
            break

        self.assert_log_match(re.escape(
            "External module killed"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "External process stopped."
        ), idx)
        idx += 1
        # self.assert_log_count(6)

    def test_modulemanager_several_modules(self):
        """ Module manager manages its modules

        Test if the module manager manages correctly all the modules

        Configured with several modules
        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct

        # for mod in self._arbiter.conf.modules:
        #     print (mod.__dict__)

        # Create an Alignak module
        mod = Module({
            'module_alias': 'mod-example',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'foo',
            'option2': 'bar',
            'option3': 1
        })
        mod2 = Module({
            'module_alias': 'mod-example-2',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'faa',
            'option2': 'bor',
            'option3': 1
        })

        # Force the daemon SyncManager to None for unit tests!
        self._broker_daemon.sync_manager = None
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)
        print("Modules: %s" % self._broker_daemon.modules)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        assert self.modules_manager.load_and_init([mod, mod2])
        print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in
                                                                self.modules_manager.instances]))
        self.show_logs()

        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_example' (mod-example)"
        ))
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example-2..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example-2"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_example' (mod-example-2)"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "configuration, foo, bar, 1"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example-2"
        ))
        self.assert_any_log_match(re.escape(
            "configuration, faa, bor, 1"
        ))
        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))

        my_module = self.modules_manager.instances[0]
        my_module2 = self.modules_manager.instances[1]
        assert my_module.is_external
        assert my_module2.is_external

        # Get list of not external modules
        assert [] == self.modules_manager.get_internal_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [] == self.modules_manager.get_internal_instances(phase)

        # Get list of external modules
        assert [my_module, my_module2] == self.modules_manager.get_external_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [my_module, my_module2] == self.modules_manager.get_external_instances(phase)

        # Start external modules
        self.modules_manager.start_external_instances()
        self.modules_manager.start_external_instances()

        # Starting external module logs
        self.assert_any_log_match(re.escape(
            "Starting external module mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Starting external process for module mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "mod-example is now started (pid="
        ))

        # Check alive
        assert my_module.process is not None
        assert my_module.process.is_alive()

        assert my_module2.process is not None
        assert my_module2.process.is_alive()

        # Kill the external module (normal stop is .stop_process)
        self.clear_logs()
        print("Killing a module")
        my_module.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "Killing external module "
        ))
        self.assert_any_log_match(re.escape(
            "External module killed"
        ))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        self.clear_logs()
        print("Killing another module")
        my_module2.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "Killing external module "
        ))
        self.assert_any_log_match(re.escape(
            "External module killed"
        ))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        # Nothing special ...
        self.clear_logs()
        self.modules_manager.check_alive_instances()

        # Try to restart the dead modules
        print("Trying to restart dead modules")
        # We lie on the last restart try time
        my_module.last_init_try = time.time()
        my_module2.last_init_try = time.time()
        self.modules_manager.try_to_restart_deads()
        self.show_logs()
        # In fact it's too early, so it won't do it

        # Here the module instances should still be dead
        assert not my_module.process.is_alive()
        assert not my_module2.process.is_alive()

        # We lie on the last restart try time
        my_module.last_init_try = 0
        my_module2.last_init_try = 0
        self.modules_manager.check_alive_instances()
        self.modules_manager.try_to_restart_deads()

        # Here the module instances should be alive again
        assert my_module.process.is_alive()
        assert my_module2.process.is_alive()

        # Kill the module again
        self.clear_logs()
        my_module.kill()
        self.show_logs()
        time.sleep(0.2)
        assert not my_module.process.is_alive()

        # And we clear all now
        self.modules_manager.stop_all()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "I'm stopping module "
        ))
class TestModuleWsHostLivestate(AlignakTest):
    """This class contains the tests for the module"""
    @classmethod
    def setUpClass(cls):

        # Set test mode for alignak backend
        os.environ['TEST_ALIGNAK_BACKEND'] = '1'
        os.environ[
            'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test'

        # Delete used mongo DBs
        print("Deleting Alignak backend DB...")
        exit_code = subprocess.call(
            shlex.split('mongo %s --eval "db.dropDatabase()"' %
                        os.environ['ALIGNAK_BACKEND_MONGO_DBNAME']))
        assert exit_code == 0

        fnull = open(os.devnull, 'w')
        cls.p = subprocess.Popen([
            'uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app',
            '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads',
            '--pidfile', '/tmp/uwsgi.pid'
        ],
                                 stdout=fnull,
                                 stderr=fnull)
        time.sleep(3)

        endpoint = 'http://127.0.0.1:5000'

        test_dir = os.path.dirname(os.path.realpath(__file__))
        print("Current test directory: %s" % test_dir)

        print("Feeding Alignak backend...")
        print('alignak-backend-import --delete %s/cfg/cfg_default.cfg' %
              test_dir)
        exit_code = subprocess.call(shlex.split(
            'alignak-backend-import --delete %s/cfg/cfg_default.cfg' %
            test_dir),
                                    stdout=fnull,
                                    stderr=fnull)
        assert exit_code == 0
        print("Fed")

        # Backend authentication
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # Get admin user token (force regenerate)
        response = requests.post(endpoint + '/login',
                                 json=params,
                                 headers=headers)
        resp = response.json()
        cls.token = resp['token']
        cls.auth = requests.auth.HTTPBasicAuth(cls.token, '')

        # Get admin user
        response = requests.get(endpoint + '/user', auth=cls.auth)
        resp = response.json()
        cls.user_admin = resp['_items'][0]

        # Get realms
        response = requests.get(endpoint + '/realm', auth=cls.auth)
        resp = response.json()
        cls.realmAll_id = resp['_items'][0]['_id']

        # Add a user
        data = {
            'name':
            'test',
            'password':
            '******',
            'back_role_super_admin':
            False,
            'host_notification_period':
            cls.user_admin['host_notification_period'],
            'service_notification_period':
            cls.user_admin['service_notification_period'],
            '_realm':
            cls.realmAll_id
        }
        response = requests.post(endpoint + '/user',
                                 json=data,
                                 headers=headers,
                                 auth=cls.auth)
        resp = response.json()
        print("Created a new user: %s" % resp)

        # Get new user restrict role
        params = {'where': json.dumps({'user': resp['_id']})}
        response = requests.get(endpoint + '/userrestrictrole',
                                params=params,
                                auth=cls.auth)
        resp = response.json()

        # Update user's rights - set full CRUD rights
        headers = {
            'Content-Type': 'application/json',
            'If-Match': resp['_items'][0]['_etag']
        }
        data = {'crud': ['create', 'read', 'update', 'delete', 'custom']}
        resp = requests.patch(endpoint + '/userrestrictrole/' +
                              resp['_items'][0]['_id'],
                              json=data,
                              headers=headers,
                              auth=cls.auth)
        resp = resp.json()
        assert resp['_status'] == 'OK'

        cls.modulemanager = None

    @classmethod
    def tearDownClass(cls):
        if cls.modulemanager:
            cls.modulemanager.stop_all()
        cls.p.kill()

    @classmethod
    def tearDown(cls):
        """Delete resources in backend

        :return: None
        """
        for resource in ['logcheckresult']:
            requests.delete('http://127.0.0.1:5000/' + resource, auth=cls.auth)

    def test_module_zzz_host_livestate(self):
        """Test the module /host API - host creation and livestate
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            # Send a log_check_result to the alignak backend
            'alignak_backend_old_lcr': '1',
            # Do not give feedback data
            'give_feedback': '0',
            'give_result': '1',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Alignak backend
        # ---
        self.endpoint = 'http://127.0.0.1:5000'
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # get token
        response = requests.post(self.endpoint + '/login',
                                 json=params,
                                 headers=headers)
        resp = response.json()
        self.token = resp['token']
        self.auth = requests.auth.HTTPBasicAuth(self.token, '')

        # Do not allow GET request on /host - not authorized
        response = requests.get('http://127.0.0.1:8888/host')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post('http://127.0.0.1:8888/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # -----
        # Create a new host with an host livestate (heartbeat / host is alive): livestate
        data = {
            "name": "new_host_0",
            "livestate": {
                # No timestamp in the livestate
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"Requested host 'new_host_0' does not exist.",
                    u"Requested host 'new_host_0' created.",
                    u"PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...",
                ]
            })
        # No errors!

        # Get new host in the backend
        response = requests.get(
            self.endpoint + '/host',
            auth=self.auth,
            params={'where': json.dumps({'name': 'new_host_0'})})
        resp = response.json()
        new_host_0 = resp['_items'][0]
        self.assertEqual('new_host_0', new_host_0['name'])

        # Get backend check results - no check result sent to the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        self.assertEqual(len(rl), 0)

        # -----
        # Send an host livestate
        data = {
            "name": "new_host_0",
            "livestate": {
                # No timestamp in the livestate
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output...",
                ]
            })
        # No errors!

        # Get backend check results - no check result sent to the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        self.assertEqual(len(rl), 0)

        # -----
        # Send an host livestate with a timestamp in the past
        now = int(time.time()) - 3600
        data = {
            "name": "new_host_0",
            "livestate": {
                # Timestamp in the past
                "timestamp": now,
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"[%d] PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output..."
                    % now,
                ]
            })
        # No errors!

        # Get backend check results - a check result was recorded in the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        # A log check result was recorded...
        self.assertEqual(len(rl), 1)
        rl = resp['_items'][0]
        print("LCR: %s" % rl)
        # ...with the correct timestamp
        self.assertEqual(rl['host_name'], "new_host_0")
        self.assertEqual(rl['last_check'], now)

        # -----
        # Send an host livestate with a timestamp in the past but sooner than the former one
        now = now + 1800
        data = {
            "name": "new_host_0",
            "livestate": {
                # Timestamp in the past
                "timestamp": now,
                "state": "UP",
                "output": "Output...",
                "long_output": "Long output...",
                "perf_data": "'counter'=1",
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"[%d] PROCESS_HOST_CHECK_RESULT;new_host_0;0;Output...|'counter'=1\nLong output..."
                    % now,
                ]
            })
        # No errors!

        # Get backend check results - one more check result was recorded in the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        # A log check result was recorded...
        self.assertEqual(len(rl), 2)
        # Get the second LCR
        rl = resp['_items'][1]
        print("LCR: %s" % rl)
        # ...with the correct timestamp
        self.assertEqual(rl['host_name'], "new_host_0")
        self.assertEqual(rl['last_check'], now)

        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

        self.modulemanager.stop_all()

    def test_module_zzz_service_livestate(self):
        """Test the module /host API - service creation and livestate
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            # Send a log_check_result to the alignak backend
            'alignak_backend_old_lcr': '1',
            # Do not give feedback data
            'give_feedback': '0',
            'give_result': '1',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Alignak backend
        # ---
        self.endpoint = 'http://127.0.0.1:5000'
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # get token
        response = requests.post(self.endpoint + '/login',
                                 json=params,
                                 headers=headers)
        resp = response.json()
        self.token = resp['token']
        self.auth = requests.auth.HTTPBasicAuth(self.token, '')

        # Do not allow GET request on /host - not authorized
        response = requests.get('http://127.0.0.1:8888/host')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post('http://127.0.0.1:8888/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # Request to create an host - create a new host
        headers = {'Content-Type': 'application/json'}
        data = {
            "name": "new_host_for_services_0",
            "template": {
                "_realm": 'All',
                "check_command": "_internal_host_up"
            }
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_for_services_0 is alive :)',
                    u"Requested host 'new_host_for_services_0' does not exist.",
                    u"Requested host 'new_host_for_services_0' created."
                ]
            })
        # No errors!

        # Get new host in the backend
        response = requests.get(
            self.endpoint + '/host',
            auth=self.auth,
            params={'where': json.dumps({'name': 'new_host_for_services_0'})})
        resp = response.json()
        new_host_for_services_0 = resp['_items'][0]
        self.assertEqual('new_host_for_services_0',
                         new_host_for_services_0['name'])

        # Get backend check results - no check result sent to the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        self.assertEqual(len(rl), 0)

        # Request to create an host - create a new service without any template data
        headers = {'Content-Type': 'application/json'}
        data = {
            "name":
            "new_host_for_services_0",
            "services": [{
                "name": "test_empty_0",
                # "template": {
                #     "_realm": 'All',
                #     "check_command": "_echo"
                # },
                "livestate": {
                    "state": "OK",
                    "output": "Output...",
                    "long_output": "Long output...",
                    "perf_data": "'counter'=1",
                },
                "variables": {
                    'test1': 'string',
                    'test2': 1,
                    'test3': 5.0
                },
            }]
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_for_services_0 is alive :)',
                    u"Requested service 'new_host_for_services_0/test_empty_0' does not exist.",
                    u"Requested service 'new_host_for_services_0/test_empty_0' created.",
                    u"PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output...",
                    u"Service 'new_host_for_services_0/test_empty_0' updated",
                ]
            })
        # No errors!

        # Get new host to confirm creation
        response = requests.get(
            self.endpoint + '/host',
            auth=self.auth,
            params={'where': json.dumps({'name': 'new_host_for_services_0'})})
        resp = response.json()
        new_host_for_services_0 = resp['_items'][0]
        self.assertEqual('new_host_for_services_0',
                         new_host_for_services_0['name'])

        # Get services data to confirm update
        response = requests.get(self.endpoint + '/service',
                                auth=self.auth,
                                params={
                                    'where':
                                    json.dumps({
                                        'host':
                                        new_host_for_services_0['_id'],
                                        'name':
                                        'test_empty_0'
                                    })
                                })
        resp = response.json()
        service = resp['_items'][0]
        expected = {u'_TEST3': 5.0, u'_TEST2': 1, u'_TEST1': u'string'}
        self.assertEqual(expected, service['customs'])

        # Send a service livestate, no timestamp
        headers = {'Content-Type': 'application/json'}
        data = {
            "name":
            "new_host_for_services_0",
            "services": [{
                "name": "test_empty_0",
                "livestate": {
                    # No timestamp in the livestate
                    "state": "OK",
                    "output": "Output...",
                    "long_output": "Long output...",
                    "perf_data": "'counter'=1",
                }
            }]
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_for_services_0 is alive :)',
                    u"PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output...",
                ]
            })
        # No errors!

        # Get backend check results - no check result sent to the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        self.assertEqual(len(rl), 0)

        # Send a service livestate, timestamp in the past
        headers = {'Content-Type': 'application/json'}
        now = int(time.time()) - 3600
        data = {
            "name":
            "new_host_for_services_0",
            "services": [{
                "name": "test_empty_0",
                "livestate": {
                    # Timestamp in the past
                    "timestamp": now,
                    "state": "OK",
                    "output": "Output...",
                    "long_output": "Long output...",
                    "perf_data": "'counter'=1",
                }
            }]
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_for_services_0 is alive :)',
                    u"[%d] PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output..."
                    % now,
                ]
            })
        # No errors!

        # Get backend check results - a check result was recorded in the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        # A log check result was recorded...
        self.assertEqual(len(rl), 1)
        rl = resp['_items'][0]
        print("LCR: %s" % rl)
        # ...with the correct timestamp
        self.assertEqual(rl['host_name'], "new_host_for_services_0")
        self.assertEqual(rl['service_name'], "test_empty_0")
        self.assertEqual(rl['last_check'], now)

        # Send a service livestate with a timestamp in the past but sooner than the former one
        now = now + 1800
        data = {
            "name":
            "new_host_for_services_0",
            "services": [{
                "name": "test_empty_0",
                "livestate": {
                    # Timestamp in the past
                    "timestamp": now,
                    "state": "OK",
                    "output": "Output...",
                    "long_output": "Long output...",
                    "perf_data": "'counter'=1",
                }
            }]
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_for_services_0 is alive :)',
                    u"[%d] PROCESS_SERVICE_CHECK_RESULT;new_host_for_services_0;test_empty_0;0;Output...|'counter'=1\nLong output..."
                    % now,
                ]
            })
        # No errors!

        # Get backend check results - a check result was recorded in the backend
        response = requests.get(self.endpoint + '/logcheckresult',
                                auth=self.auth)
        resp = response.json()
        rl = resp['_items']
        # A log check result was recorded...
        self.assertEqual(len(rl), 2)
        rl = resp['_items'][1]
        print("LCR: %s" % rl)
        # ...with the correct timestamp
        self.assertEqual(rl['host_name'], "new_host_for_services_0")
        self.assertEqual(rl['service_name'], "test_empty_0")
        self.assertEqual(rl['last_check'], now)

        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

        self.modulemanager.stop_all()
Example #10
0
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 "))
Example #11
0
    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
Example #12
0
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')
Example #13
0
    def setUp(self):
        """Create resources in backend

        :return: None
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        self.my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(self.my_module.process)
        self.assertTrue(self.my_module.process.is_alive())

        time.sleep(1)
    def test_module_zzz_command(self):
        """ Test the WS /command endpoint
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Do not allow GET request on /command - not yet authorized
        response = requests.get('http://127.0.0.1:8888/command')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post('http://127.0.0.1:8888/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # Allowed request on /command
        response = session.get('http://127.0.0.1:8888/command')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ERR')
        self.assertEqual(result['_error'],
                         'You must only POST on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # You must have parameters when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {}
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ERR')
        self.assertEqual(result['_error'],
                         'You must POST parameters on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # You must have a command parameter when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {
            # "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ERR')
        # Result error message
        self.assertEqual(result['_error'], 'Missing command parameter')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1')

        # Request to execute an external command with timestamp - bad value
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "timestamp": "text",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result, {
            u'_status': u'ERR',
            u'_error': u'Timestamp must be an integer value'
        })

        # Request to execute an external command with timestamp
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "timestamp": "1234",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(
            result['_command'],
            '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element":
            "test_host/test_service",  # Accept / as an host/service separator
            "parameters": "1;abc;2"
        }
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "parameters": "1;abc;2"
        }
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "user": "******",
            "parameters": "1;abc;2"
        }
        response = session.post('http://127.0.0.1:8888/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(
            result['_command'],
            'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2')

        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

        self.modulemanager.stop_all()
Example #15
0
class TestMetricsSetup(AlignakTest):
    """
    This class tests the inner metrics module set-up
    """
    def setUp(self):
        super(TestMetricsSetup, self).setUp()

        # Log at DEBUG level
        self.set_unit_tests_logger_level()
        self.clear_logs()

        # Create a fake server
        self.fake_carbon = FakeCarbonServer(port=2004)

        if os.path.exists('/tmp/alignak-metrics.log'):
            os.remove('/tmp/alignak-metrics.log')

    def tearDown(self):
        super(TestMetricsSetup, self).tearDown()

        self.fake_carbon.stop()
        self.fake_carbon.join()

    def test_default_is_disabled(self):
        """ Test that default configuration is metrics disabled

        :return: None
        """
        self.setup_with_file('cfg/cfg_default.cfg')

        # Default configuration do not enable the module
        assert True == self._scheduler.pushed_conf.process_performance_data
        assert self._scheduler.pushed_conf.host_perfdata_command is None
        assert self._scheduler.pushed_conf.service_perfdata_command is None
        assert self._scheduler.pushed_conf.host_perfdata_file == ''
        assert self._scheduler.pushed_conf.service_perfdata_file == ''

        assert self._broker_daemon.modules == []

    def test_inner_module_enabled(self):
        """ Test that inner metrics module may be enabled

        If configuration parameters host_perfdata_command or service_perfdata_command
        are declared and not empty and if process_performance_data is set, the inner metrics
        module is configured and enabled to push performance data to the Alignak configured
        StatsD / Graphite interface.

        :return: None
        """
        self.setup_with_file('cfg/cfg_metrics.cfg')

        # Specific configuration enables the module
        assert True == self._scheduler.pushed_conf.process_performance_data
        assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts'
        assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services'
        assert 1 == len(self._broker_daemon.modules)

        self.show_logs()

    def test_inner_module_configuration(self):
        """ Test that inner metrics module may be configured in Alignak configuration

        Withi this configuration, hosts/services cache is enabled and tested. Broks for
        unknown hosts/services are ignored.

        :return: None
        """
        self.setup_with_file('cfg/cfg_metrics.cfg', 'cfg/inner_metrics/alignak.ini')

        # Specific configuration enables the module
        assert True == self._scheduler.pushed_conf.process_performance_data
        assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts'
        assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services'
        assert 1 == len(self._broker_daemon.modules)

        self.show_logs()

        # The declared module instance
        my_module = self._broker_daemon.modules[0]
        print(my_module)
        # Generic stuff
        assert my_module.python_name == 'alignak.modules.inner_metrics'
        assert my_module.type == 'metrics'
        assert my_module.alias == 'inner-metrics'
        assert my_module.enabled is True

        # Specific stuff - the content of the configuration parameters
        # When the module is configured in Alignak configuration, it does not exist!
        # assert my_module.host_perfdata_file == 'go-hosts'
        # assert my_module.service_perfdata_file == 'go-services'

        self.clear_logs()

        # Module is not yet initialized, let's do it in place of the daemon.
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modules_manager.load_and_init([my_module])

        self.show_logs()

        # Module is an internal one (no external process) in the broker daemon modules manager
        my_module = self._broker_daemon.modules_manager.instances[0]
        assert my_module.is_external is False

        # Known hosts/services cache is empty
        assert my_module.hosts_cache == {}
        assert my_module.services_cache == {}

        # When the broker daemon receives a Brok, it is propagated to the module

        # Host check result
        self.clear_logs()
        hcr = {
            "host_name": "srv001",

            "last_time_unreachable": 0,
            "last_problem_id": 0,
            "passive_check": False,
            "retry_interval": 1,
            "last_event_id": 0,
            "problem_has_been_acknowledged": False,
            "command_name": "pm-check_linux_host_alive",
            "last_state": "UP",
            "latency": 0.2317881584,
            "last_state_type": "HARD",
            "last_hard_state_change": 1444427108,
            "last_time_up": 0,
            "percent_state_change": 0.0,
            "state": "DOWN",
            "last_chk": 1444427104,
            "last_state_id": 0,
            "end_time": 0,
            "timeout": 0,
            "current_event_id": 10,
            "execution_time": 3.1496069431000002,
            "start_time": 0,
            "return_code": 2,
            "state_type": "SOFT",
            "output": "CRITICAL - Plugin timed out after 10 seconds",
            "in_checking": True,
            "early_timeout": 0,
            "in_scheduled_downtime": False,
            "attempt": 0,
            "state_type_id": 1,
            "acknowledgement_type": 1,
            "last_state_change": 1444427108.040841,
            "last_time_down": 1444427108,
            "instance_id": 0,
            "long_output": "",
            "current_problem_id": 0,
            "check_interval": 5,
            "state_id": 2,
            "has_been_checked": 1,
            "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
        }
        b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(1)
        self.assert_log_match("received host check result for an unknown host", 0)

        # Service check result
        self.clear_logs()
        scr = {
            "host_name": "srv001",
            "service_description": "ping",
            "command_name": "ping",

            "attempt": 1,
            "execution_time": 3.1496069431000002,
            "latency": 0.2317881584,
            "return_code": 2,
            "state": "OK",
            "state_type": "HARD",
            "state_id": 0,
            "state_type_id": 1,

            "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms",
            "long_output": "Long output ...",
            "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0",

            "passive_check": False,

            "problem_has_been_acknowledged": False,
            "acknowledgement_type": 1,
            "in_scheduled_downtime": False,

            "last_chk": 1473597375,
            "last_state_change": 1444427108.147903,
            "last_state_id": 0,
            "last_state": "UNKNOWN",
            "last_state_type": "HARD",
            "last_hard_state_change": 0.0,
            "last_time_unknown": 0,
            "last_time_unreachable": 0,
            "last_time_critical": 1473597376,
            "last_time_warning": 0,
            "last_time_ok": 0,

            "retry_interval": 2,
            "percent_state_change": 4.1,
            "check_interval": 5,

            "in_checking": False,
            "early_timeout": 0,
            "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc",
            "current_event_id": 1,
            "last_event_id": 0,
            "current_problem_id": 1,
            "last_problem_id": 0,
            "timeout": 0,
            "has_been_checked": 1,
            "start_time": 0,
            "end_time": 0
        }
        b = Brok({'data': scr, 'type': 'service_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(1)
        self.assert_log_match("received service check result for an unknown host", 0)

        # Initial host status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
        }
        b = Brok({'data': hcr, 'type': 'initial_host_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert my_module.services_cache == {}

        # Initial service status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
            "service_description": "ping"
        }
        b = Brok({'data': hcr, 'type': 'initial_service_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert 'srv001/ping' in my_module.services_cache
        assert my_module.services_cache['srv001/ping'] == {}

        # Now the host srv001 is known in the module, let's raise an host brok

        # Host check result
        self.clear_logs()
        hcr = {
            "host_name": "srv001",

            "last_time_unreachable": 0,
            "last_problem_id": 0,
            "passive_check": False,
            "retry_interval": 1,
            "last_event_id": 0,
            "problem_has_been_acknowledged": False,
            "command_name": "pm-check_linux_host_alive",
            "last_state": "UP",
            "latency": 0.2317881584,
            "last_state_type": "HARD",
            "last_hard_state_change": 1444427108,
            "last_time_up": 0,
            "percent_state_change": 0.0,
            "state": "DOWN",
            "last_chk": 1444427104,
            "last_state_id": 0,
            "end_time": 0,
            "timeout": 0,
            "current_event_id": 10,
            "execution_time": 3.1496069431000002,
            "start_time": 0,
            "return_code": 2,
            "state_type": "SOFT",
            "output": "CRITICAL - Plugin timed out after 10 seconds",
            "in_checking": True,
            "early_timeout": 0,
            "in_scheduled_downtime": False,
            "attempt": 0,
            "state_type_id": 1,
            "acknowledgement_type": 1,
            "last_state_change": 1444427108.040841,
            "last_time_down": 1444427108,
            "instance_id": 0,
            "long_output": "",
            "current_problem_id": 0,
            "check_interval": 5,
            "state_id": 2,
            "has_been_checked": 1,
            "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
        }
        b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
        self._broker_daemon.manage_brok(b)

        # 5 log events because the Graphite server do not respond!
        self.show_logs()
        # self.assert_any_log_match(re.escape('Exception: [Errno 111] Connection refused'))
        self.assert_log_count(0)

        # File output
        assert os.path.exists('/tmp/alignak-metrics.log')

    def test_inner_module_broks(self):
        """ Test that inner metrics module is managing broks with the default configuration

        :return: None
        """
        self.setup_with_file('cfg/cfg_metrics.cfg')

        # Specific configuration enables the module
        assert True == self._scheduler.pushed_conf.process_performance_data
        assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts'
        assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services'
        assert 1 == len(self._broker_daemon.modules)

        self.show_logs()

        # The declared module instance
        my_module = self._broker_daemon.modules[0]
        # Generic stuff
        assert my_module.python_name == 'alignak.modules.inner_metrics'
        assert my_module.type == 'metrics'
        assert my_module.alias == 'inner-metrics'
        assert my_module.enabled is True

        # Specific stuff - the content of the configuration parameters
        assert my_module.host_perfdata_file == 'go-hosts'
        assert my_module.service_perfdata_file == 'go-services'

        self.clear_logs()

        # Module is not yet initialized, let's do it in place of the daemon.
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modules_manager.load_and_init([my_module])

        self.show_logs()

        # Module is an internal one (no external process) in the broker daemon modules manager
        my_module = self._broker_daemon.modules_manager.instances[0]
        assert my_module.is_external is False

        # Known hosts/services cache is empty
        assert my_module.hosts_cache == {}
        assert my_module.services_cache == {}

        # When the broker daemon receives a Brok, it is propagated to the module

        # Host check result
        self.clear_logs()
        hcr = {
            "host_name": "srv001",

            "last_time_unreachable": 0,
            "last_problem_id": 0,
            "passive_check": False,
            "retry_interval": 1,
            "last_event_id": 0,
            "problem_has_been_acknowledged": False,
            "command_name": "pm-check_linux_host_alive",
            "last_state": "UP",
            "latency": 0.2317881584,
            "last_state_type": "HARD",
            "last_hard_state_change": 1444427108,
            "last_time_up": 0,
            "percent_state_change": 0.0,
            "state": "DOWN",
            "last_chk": 1444427104,
            "last_state_id": 0,
            "end_time": 0,
            "timeout": 0,
            "current_event_id": 10,
            "execution_time": 3.1496069431000002,
            "start_time": 0,
            "return_code": 2,
            "state_type": "SOFT",
            "output": "CRITICAL - Plugin timed out after 10 seconds",
            "in_checking": True,
            "early_timeout": 0,
            "in_scheduled_downtime": False,
            "attempt": 0,
            "state_type_id": 1,
            "acknowledgement_type": 1,
            "last_state_change": 1444427108.040841,
            "last_time_down": 1444427108,
            "instance_id": 0,
            "long_output": "",
            "current_problem_id": 0,
            "check_interval": 5,
            "state_id": 2,
            "has_been_checked": 1,
            "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
        }
        b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(0)

        # Service check result
        self.clear_logs()
        scr = {
            "host_name": "srv001",
            "service_description": "ping",
            "command_name": "ping",

            "attempt": 1,
            "execution_time": 3.1496069431000002,
            "latency": 0.2317881584,
            "return_code": 2,
            "state": "OK",
            "state_type": "HARD",
            "state_id": 0,
            "state_type_id": 1,

            "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms",
            "long_output": "Long output ...",
            "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0",

            "passive_check": False,

            "problem_has_been_acknowledged": False,
            "acknowledgement_type": 1,
            "in_scheduled_downtime": False,

            "last_chk": 1473597375,
            "last_state_change": 1444427108.147903,
            "last_state_id": 0,
            "last_state": "UNKNOWN",
            "last_state_type": "HARD",
            "last_hard_state_change": 0.0,
            "last_time_unknown": 0,
            "last_time_unreachable": 0,
            "last_time_critical": 1473597376,
            "last_time_warning": 0,
            "last_time_ok": 0,

            "retry_interval": 2,
            "percent_state_change": 4.1,
            "check_interval": 5,

            "in_checking": False,
            "early_timeout": 0,
            "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc",
            "current_event_id": 1,
            "last_event_id": 0,
            "current_problem_id": 1,
            "last_problem_id": 0,
            "timeout": 0,
            "has_been_checked": 1,
            "start_time": 0,
            "end_time": 0
        }
        b = Brok({'data': scr, 'type': 'service_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(0)

        # Initial host status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
        }
        b = Brok({'data': hcr, 'type': 'initial_host_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert my_module.services_cache == {}

        # Initial service status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
            "service_description": "ping"
        }
        b = Brok({'data': hcr, 'type': 'initial_service_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert 'srv001/ping' in my_module.services_cache
        assert my_module.services_cache['srv001/ping'] == {}
Example #16
0
    def test_inner_module_broks(self):
        """ Test that inner metrics module is managing broks with the default configuration

        :return: None
        """
        self.setup_with_file('cfg/cfg_metrics.cfg')

        # Specific configuration enables the module
        assert True == self._scheduler.pushed_conf.process_performance_data
        assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts'
        assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services'
        assert 1 == len(self._broker_daemon.modules)

        self.show_logs()

        # The declared module instance
        my_module = self._broker_daemon.modules[0]
        # Generic stuff
        assert my_module.python_name == 'alignak.modules.inner_metrics'
        assert my_module.type == 'metrics'
        assert my_module.alias == 'inner-metrics'
        assert my_module.enabled is True

        # Specific stuff - the content of the configuration parameters
        assert my_module.host_perfdata_file == 'go-hosts'
        assert my_module.service_perfdata_file == 'go-services'

        self.clear_logs()

        # Module is not yet initialized, let's do it in place of the daemon.
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modules_manager.load_and_init([my_module])

        self.show_logs()

        # Module is an internal one (no external process) in the broker daemon modules manager
        my_module = self._broker_daemon.modules_manager.instances[0]
        assert my_module.is_external is False

        # Known hosts/services cache is empty
        assert my_module.hosts_cache == {}
        assert my_module.services_cache == {}

        # When the broker daemon receives a Brok, it is propagated to the module

        # Host check result
        self.clear_logs()
        hcr = {
            "host_name": "srv001",

            "last_time_unreachable": 0,
            "last_problem_id": 0,
            "passive_check": False,
            "retry_interval": 1,
            "last_event_id": 0,
            "problem_has_been_acknowledged": False,
            "command_name": "pm-check_linux_host_alive",
            "last_state": "UP",
            "latency": 0.2317881584,
            "last_state_type": "HARD",
            "last_hard_state_change": 1444427108,
            "last_time_up": 0,
            "percent_state_change": 0.0,
            "state": "DOWN",
            "last_chk": 1444427104,
            "last_state_id": 0,
            "end_time": 0,
            "timeout": 0,
            "current_event_id": 10,
            "execution_time": 3.1496069431000002,
            "start_time": 0,
            "return_code": 2,
            "state_type": "SOFT",
            "output": "CRITICAL - Plugin timed out after 10 seconds",
            "in_checking": True,
            "early_timeout": 0,
            "in_scheduled_downtime": False,
            "attempt": 0,
            "state_type_id": 1,
            "acknowledgement_type": 1,
            "last_state_change": 1444427108.040841,
            "last_time_down": 1444427108,
            "instance_id": 0,
            "long_output": "",
            "current_problem_id": 0,
            "check_interval": 5,
            "state_id": 2,
            "has_been_checked": 1,
            "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
        }
        b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(0)

        # Service check result
        self.clear_logs()
        scr = {
            "host_name": "srv001",
            "service_description": "ping",
            "command_name": "ping",

            "attempt": 1,
            "execution_time": 3.1496069431000002,
            "latency": 0.2317881584,
            "return_code": 2,
            "state": "OK",
            "state_type": "HARD",
            "state_id": 0,
            "state_type_id": 1,

            "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms",
            "long_output": "Long output ...",
            "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0",

            "passive_check": False,

            "problem_has_been_acknowledged": False,
            "acknowledgement_type": 1,
            "in_scheduled_downtime": False,

            "last_chk": 1473597375,
            "last_state_change": 1444427108.147903,
            "last_state_id": 0,
            "last_state": "UNKNOWN",
            "last_state_type": "HARD",
            "last_hard_state_change": 0.0,
            "last_time_unknown": 0,
            "last_time_unreachable": 0,
            "last_time_critical": 1473597376,
            "last_time_warning": 0,
            "last_time_ok": 0,

            "retry_interval": 2,
            "percent_state_change": 4.1,
            "check_interval": 5,

            "in_checking": False,
            "early_timeout": 0,
            "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc",
            "current_event_id": 1,
            "last_event_id": 0,
            "current_problem_id": 1,
            "last_problem_id": 0,
            "timeout": 0,
            "has_been_checked": 1,
            "start_time": 0,
            "end_time": 0
        }
        b = Brok({'data': scr, 'type': 'service_check_result'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        self.assert_log_count(0)

        # Initial host status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
        }
        b = Brok({'data': hcr, 'type': 'initial_host_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert my_module.services_cache == {}

        # Initial service status
        self.clear_logs()
        hcr = {
            "host_name": "srv001",
            "service_description": "ping"
        }
        b = Brok({'data': hcr, 'type': 'initial_service_status'}, False)
        self._broker_daemon.manage_brok(b)
        self.show_logs()
        # The module inner cache stored the host
        assert 'srv001' in my_module.hosts_cache
        assert my_module.hosts_cache['srv001'] == {}
        assert 'srv001/ping' in my_module.services_cache
        assert my_module.services_cache['srv001/ping'] == {}
Example #17
0
class TestModules(AlignakTest):
    """
    This class contains the tests for the module
    """

    def test_module_loading(self):
        """
        Test arbiter, broker, ... auto-generated modules

        Alignak module loading

        :return:
        """
        self.print_header()
        self.setup_with_file('./cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)
        self.show_configuration_logs()

        # No arbiter modules created
        modules = [m.module_alias for m in self.arbiter.myself.modules]
        self.assertListEqual(modules, [])

        # The only existing broker module is logs declared in the configuration
        modules = [m.module_alias for m in self.brokers['broker-master'].modules]
        self.assertListEqual(modules, [])

        # No poller module
        modules = [m.module_alias for m in self.pollers['poller-master'].modules]
        self.assertListEqual(modules, [])

        # No receiver module
        modules = [m.module_alias for m in self.receivers['receiver-master'].modules]
        self.assertListEqual(modules, ['web-services'])

        # No reactionner module
        modules = [m.module_alias for m in self.reactionners['reactionner-master'].modules]
        self.assertListEqual(modules, [])

        # No scheduler modules
        modules = [m.module_alias for m in self.schedulers['scheduler-master'].modules]
        self.assertListEqual(modules, [])

    def test_module_manager(self):
        """
        Test if the module manager manages correctly all the modules
        :return:
        """
        self.print_header()
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        time_hacker.set_real_time()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load and initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_ws' for web-services..."
        ))
        self.assert_any_log_match(re.escape(
            "Module properties: {'daemons': ['receiver'], 'phases': ['running'], "
            "'type': 'web-services', 'external': True}"
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_ws' for web-services"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_ws' (web-services)"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_ws for alias: web-services"
        ))

        my_module = self.modulemanager.instances[0]

        # Get list of not external modules
        self.assertListEqual([], self.modulemanager.get_internal_instances())
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            self.assertListEqual([], self.modulemanager.get_internal_instances(phase))

        # Get list of external modules
        self.assertListEqual([my_module], self.modulemanager.get_external_instances())
        for phase in ['configuration', 'late_configuration', 'retention']:
            self.assertListEqual([], self.modulemanager.get_external_instances(phase))
        for phase in ['running']:
            self.assertListEqual([my_module], self.modulemanager.get_external_instances(phase))

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        # Clear logs
        self.clear_logs()

        # Kill the external module (normal stop is .stop_process)
        my_module.kill()
        time.sleep(0.1)
        self.assert_log_match("Killing external module", 0)
        self.assert_log_match("External module killed", 1)

        # Should be dead (not normally stopped...) but we still know a process for this module!
        self.assertIsNotNone(my_module.process)

        # Nothing special ...
        self.modulemanager.check_alive_instances()
        self.assert_log_match("The external module web-services died unexpectedly!", 2)
        self.assert_log_match("Setting the module web-services to restart", 3)

        # Try to restart the dead modules
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 4)

        # In fact it's too early, so it won't do it
        # The module instance is still dead
        self.assertFalse(my_module.process.is_alive())

        # So we lie, on the restart tries ...
        my_module.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 5)

        # The module instance is now alive again
        self.assertTrue(my_module.process.is_alive())
        self.assert_log_match("I'm stopping module 'web-services'", 6)
        self.assert_log_match("Starting external process for module web-services", 7)
        self.assert_log_match("web-services is now started", 8)

        # There is nothing else to restart in the module manager
        self.assertEqual([], self.modulemanager.to_restart)

        # Clear logs
        self.clear_logs()

        # Now we look for time restart so we kill it again
        my_module.kill()
        time.sleep(0.2)
        self.assertFalse(my_module.process.is_alive())
        self.assert_log_match("Killing external module", 0)
        self.assert_log_match("External module killed", 1)

        # Should be too early
        self.modulemanager.check_alive_instances()
        self.assert_log_match("The external module web-services died unexpectedly!", 2)
        self.assert_log_match("Setting the module web-services to restart", 3)

        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 4)

        # In fact it's too early, so it won't do it
        # The module instance is still dead
        self.assertFalse(my_module.process.is_alive())

        # So we lie, on the restart tries ...
        my_module.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 5)

        # The module instance is now alive again
        self.assertTrue(my_module.process.is_alive())
        self.assert_log_match("I'm stopping module 'web-services'", 6)
        self.assert_log_match("Starting external process for module web-services", 7)
        self.assert_log_match("web-services is now started", 8)

        # And we clear all now
        self.modulemanager.stop_all()
        # Stopping module logs

        self.assert_log_match("Request external process to stop for web-services", 9)
        self.assert_log_match(re.escape("I'm stopping module 'web-services' (pid="), 10)
        self.assert_log_match(
            re.escape("'web-services' is still alive after normal kill, I help it to die"), 11
        )
        self.assert_log_match("Killing external module ", 12)
        self.assert_log_match("External module killed", 13)
        self.assert_log_match("External process stopped.", 14)

    def test_module_start_default(self):
        """
        Test the module initialization function, no parameters, using default
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Default initialization
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws'
        })

        instance = alignak_module_ws.get_instance(mod)
        self.assertIsInstance(instance, BaseModule)

        self.assert_log_match(
            re.escape("Give an instance of alignak_module_ws for "
                      "alias: web-services"), 0)
        self.assert_log_match(
            re.escape("configuration, Alignak Arbiter: 127.0.0.1:7770"), 1)
        self.assert_log_match(
            re.escape("configuration, listening on: 0.0.0.0:8888"), 2)
        self.assert_log_match(
            re.escape("SSL is not enabled, this is not recommended. "
                      "You should consider enabling SSL!"), 3)

    def test_module_start_parameters(self):
        """
        Test the module initialization function, no parameters, provide parameters
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            'use_ssl': '1',
            'alignak_host': 'my_host',
            'alignak_port': 80,
            'host': 'me',
            'port': 8080,
        })

        instance = alignak_module_ws.get_instance(mod)
        self.assertIsInstance(instance, BaseModule)

        self.assert_log_match(
            re.escape("Give an instance of alignak_module_ws for "
                      "alias: web-services"), 0)
        self.assert_log_match(
            re.escape("configuration, Alignak Arbiter: my_host:80"), 1)
        self.assert_log_match(
            re.escape("configuration, listening on: me:8080"), 2)
        self.assert_log_match(
            re.escape("Error : the CA certificate /usr/local/etc/alignak/certs/ca.pem is "
                      "missing (ca_cert).Please fix it in your configuration"), 3)
        self.assert_log_match(
            re.escape("SSL is not enabled, this is not recommended. "
                      "You should consider enabling SSL!"), 4)

    def test_module_zzz_run(self):
        """
        Test the module API
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Get the module API list and request on each endpoint
        response = requests.get('http://127.0.0.1:8888')
        api_list = response.json()
        for endpoint in api_list:
            print("Trying %s" % (endpoint))
            response = requests.get('http://127.0.0.1:8888/' + endpoint)
            print("Response %d: %s" % (response.status_code, response.content))
            self.assertEqual(response.status_code, 200)
            if response.status_code == 200:
                print("Got %s: %s" % (endpoint, response.json()))
            else:
                print("Error %s: %s" % (response.status_code, response.content))

        time.sleep(1)

        # Do not allow GET request on /command
        response = requests.get('http://127.0.0.1:8888/command')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ko')
        self.assertEqual(result['_result'], 'You must only POST on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # You must have parameters when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {}
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ko')
        self.assertEqual(result['_result'], 'You must POST parameters on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND;test_host;abc;1')

        # Not during unit tests ... because module queues are not functional!
        # time.sleep(1)
        # self.assertEqual(my_module.received_commands, 1)

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host/test_service",    # Accept / as an host/service separator
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "user": "******",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'],
                         'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2')

        self.modulemanager.stop_all()
    def test_inner_module_configuration(self):
        """ Test that inner metrics module may be configured in Alignak configuration

        With this configuration, hosts/services cache is enabled and tested. Broks for
        unknown hosts/services are ignored.

        :return: None
        """
        with requests_mock.mock() as mr:
            mr.get("http://localhost:8086/ping",
                   json={
                       "results":[{
                           "statement_id":0, "version":"1.7.2"
                       }]
                   }, status_code=204, headers={"x-influxdb-version": "1.7.2"})
            mr.get("http://localhost:8086/query?q=SHOW+DATABASES&db=alignak",
                   json={
                       "results":[{
                           "statement_id":0, "series":[
                                {"name":"databases","columns":["name"],"values":[["_internal"]]}
                            ]
                       }]
                   })
            mr.get("http://localhost:8086/query?q=SHOW+DATABASES&db=alignak",
                   json={"results": [{"statement_id": 0}]})
            mr.post("http://localhost:8086/query?q=CREATE+DATABASE+%22alignak%22&db=alignak",
                   json={"results":[{ "statement_id":0 }]})
            mr.post("http://localhost:8086/query?q=CREATE+RETENTION+POLICY+%22alignak%22+ON+%22alignak%22+DURATION+1y+REPLICATION+1+SHARD+DURATION+0s&db=alignak",
                   json={"results":[{ "statement_id":0 }]})
            mr.post("http://localhost:8086/write?db=alignak", status_code=204,
                    json={"results":[{ "statement_id":0 }]})

            self.setup_with_file('cfg/cfg_metrics.cfg', 'cfg/inner_metrics/alignak.ini')

            # Specific configuration enables the module
            assert self._scheduler.pushed_conf.process_performance_data is True
            assert self._scheduler.pushed_conf.host_perfdata_file == 'go-hosts'
            assert self._scheduler.pushed_conf.service_perfdata_file == 'go-services'
            assert 1 == len(self._broker_daemon.modules)

            self.show_logs()

            # The declared module instance
            my_module = self._broker_daemon.modules[0]
            print(my_module)
            # Generic stuff
            assert my_module.python_name == 'alignak.modules.inner_metrics'
            assert my_module.type == 'metrics'
            # assert my_module.alias == 'inner-metrics'
            assert my_module.enabled is True

            # Specific stuff - the content of the configuration parameters
            # When the module is configured in Alignak configuration, it does not exist!
            # assert my_module.host_perfdata_file == 'go-hosts'
            # assert my_module.service_perfdata_file == 'go-services'
            assert my_module.output_file == '/tmp/alignak-metrics.log'

            self.clear_logs()

            # Module is not yet initialized, let's do it in place of the daemon.
            # Create the modules manager for a daemon type
            self.modules_manager = ModulesManager(self._broker_daemon)

            # Load an initialize the modules:
            #  - load python module
            #  - get module properties and instances
            self.modules_manager.load_and_init([my_module])

            self.show_logs()

            # self.assert_log_match(
            #     "Targets configuration: graphite: True, influxdb: True, "
            #     "file: /tmp/alignak-metrics.log", 10)
            #
            self.assert_log_match(
                "targets configuration: graphite: True, influxdb: True, "
                "file: /tmp/alignak-metrics.log", 11)

            self.assert_log_match(
                "Storing metrics in an output file is configured. Do not forget "
                "to regularly clean this file to avoid important disk usage!", 12)

            self.assert_log_match("Trying to initialize module: inner-metrics", 24)

            self.assert_log_match("testing storage to /tmp/alignak-metrics.log ...", 25)
            self.assert_log_match("Ok", 26)

            self.assert_log_match("testing connection to InfluxDB localhost:8086 ...", 27)
            self.assert_log_match("connected, InfluxDB version 1.7.2", 28)
            self.assert_log_match("testing connection to Graphite localhost:2004 ...", 29)
            self.assert_log_match("Ok", 30)

            self.assert_log_match("creating database alignak...", 31)
            # self.assert_log_match("creating database retention policy: alignak - 1y - 1...", 32)
            # self.assert_log_match("Ok", 33)

            self.assert_log_match("Module inner-metrics is initialized.", 32)

            # Module is an internal one (no external process) in the broker daemon modules manager
            my_module = self._broker_daemon.modules_manager.instances[0]
            assert my_module.is_external is False

            # Known hosts/services cache is empty
            assert my_module.hosts_cache == {}
            assert my_module.services_cache == {}

            # File output - we still got a metric for the connection test!
            assert os.path.exists('/tmp/alignak-metrics.log')
            with open('/tmp/alignak-metrics.log') as f:
                lines = f.readlines()
                first_line = False
                for line in lines:
                    assert 3 == len(line.split(';'))
                    if not first_line:
                        line = line.strip()
                        metric = line.split(';')
                        assert metric[0] == metric[2]
                        assert metric[1] == 'connection-test'
                    print(line)
                # Some metrics were stored
                assert 2 == len(lines)

            # When the broker daemon receives a Brok, it is propagated to the module

            # Host check result
            self.clear_logs()
            hcr = {
                "host_name": "srv001",

                "last_time_unreachable": 0,
                "last_problem_id": 0,
                "passive_check": False,
                "retry_interval": 1,
                "last_event_id": 0,
                "problem_has_been_acknowledged": False,
                "command_name": "pm-check_linux_host_alive",
                "last_state": "UP",
                "latency": 0.2317881584,
                "last_state_type": "HARD",
                "last_hard_state_change": 1444427108,
                "last_time_up": 0,
                "percent_state_change": 0.0,
                "state": "DOWN",
                "last_chk": 1444427104,
                "last_state_id": 0,
                "end_time": 0,
                "timeout": 0,
                "current_event_id": 10,
                "execution_time": 3.1496069431000002,
                "start_time": 0,
                "return_code": 2,
                "state_type": "SOFT",
                "output": "CRITICAL - Plugin timed out after 10 seconds",
                "in_checking": True,
                "early_timeout": 0,
                "in_scheduled_downtime": False,
                "attempt": 0,
                "state_type_id": 1,
                "acknowledgement_type": 1,
                "last_state_change": 1444427108.040841,
                "last_time_down": 1444427108,
                "instance_id": 0,
                "long_output": "",
                "current_problem_id": 0,
                "check_interval": 5,
                "state_id": 2,
                "has_been_checked": 1,
                "perf_data": "uptime=1200;rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
            }
            b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
            self._broker_daemon.manage_brok(b)
            self.show_logs()
            self.assert_log_count(2)
            self.assert_log_match("host check result: srv001", 0)
            self.assert_log_match("received host check result for an unknown host: srv001", 1)

            # Service check result
            self.clear_logs()
            scr = {
                "host_name": "srv001",
                "service_description": "ping",
                "command_name": "ping",

                "attempt": 1,
                "execution_time": 3.1496069431000002,
                "latency": 0.2317881584,
                "return_code": 2,
                "state": "OK",
                "state_type": "HARD",
                "state_id": 0,
                "state_type_id": 1,

                "output": "PING OK - Packet loss = 0%, RTA = 0.05 ms",
                "long_output": "Long output ...",
                "perf_data": "rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0",

                "passive_check": False,

                "problem_has_been_acknowledged": False,
                "acknowledgement_type": 1,
                "in_scheduled_downtime": False,

                "last_chk": 1473597375,
                "last_state_change": 1444427108.147903,
                "last_state_id": 0,
                "last_state": "UNKNOWN",
                "last_state_type": "HARD",
                "last_hard_state_change": 0.0,
                "last_time_unknown": 0,
                "last_time_unreachable": 0,
                "last_time_critical": 1473597376,
                "last_time_warning": 0,
                "last_time_ok": 0,

                "retry_interval": 2,
                "percent_state_change": 4.1,
                "check_interval": 5,

                "in_checking": False,
                "early_timeout": 0,
                "instance_id": "3ac88dd0c1c04b37a5d181622e93b5bc",
                "current_event_id": 1,
                "last_event_id": 0,
                "current_problem_id": 1,
                "last_problem_id": 0,
                "timeout": 0,
                "has_been_checked": 1,
                "start_time": 0,
                "end_time": 0
            }
            b = Brok({'data': scr, 'type': 'service_check_result'}, False)
            self._broker_daemon.manage_brok(b)
            self.show_logs()
            self.assert_log_count(2)
            self.assert_log_match("service check result: srv001/ping", 0)
            self.assert_log_match("received service check result for an unknown host", 1)

            # Initial host status
            self.clear_logs()
            hcr = {
                "host_name": "srv001",
            }
            b = Brok({'data': hcr, 'type': 'initial_host_status'}, False)
            self._broker_daemon.manage_brok(b)
            self.show_logs()
            # The module inner cache stored the host
            assert 'srv001' in my_module.hosts_cache
            assert my_module.hosts_cache['srv001'] == {'realm_name': 'All'}
            assert my_module.services_cache == {}

            # Initial service status
            self.clear_logs()
            hcr = {
                "host_name": "srv001",
                "service_description": "disks"
            }
            b = Brok({'data': hcr, 'type': 'initial_service_status'}, False)
            self._broker_daemon.manage_brok(b)
            self.show_logs()
            # The module inner cache stored the host
            assert 'srv001' in my_module.hosts_cache
            assert my_module.hosts_cache['srv001'] == {'realm_name': 'All'}
            assert 'srv001/disks' in my_module.services_cache
            assert my_module.services_cache['srv001/disks'] == {}

            # Now the host srv001 is known in the module, let's raise an host brok

            # Host check result
            self.clear_logs()
            hcr = {
                "host_name": "srv001",

                "last_time_unreachable": 0,
                "last_problem_id": 0,
                "passive_check": False,
                "retry_interval": 1,
                "last_event_id": 0,
                "problem_has_been_acknowledged": False,
                "command_name": "pm-check_linux_host_alive",
                "last_state": "UP",
                "latency": 0.2317881584,
                "last_state_type": "HARD",
                "last_hard_state_change": 1444427108,
                "last_time_up": 0,
                "percent_state_change": 0.0,
                "state": "DOWN",
                "last_chk": 1444427104,
                "last_state_id": 0,
                "end_time": 0,
                "timeout": 0,
                "current_event_id": 10,
                "execution_time": 3.1496069431000002,
                "start_time": 0,
                "return_code": 2,
                "state_type": "SOFT",
                "output": "CRITICAL - Plugin timed out after 10 seconds",
                "in_checking": True,
                "early_timeout": 0,
                "in_scheduled_downtime": False,
                "attempt": 0,
                "state_type_id": 1,
                "acknowledgement_type": 1,
                "last_state_change": 1444427108.040841,
                "last_time_down": 1444427108,
                "instance_id": 0,
                "long_output": "",
                "current_problem_id": 0,
                "check_interval": 5,
                "state_id": 2,
                "has_been_checked": 1,
                "perf_data": "uptime=1200 rta=0.049000ms;2.000000;3.000000;0.000000 pl=0%;50;80;0"
            }
            b = Brok({'data': hcr, 'type': 'host_check_result'}, False)
            self._broker_daemon.manage_brok(b)

            self.show_logs()
            self.assert_log_count(9)
            self.assert_log_match("host check result: srv001", 0)
            self.assert_log_match("service: host_check, metric: ", 1)
            self.assert_log_match("service: host_check, metric: ", 2)
            self.assert_log_match("service: host_check, metric: ", 3)
            self.assert_log_match("Metrics: host_check - ", 4)
            self.assert_log_match("Data: ", 5)
            self.assert_log_match("Flushing 1 metrics to Graphite/carbon", 6)
            self.assert_log_match("Flushing 1 metrics to InfluxDB", 7)
            self.assert_log_match("Storing 1 metrics to /tmp/alignak-metrics.log", 8)

            # Service check result
            self.clear_logs()
            scr = {
                "host_name": "srv001",
                "service_description": "disks",

                "last_time_unreachable": 0,
                "last_problem_id": 0,
                "passive_check": False,
                "retry_interval": 1,
                "last_event_id": 0,
                "problem_has_been_acknowledged": False,
                "command_name": "pm-check_linux_disks",
                "last_state": "UP",
                "latency": 0.2317881584,
                "last_state_type": "HARD",
                "last_hard_state_change": 1444427108,
                "last_time_up": 0,
                "percent_state_change": 0.0,
                "state": "OK",
                "last_chk": 1444427104,
                "last_state_id": 0,
                "end_time": 0,
                "timeout": 0,
                "current_event_id": 10,
                "execution_time": 3.1496069431000002,
                "start_time": 0,
                "return_code": 2,
                "state_type": "SOFT",
                "output": "DISK OK - free space: / 3326 MB (56%); / 15272 MB (77%);/boot 68 MB (69%);/home 69357 MB (27%);/var/log 819 MB (84%);",
                "in_checking": True,
                "early_timeout": 0,
                "in_scheduled_downtime": False,
                "attempt": 0,
                "state_type_id": 1,
                "acknowledgement_type": 1,
                "last_state_change": 1444427108.040841,
                "last_time_down": 1444427108,
                "instance_id": 0,
                "long_output": "",
                "current_problem_id": 0,
                "check_interval": 5,
                "state_id": 2,
                "has_been_checked": 1,
                "perf_data": "/=2643MB;5948;5958;0;5968 /boot=68MB;88;93;0;98 /home=69357MB;253404;253409;0;253414 /var/log=818MB;970;975;0;980"
            }
            b = Brok({'data': scr, 'type': 'service_check_result'}, False)
            self._broker_daemon.manage_brok(b)

            self.show_logs()
            self.assert_log_count(10)
            self.assert_log_match("service check result: srv001/disks", 0)
            self.assert_log_match(re.escape("service: disks, metric: "), 1)
            self.assert_log_match(re.escape("service: disks, metric: "), 2)
            self.assert_log_match(re.escape("service: disks, metric: "), 3)
            self.assert_log_match(re.escape("service: disks, metric: "), 4)
            self.assert_log_match(re.escape("Metrics: disks - "), 5)
            self.assert_log_match("Data: ", 6)
            self.assert_log_match("Flushing 1 metrics to Graphite/carbon", 7)
            self.assert_log_match("Flushing 1 metrics to InfluxDB", 8)
            self.assert_log_match("Storing 1 metrics to /tmp/alignak-metrics.log", 9)

            # Metrics count

            # File output
            assert os.path.exists('/tmp/alignak-metrics.log')
            with open('/tmp/alignak-metrics.log') as f:
                lines = f.readlines()
                first_line = False
                for line in lines:
                    line = line.strip()
                    assert 3 == len(line.split(';'))
                    print(line)
                    if not first_line:
                        first_line = True
                        metric = line.split(';')
                        assert metric[0] == metric[2]
                        assert metric[1] == 'connection-test'
                # Some metrics were stored!
                assert 33 == len(lines)
Example #19
0
    def test_module_manager(self):
        """
        Test if the module manager manages correctly all the modules
        :return:
        """
        self.print_header()
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        time_hacker.set_real_time()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'nrpe-booster',
            'module_types': 'nrpe-booster',
            'python_name': 'alignak_module_nrpe_booster'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('poller', None)

        # Clear logs
        self.clear_logs()

        # Load and initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        # Loading module logs
        self.assert_log_match(
            re.escape(
                "Importing Python module 'alignak_module_nrpe_booster' for nrpe-booster..."
            ), 0)
        self.assert_log_match(
            re.escape(
                "Module properties: {'daemons': ['poller'], 'phases': ['running'], "
                "'type': 'nrpe_poller', 'external': False, 'worker_capable': True}"
            ), 1)
        self.assert_log_match(
            re.escape(
                "Imported 'alignak_module_nrpe_booster' for nrpe-booster"), 2)
        self.assert_log_match(
            re.escape(
                "Loaded Python module 'alignak_module_nrpe_booster' (nrpe-booster)"
            ), 3)
        self.assert_log_match(
            re.escape(
                "Give an instance of alignak_module_nrpe_booster for alias: nrpe-booster"
            ), 4)

        # Starting internal module logs
        self.assert_log_match("Trying to initialize module: nrpe-booster", 5)
        self.assert_log_match("Initialization of the NRPE poller module", 6)

        my_module = self.modulemanager.instances[0]

        # Get list of not external modules
        self.assertListEqual([my_module],
                             self.modulemanager.get_internal_instances())
        for phase in ['configuration', 'late_configuration', 'retention']:
            self.assertListEqual(
                [], self.modulemanager.get_internal_instances(phase))
        for phase in ['running']:
            self.assertListEqual(
                [my_module], self.modulemanager.get_internal_instances(phase))

        # Get list of external modules
        self.assertListEqual([], self.modulemanager.get_external_instances())
        for phase in [
                'configuration', 'late_configuration', 'running', 'retention'
        ]:
            self.assertListEqual(
                [], self.modulemanager.get_external_instances(phase))

        # Clear logs
        self.clear_logs()

        # Nothing special ...
        self.modulemanager.check_alive_instances()

        # And we clear all now
        self.modulemanager.stop_all()
        # Stopping module logs

        self.assert_log_match("Ending the NRPE poller module", 0)
Example #20
0
    def test_modulemanager_several_modules(self):
        """ Module manager manages its modules

        Test if the module manager manages correctly all the modules

        Configured with several modules
        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct

        # for mod in self._arbiter.conf.modules:
        #     print (mod.__dict__)

        # Create an Alignak module
        mod = Module({
            'module_alias': 'mod-example',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'foo',
            'option2': 'bar',
            'option3': 1
        })
        mod2 = Module({
            'module_alias': 'mod-example-2',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'faa',
            'option2': 'bor',
            'option3': 1
        })

        # Force the daemon SyncManager to None for unit tests!
        self._broker_daemon.sync_manager = None
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)
        print("Modules: %s" % self._broker_daemon.modules)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        assert self.modules_manager.load_and_init([mod, mod2])
        print("I correctly loaded my modules: [%s]" %
              ','.join([inst.name for inst in self.modules_manager.instances]))
        self.show_logs()

        self.assert_any_log_match(
            re.escape(
                "Importing Python module 'alignak_module_example' for mod-example..."
            ))
        self.assert_any_log_match(
            re.escape("Imported 'alignak_module_example' for mod-example"))
        self.assert_any_log_match(
            re.escape(
                "Loaded Python module 'alignak_module_example' (mod-example)"))
        self.assert_any_log_match(
            re.escape(
                "Importing Python module 'alignak_module_example' for mod-example-2..."
            ))
        self.assert_any_log_match(
            re.escape("Imported 'alignak_module_example' for mod-example-2"))
        self.assert_any_log_match(
            re.escape(
                "Loaded Python module 'alignak_module_example' (mod-example-2)"
            ))
        self.assert_any_log_match(
            re.escape(
                "Give an instance of alignak_module_example for alias: mod-example"
            ))
        self.assert_any_log_match(re.escape("configuration, foo, bar, 1"))
        self.assert_any_log_match(
            re.escape(
                "Give an instance of alignak_module_example for alias: mod-example-2"
            ))
        self.assert_any_log_match(re.escape("configuration, faa, bor, 1"))
        # Loading module logs
        self.assert_any_log_match(
            re.escape(
                "Importing Python module 'alignak_module_example' for mod-example..."
            ))

        my_module = self.modules_manager.instances[0]
        my_module2 = self.modules_manager.instances[1]
        assert my_module.is_external
        assert my_module2.is_external

        # Get list of not external modules
        assert [] == self.modules_manager.get_internal_instances()
        for phase in [
                'configuration', 'late_configuration', 'running', 'retention'
        ]:
            assert [] == self.modules_manager.get_internal_instances(phase)

        # Get list of external modules
        assert [my_module,
                my_module2] == self.modules_manager.get_external_instances()
        for phase in [
                'configuration', 'late_configuration', 'running', 'retention'
        ]:
            assert [my_module, my_module2
                    ] == self.modules_manager.get_external_instances(phase)

        # Start external modules
        self.modules_manager.start_external_instances()
        self.modules_manager.start_external_instances()

        # Starting external module logs
        self.assert_any_log_match(
            re.escape("Starting external module mod-example"))
        self.assert_any_log_match(
            re.escape("Starting external process for module mod-example"))
        self.assert_any_log_match(
            re.escape("mod-example is now started (pid="))

        # Check alive
        assert my_module.process is not None
        assert my_module.process.is_alive()

        assert my_module2.process is not None
        assert my_module2.process.is_alive()

        # Kill the external module (normal stop is .stop_process)
        self.clear_logs()
        print("Killing a module")
        my_module.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape("Killing external module "))
        self.assert_any_log_match(re.escape("External module killed"))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        self.clear_logs()
        print("Killing another module")
        my_module2.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape("Killing external module "))
        self.assert_any_log_match(re.escape("External module killed"))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        # Nothing special ...
        self.clear_logs()
        self.modules_manager.check_alive_instances()

        # Try to restart the dead modules
        print("Trying to restart dead modules")
        # We lie on the last restart try time
        my_module.last_init_try = time.time()
        my_module2.last_init_try = time.time()
        self.modules_manager.try_to_restart_deads()
        self.show_logs()
        # In fact it's too early, so it won't do it

        # Here the module instances should still be dead
        assert not my_module.process.is_alive()
        assert not my_module2.process.is_alive()

        # We lie on the last restart try time
        my_module.last_init_try = 0
        my_module2.last_init_try = 0
        self.modules_manager.check_alive_instances()
        self.modules_manager.try_to_restart_deads()

        # Here the module instances should be alive again
        assert my_module.process.is_alive()
        assert my_module2.process.is_alive()

        # Kill the module again
        self.clear_logs()
        my_module.kill()
        self.show_logs()
        time.sleep(0.2)
        assert not my_module.process.is_alive()

        # And we clear all now
        self.modules_manager.stop_all()
        # Stopping module logs
        self.assert_any_log_match(re.escape("I'm stopping module "))
    def run_modulemanager(self, mod):
        # Force the daemon SyncManager to None for unit tests!
        self._broker_daemon.sync_manager = None

        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modules_manager.load_and_init([mod])

        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example"
        ))

        self.clear_logs()

        my_module = self.modules_manager.instances[0]
        assert my_module.is_external

        # Get list of not external modules
        assert [] == self.modules_manager.get_internal_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [] == self.modules_manager.get_internal_instances(phase)

        # Get list of external modules
        assert [my_module] == self.modules_manager.get_external_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [my_module] == self.modules_manager.get_external_instances(phase)

        # Start external modules
        self.modules_manager.start_external_instances()

        self.show_logs()

        # Starting external module logs
        idx = 0
        self.assert_log_match(re.escape(
            "Trying to initialize module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Test - Example in init"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Initialization of the example module"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Module mod-example is initialized"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external process for module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "mod-example is now started (pid="
        ), idx)
        idx += 1
        self.assert_log_count(7)

        # Check alive
        assert my_module.process is not None
        assert my_module.process.is_alive()

        self.clear_logs()
        # Check the alive module instances...
        self.modules_manager.check_alive_instances()
        # Try to restart the dead modules, if any
        self.modules_manager.try_to_restart_deads()
        self.assert_log_count(0)

        # Kill the external module (normal stop is .stop_process)
        self.clear_logs()
        my_module.kill()
        idx = 0
        self.assert_log_match(re.escape(
            "Killing external module "
        ), idx)
        idx += 1
        self.show_logs()

        # self.assert_log_match(re.escape(
        #     "mod-example is still living "
        # ), idx)
        # idx += 1
        # Specific case because sometimes the module is not killed within the expected 10s time
        normal_kill = True
        logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME)
        for handler in logger_.handlers:
            if not isinstance(handler, CollectorHandler):
                continue
            regex = re.compile('mod-example is still living')

            log_num = 0
            found = False
            for log in handler.collector:
                if idx == log_num:
                    if regex.search(log):
                        idx += 1
                        normal_kill = False
                        break
                log_num += 1
            break

        self.assert_log_match(re.escape(
            "External module killed"
        ), idx)
        idx += 1
        self.assert_log_count(idx)

        # The module is dead (not normally stopped...) so this module inner
        # process reference is not None!
        assert my_module.process is not None

        # Check the alive module instances...
        self.clear_logs()
        idx = 0
        self.modules_manager.check_alive_instances()
        self.show_logs()
        self.assert_log_match(re.escape(
            "The external module mod-example died unexpectedly!"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Setting the module mod-example to restart"
        ), idx)
        self.assert_log_count(2)
        idx += 1

        if normal_kill:
            # Try to restart the dead modules, if any
            # Indeed, it's too early, so it won't do it
            self.clear_logs()
            idx = 0
            print("try init: %d" % my_module.init_try)
            self.modules_manager.try_to_restart_deads()
            self.show_logs()

            self.assert_log_match(re.escape(
                "Trying to restart module: mod-example"
            ), idx)
            idx += 1
            self.assert_log_match(re.escape(
                "Too early to retry initialization, retry period is %d seconds" % MODULE_INIT_PERIOD
            ), idx)
            idx += 1
            self.assert_log_count(2)

            # Here the module instance is still dead
            assert not my_module.process.is_alive()

            # Wait for a minimum delay
            time.sleep(MODULE_INIT_PERIOD + 1)

        # my_module.last_init_try = -5
        self.clear_logs()
        self.modules_manager.check_alive_instances()
        self.show_logs()
        self.assert_log_count(0)

        # Try to restart the dead modules, if any
        # Now it is time...
        self.clear_logs()
        idx = 0
        self.modules_manager.try_to_restart_deads()
        self.show_logs()
        self.assert_log_match(re.escape(
            "Trying to restart module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Trying to initialize module: mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Test - Example in init"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Initialization of the example module"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Module mod-example is initialized"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Restarting mod-example..."
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Starting external process for module mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "mod-example is now started (pid="
        ), idx)
        idx += 1
        self.assert_log_count(8)

        # Here the module instance should be alive again
        assert my_module.process.is_alive()

        # No more module to restart...
        assert [] == self.modules_manager.to_restart

        # And we clear all now
        self.clear_logs()
        idx = 0
        self.modules_manager.stop_all()
        self.show_logs()
        self.assert_log_match(re.escape(
            "Shutting down modules..."
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Request external process to stop for mod-example"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "I'm stopping module 'mod-example'"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "Killing external module "
        ), idx)
        idx += 1

        # Specific case because sometimes the module is not killed within the expected 10s time
        logger_ = logging.getLogger(ALIGNAK_LOGGER_NAME)
        for handler in logger_.handlers:
            if not isinstance(handler, CollectorHandler):
                continue
            regex = re.compile('mod-example is still living')

            log_num = 0
            found = False
            for log in handler.collector:
                if idx == log_num:
                    if regex.search(log):
                        idx += 1
                        break
                log_num += 1
            break

        self.assert_log_match(re.escape(
            "External module killed"
        ), idx)
        idx += 1
        self.assert_log_match(re.escape(
            "External process stopped."
        ), idx)
        idx += 1
Example #22
0
class TestModuleNrpeBooster(AlignakTest):
    """
    This class contains the tests for the module
    """
    def test_module_loading(self):
        """
        Alignak module loading

        :return:
        """
        self.print_header()
        self.setup_with_file('./cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)
        self.show_configuration_logs()

        # No arbiter modules created
        modules = [m.module_alias for m in self.arbiter.myself.modules]
        self.assertListEqual(modules, [])

        # The only existing broker module is logs declared in the configuration
        modules = [
            m.module_alias for m in self.brokers['broker-master'].modules
        ]
        self.assertListEqual(modules, [])

        # No poller module
        modules = [
            m.module_alias for m in self.pollers['poller-master'].modules
        ]
        self.assertListEqual(modules, ['nrpe-booster'])

        # No receiver module
        modules = [
            m.module_alias for m in self.receivers['receiver-master'].modules
        ]
        self.assertListEqual(modules, [])

        # No reactionner module
        modules = [
            m.module_alias
            for m in self.reactionners['reactionner-master'].modules
        ]
        self.assertListEqual(modules, [])

        # No scheduler modules
        modules = [
            m.module_alias for m in self.schedulers['scheduler-master'].modules
        ]
        self.assertListEqual(modules, [])

    def test_module_manager(self):
        """
        Test if the module manager manages correctly all the modules
        :return:
        """
        self.print_header()
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        time_hacker.set_real_time()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'nrpe-booster',
            'module_types': 'nrpe-booster',
            'python_name': 'alignak_module_nrpe_booster'
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('poller', None)

        # Clear logs
        self.clear_logs()

        # Load and initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        # Loading module logs
        self.assert_log_match(
            re.escape(
                "Importing Python module 'alignak_module_nrpe_booster' for nrpe-booster..."
            ), 0)
        self.assert_log_match(
            re.escape(
                "Module properties: {'daemons': ['poller'], 'phases': ['running'], "
                "'type': 'nrpe_poller', 'external': False, 'worker_capable': True}"
            ), 1)
        self.assert_log_match(
            re.escape(
                "Imported 'alignak_module_nrpe_booster' for nrpe-booster"), 2)
        self.assert_log_match(
            re.escape(
                "Loaded Python module 'alignak_module_nrpe_booster' (nrpe-booster)"
            ), 3)
        self.assert_log_match(
            re.escape(
                "Give an instance of alignak_module_nrpe_booster for alias: nrpe-booster"
            ), 4)

        # Starting internal module logs
        self.assert_log_match("Trying to initialize module: nrpe-booster", 5)
        self.assert_log_match("Initialization of the NRPE poller module", 6)

        my_module = self.modulemanager.instances[0]

        # Get list of not external modules
        self.assertListEqual([my_module],
                             self.modulemanager.get_internal_instances())
        for phase in ['configuration', 'late_configuration', 'retention']:
            self.assertListEqual(
                [], self.modulemanager.get_internal_instances(phase))
        for phase in ['running']:
            self.assertListEqual(
                [my_module], self.modulemanager.get_internal_instances(phase))

        # Get list of external modules
        self.assertListEqual([], self.modulemanager.get_external_instances())
        for phase in [
                'configuration', 'late_configuration', 'running', 'retention'
        ]:
            self.assertListEqual(
                [], self.modulemanager.get_external_instances(phase))

        # Clear logs
        self.clear_logs()

        # Nothing special ...
        self.modulemanager.check_alive_instances()

        # And we clear all now
        self.modulemanager.stop_all()
        # Stopping module logs

        self.assert_log_match("Ending the NRPE poller module", 0)

    def test_module_start_default(self):
        """
        Test the module initialization function, no parameters, using default
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Default initialization
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'nrpe-booster',
            'module_types': 'nrpe-booster',
            'python_name': 'alignak_module_nrpe_booster'
        })

        instance = alignak_module_nrpe_booster.get_instance(mod)
        self.assertIsInstance(instance, BaseModule)

        self.assert_log_match(
            re.escape("Give an instance of alignak_module_nrpe_booster for "
                      "alias: nrpe-booster"), 0)
Example #23
0
class TestModuleManager(AlignakTest):
    def setUp(self):
        self.setup_with_file([])
        time_hacker.set_real_time()

    # Try to see if the module manager can manage modules
    def test_modulemanager(self):
        mod = Module({'module_name': 'mod-example', 'module_type': 'example'})
        path = sys.modules['alignak'].__path__[0] + '/modules'
        self.modulemanager = ModulesManager('broker', path, [])
        self.modulemanager.set_modules([mod])
        self.modulemanager.load_and_init()
        # And start external ones, like our LiveStatus
        self.modulemanager.start_external_instances()
        print "I correctly loaded the modules: %s " % ([inst.get_name() for inst in self.modulemanager.instances])

        print "*** First kill ****"
        # Now I will try to kill the livestatus module
        ls = self.modulemanager.instances[0]
        ls._BaseModule__kill()

        time.sleep(1)
        print "Check alive?"
        print "Is alive?", ls.process.is_alive()
        # Should be dead
        self.assertFalse(ls.process.is_alive())
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()

        # In fact it's too early, so it won't do it

        # Here the inst should still be dead
        print "Is alive?", ls.process.is_alive()
        self.assertFalse(ls.process.is_alive())

        # So we lie
        ls.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()

        # In fact it's too early, so it won't do it

        # Here the inst should be alive again
        print "Is alive?", ls.process.is_alive()
        self.assertTrue(ls.process.is_alive())

        # should be nothing more in to_restart of
        # the module manager
        self.assertEqual([], self.modulemanager.to_restart)

        # Now we look for time restart so we kill it again
        ls._BaseModule__kill()
        time.sleep(1)
        self.assertFalse(ls.process.is_alive())

        # Should be too early
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()
        print "Is alive or not", ls.process.is_alive()
        self.assertFalse(ls.process.is_alive())
        # We lie for the test again
        ls.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()

        # Here the inst should be alive again
        print "Is alive?", ls.process.is_alive()
        self.assertTrue(ls.process.is_alive())

        # And we clear all now
        print "Ask to die"
        self.modulemanager.stop_all()
        print "Died"
Example #24
0
    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
Example #25
0
    def test_module_zzz_command_unauthorized(self):
        """ Test the WS /command endpoint - unauthorized access mode
        :return:
        """
        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend - not configured
            'alignak_backend': '',
            'username': '',
            'password': '',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Disable authorization
            'authorization': '0'
        })

        # Create a receiver daemon
        args = {'env_file': '', 'daemon_name': 'receiver-master'}
        self._receiver_daemon = Receiver(**args)

        # Create the modules manager for the daemon
        self.modulemanager = ModulesManager(self._receiver_daemon)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        session = requests.Session()

        # You must have parameters when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {}
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ERR')
        self.assertEqual(result['_error'],
                         'You must POST parameters on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # You must have a command parameter when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {
            # "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ERR')
        # Result error message
        self.assertEqual(result['_error'], 'Missing command parameter')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 1)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'], 'COMMAND;test_host;abc;1')

        # Request to execute an external command with timestamp - bad value
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "timestamp": "text",
            "element": "test_host",
            "parameters": "abc;1"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result, {
            '_status': 'ERR',
            '_error': 'Timestamp must be an integer value'
        })
        self.assertEqual(my_module.received_commands, 1)

        # Request to execute an external command with timestamp
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "timestamp": "1234",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 2)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(
            result['_command'],
            '[1234] COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 3)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element":
            "test_host/test_service",  # Accept / as an host/service separator
            "parameters": "1;abc;2"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 4)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "parameters": "1;abc;2"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 5)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_command'],
                         'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "user": "******",
            "parameters": "1;abc;2"
        }
        response = session.post(self.ws_endpoint + '/command',
                                json=data,
                                headers=headers)
        self.assertEqual(my_module.received_commands, 6)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(
            result['_command'],
            'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2')

        self.modulemanager.stop_all()
    def test_modulemanager_several_modules(self):
        """ Module manager manages its modules

        Test if the module manager manages correctly all the modules

        Configured with several modules
        :return:
        """
        self.setup_with_file('cfg/cfg_default_with_modules.cfg',
                             'cfg/default_with_modules/alignak.ini')
        assert self.conf_is_correct

        # for mod in self._arbiter.conf.modules:
        #     print (mod.__dict__)

        # Create an Alignak module
        mod = Module({
            'module_alias': 'mod-example',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'foo',
            'option2': 'bar',
            'option3': 1
        })
        mod2 = Module({
            'module_alias': 'mod-example-2',
            'module_types': 'example',
            'python_name': 'alignak_module_example',
            'option1': 'faa',
            'option2': 'bor',
            'option3': 1
        })

        # Force the daemon SyncManager to None for unit tests!
        self._broker_daemon.sync_manager = None
        # Create the modules manager for a daemon type
        self.modules_manager = ModulesManager(self._broker_daemon)
        print("Modules: %s" % self._broker_daemon.modules)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        assert self.modules_manager.load_and_init([mod, mod2])
        print("I correctly loaded my modules: [%s]" % ','.join([inst.name for inst in
                                                                self.modules_manager.instances]))
        self.show_logs()

        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_example' (mod-example)"
        ))
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example-2..."
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_example' for mod-example-2"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_example' (mod-example-2)"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "configuration, foo, bar, 1"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_example for alias: mod-example-2"
        ))
        self.assert_any_log_match(re.escape(
            "configuration, faa, bor, 1"
        ))
        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_example' for mod-example..."
        ))

        my_module = self.modules_manager.instances[0]
        my_module2 = self.modules_manager.instances[1]
        assert my_module.is_external
        assert my_module2.is_external

        # Get list of not external modules
        assert [] == self.modules_manager.get_internal_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [] == self.modules_manager.get_internal_instances(phase)

        # Get list of external modules
        assert [my_module, my_module2] == self.modules_manager.get_external_instances()
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            assert [my_module, my_module2] == self.modules_manager.get_external_instances(phase)

        # Start external modules
        self.modules_manager.start_external_instances()
        self.modules_manager.start_external_instances()

        # Starting external module logs
        self.assert_any_log_match(re.escape(
            "Starting external module mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "Starting external process for module mod-example"
        ))
        self.assert_any_log_match(re.escape(
            "mod-example is now started (pid="
        ))

        # Check alive
        assert my_module.process is not None
        assert my_module.process.is_alive()

        assert my_module2.process is not None
        assert my_module2.process.is_alive()

        # Kill the external module (normal stop is .stop_process)
        self.clear_logs()
        print("Killing a module")
        my_module.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "Killing external module "
        ))
        self.assert_any_log_match(re.escape(
            "External module killed"
        ))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        self.clear_logs()
        print("Killing another module")
        my_module2.kill()
        time.sleep(0.1)
        self.show_logs()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "Killing external module "
        ))
        self.assert_any_log_match(re.escape(
            "External module killed"
        ))
        # Should be dead (not normally stopped...) but we still know a process for this module!
        assert my_module.process is not None

        # Nothing special ...
        self.clear_logs()
        self.modules_manager.check_alive_instances()

        # Try to restart the dead modules
        print("Trying to restart dead modules")
        # We lie on the last restart try time
        my_module.last_init_try = time.time()
        my_module2.last_init_try = time.time()
        self.modules_manager.try_to_restart_deads()
        self.show_logs()
        # In fact it's too early, so it won't do it

        # Here the module instances should still be dead
        assert not my_module.process.is_alive()
        assert not my_module2.process.is_alive()

        # We lie on the last restart try time
        my_module.last_init_try = 0
        my_module2.last_init_try = 0
        self.modules_manager.check_alive_instances()
        self.modules_manager.try_to_restart_deads()

        # Here the module instances should be alive again
        assert my_module.process.is_alive()
        assert my_module2.process.is_alive()

        # Kill the module again
        self.clear_logs()
        my_module.kill()
        self.show_logs()
        time.sleep(0.2)
        assert not my_module.process.is_alive()

        # And we clear all now
        self.modules_manager.stop_all()
        # Stopping module logs
        self.assert_any_log_match(re.escape(
            "I'm stopping module "
        ))
Example #27
0
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()
Example #28
0
    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"
Example #29
0
    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()
Example #30
0
    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()
Example #31
0
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()
Example #32
0
    def test_module_zzz_host_get(self):
        """Test the module /host API - host creation and get information
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Alignak backend
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Do not set a timestamp in the built external commands
            'set_timestamp': '0',
            'give_result': '1',
            'give_feedback': '1',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Allow host/service creation
            'allow_host_creation': '1',
            'allow_service_creation': '1',
            # Errors for unknown host/service
            'ignore_unknown_host': '0',
            'ignore_unknown_service': '0',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match(
            "Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Do not allow GET request on /host - not yet authorized!
        response = requests.get('http://127.0.0.1:8888/host')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        response = session.post('http://127.0.0.1:8888/login',
                                json=params,
                                headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # -----
        # Get a non-existing host - 1st: use parameters in the request
        response = session.get('http://127.0.0.1:8888/host',
                               auth=self.auth,
                               params={'name': 'new_host_2'})
        result = response.json()
        self.assertEqual(
            result, {
                u'_status': u'ERR',
                u'_result': [],
                u'_issues': ["Requested host 'new_host_2' does not exist"]
            })

        # Get a non-existing host - 2nd: use host name in the URI
        response = session.get('http://127.0.0.1:8888/host/new_host_2',
                               auth=self.auth)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status': u'ERR',
                u'_result': [],
                u'_issues': ["Requested host 'new_host_2' does not exist"]
            })

        # -----
        # Request to create an host - no provided data (default)
        headers = {'Content-Type': 'application/json'}
        data = {
            "name": "new_host_0",
        }
        self.assertEqual(my_module.received_commands, 0)
        response = session.patch('http://127.0.0.1:8888/host',
                                 json=data,
                                 headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(
            result, {
                u'_status':
                u'OK',
                u'_result': [
                    u'new_host_0 is alive :)',
                    u"Requested host 'new_host_0' does not exist.",
                    u"Requested host 'new_host_0' created."
                ],
                u'_feedback': {
                    u'name': u'new_host_0'
                }
            })
        # Host created with default check_command and in default user realm

        # -----
        # Get new host to confirm creation - 1st: use parameters in the request
        response = session.get('http://127.0.0.1:8888/host',
                               auth=self.auth,
                               params={'name': 'new_host_0'})
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertIsNot(result['_result'], {})
        self.assertEqual(result['_result'][0]['name'], 'new_host_0')

        # Get new host to confirm creation - 2nd: use host name in the URI
        response = session.get('http://127.0.0.1:8888/host/new_host_0',
                               auth=self.auth)
        result = response.json()
        from pprint import pprint
        pprint(result['_result'])
        # [{u'2d_coords': u'',
        # u'3d_coords': u'',
        # u'_created': u'Thu, 01 Jun 2017 10:58:30 GMT',
        # u'_etag': u'691c3f4a7cc8996c1d047932421759c020d00857',
        # u'_id': u'592ff35606fd4b7eec395625',
        # u'_is_template': False,
        # u'_links': {u'self': {u'href': u'host/592ff35606fd4b7eec395625',
        #                       u'title': u'Host'}},
        # u'_overall_state_id': 3,
        # u'_realm': {u'_all_children': [],
        #             u'_children': [],
        #             u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #             u'_etag': u'26b3830c017b4fca8553365246f21267aece46a7',
        #             u'_id': u'592ff35006fd4b7eec3955eb',
        #             u'_level': 0,
        #             u'_parent': None,
        #             u'_tree_parents': [],
        #             u'_updated': u'Thu, 01 Jun 2017 10:58:27 GMT',
        #             u'alias': u'',
        #             u'default': True,
        #             u'definition_order': 100,
        #             u'global_critical_threshold': 5,
        #             u'global_warning_threshold': 3,
        #             u'hosts_critical_threshold': 5,
        #             u'hosts_warning_threshold': 3,
        #             u'imported_from': u'unknown',
        #             u'name': u'All',
        #             u'notes': u'',
        #             u'services_critical_threshold': 5,
        #             u'services_warning_threshold': 3},
        # u'_sub_realm': True,
        # u'_template_fields': {},
        # u'_templates': [],
        # u'_templates_with_services': True,
        # u'_updated': u'Thu, 01 Jun 2017 10:58:30 GMT',
        # u'action_url': u'',
        # u'active_checks_enabled': True,
        # u'address': u'',
        # u'address6': u'',
        # u'alias': u'',
        # u'business_impact': 2,
        # u'business_impact_modulations': [],
        # u'business_rule_downtime_as_ack': False,
        # u'business_rule_host_notification_options': [u'd', u'u', u'r', u'f', u's'],
        # u'business_rule_output_template': u'',
        # u'business_rule_service_notification_options': [u'w',
        #                                                 u'u',
        #                                                 u'c',
        #                                                 u'r',
        #                                                 u'f',
        #                                                 u's'],
        # u'business_rule_smart_notifications': False,
        # u'check_command': {u'_created': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #                    u'_etag': u'356d02479ca7dbebe85e22b9b43e95dc9d5d037c',
        #                    u'_id': u'592ff35006fd4b7eec3955f1',
        #                    u'_realm': u'592ff35006fd4b7eec3955eb',
        #                    u'_sub_realm': True,
        #                    u'_updated': u'Thu, 01 Jun 2017 10:58:24 GMT',
        #                    u'alias': u'Host/service is always UP/OK',
        #                    u'command_line': u'_internal_host_up',
        #                    u'definition_order': 100,
        #                    u'enable_environment_macros': False,
        #                    u'imported_from': u'unknown',
        #                    u'module_type': u'fork',
        #                    u'name': u'_internal_host_up',
        #                    u'notes': u'',
        #                    u'poller_tag': u'',
        #                    u'reactionner_tag': u'',
        #                    u'timeout': -1},
        # u'check_command_args': u'',
        # u'check_freshness': False,
        # u'check_interval': 5,
        # u'checkmodulations': [],
        # u'custom_views': [],
        # u'customs': {},
        # u'definition_order': 100,
        # u'display_name': u'',
        # u'escalations': [],
        # u'event_handler': None,
        # u'event_handler_args': u'',
        # u'event_handler_enabled': False,
        # u'failure_prediction_enabled': False,
        # u'first_notification_delay': 0,
        # u'flap_detection_enabled': True,
        # u'flap_detection_options': [u'o', u'd', u'x'],
        # u'freshness_state': u'x',
        # u'freshness_threshold': 0,
        # u'high_flap_threshold': 50,
        # u'icon_image': u'',
        # u'icon_image_alt': u'',
        # u'icon_set': u'',
        # u'imported_from': u'unknown',
        # u'initial_state': u'x',
        # u'labels': [],
        # u'location': {u'coordinates': [48.858293, 2.294601], u'type': u'Point'},
        # u'low_flap_threshold': 25,
        # u'ls_acknowledged': False,
        # u'ls_acknowledgement_type': 1,
        # u'ls_attempt': 0,
        # u'ls_current_attempt': 0,
        # u'ls_downtimed': False,
        # u'ls_execution_time': 0.0,
        # u'ls_grafana': False,
        # u'ls_grafana_panelid': 0,
        # u'ls_impact': False,
        # u'ls_last_check': 0,
        # u'ls_last_hard_state_changed': 0,
        # u'ls_last_notification': 0,
        # u'ls_last_state': u'OK',
        # u'ls_last_state_changed': 0,
        # u'ls_last_state_type': u'HARD',
        # u'ls_last_time_down': 0,
        # u'ls_last_time_unknown': 0,
        # u'ls_last_time_unreachable': 0,
        # u'ls_last_time_up': 0,
        # u'ls_latency': 0.0,
        # u'ls_long_output': u'',
        # u'ls_max_attempts': 0,
        # u'ls_next_check': 0,
        # u'ls_output': u'',
        # u'ls_passive_check': False,
        # u'ls_perf_data': u'',
        # u'ls_state': u'UNREACHABLE',
        # u'ls_state_id': 3,
        # u'ls_state_type': u'HARD',
        # u'macromodulations': [],
        # u'max_check_attempts': 1,
        # u'name': u'new_host_0',
        # u'notes': u'',
        # u'notes_url': u'',
        # u'notification_interval': 60,
        # u'notification_options': [u'd', u'x', u'r', u'f', u's'],
        # u'notifications_enabled': True,
        # u'obsess_over_host': False,
        # u'parents': [],
        # u'passive_checks_enabled': True,
        # u'poller_tag': u'',
        # u'process_perf_data': True,
        # u'reactionner_tag': u'',
        # u'resultmodulations': [],
        # u'retry_interval': 0,
        # u'service_excludes': [],
        # u'service_includes': [],
        # u'service_overrides': [],
        # u'snapshot_criteria': [u'd', u'x'],
        # u'snapshot_enabled': False,
        # u'snapshot_interval': 5,
        # u'stalking_options': [],
        # u'statusmap_image': u'',
        # u'tags': [],
        # u'time_to_orphanage': 300,
        # u'trending_policies': [],
        # u'trigger_broker_raise_enabled': False,
        # u'trigger_name': u'',
        # u'usergroups': [],
        # u'users': [],
        # u'vrml_image': u''}]
        #
        self.assertEqual(result['_status'], 'OK')
        self.assertIsNot(result['_result'], {})
        self.assertEqual(result['_result'][0]['name'], 'new_host_0')

        # -----
        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

        self.modulemanager.stop_all()
    def _get_history(self, username, password):

        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Alignak backend URL
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Activate CherryPy file logs
            'log_access': '/tmp/alignak-module-ws-access.log',
            'log_error': '/tmp/alignak-module-ws-error.log',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        time.sleep(1)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # ---
        # Prepare the backend content...
        self.endpoint = 'http://127.0.0.1:5000'

        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # get token
        response = requests.post(self.endpoint + '/login', json=params, headers=headers)
        resp = response.json()
        self.token = resp['token']
        self.auth = requests.auth.HTTPBasicAuth(self.token, '')

        # Get default realm
        response = requests.get(self.endpoint + '/realm', auth=self.auth)
        resp = response.json()
        self.realm_all = resp['_items'][0]['_id']
        # ---

        # -------------------------------------------
        # Add a check result for an host
        data = {
            "last_check": 1496332753,
            "host": self.rh[0]['_id'],
            "service": None,
            'acknowledged': False,
            'state_id': 0,
            'state': 'UP',
            'state_type': 'HARD',
            'last_state_id': 0,
            'last_state': 'UP',
            'last_state_type': 'HARD',
            'state_changed': False,
            'latency': 0,
            'execution_time': 0.12,
            'output': 'Check output',
            'long_output': 'Check long_output',
            'perf_data': 'perf_data',
            "_realm": self.realm_all
        }
        response = requests.post(
            self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth
        )
        resp = response.json()
        self.assertEqual(resp['_status'], 'OK')

        # -------------------------------------------
        # Add a check result for a service
        data = {
            "last_check": 1496332754,
            "host": self.rh[0]['_id'],
            "service": self.rs[0]['_id'],
            'acknowledged': False,
            'state_id': 0,
            'state': 'UP',
            'state_type': 'HARD',
            'last_state_id': 0,
            'last_state': 'UP',
            'last_state_type': 'HARD',
            'state_changed': False,
            'latency': 0,
            'execution_time': 0.12,
            'output': 'Check output',
            'long_output': 'Check long_output',
            'perf_data': 'perf_data',
            "_realm": self.realm_all
        }
        response = requests.post(
            self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth
        )
        resp = response.json()
        self.assertEqual(resp['_status'], 'OK')
        # Add an history event
        data = {
            "host_name": "chazay",
            "service_name": "Processus",
            "user_name": "Alignak",
            "type": "check.result",
            "message": "OK[HARD] (False,False): All is ok",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        time.sleep(1)
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)

        # Add an history event
        time.sleep(1)
        data = {
            "host_name": "denice",
            "service_name": "Zombies",
            "user_name": "Alignak",
            "type": "check.result",
            "message": "OK[HARD] (False,False): All is ok",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)

        # Add an history event
        time.sleep(1)
        data = {
            "host_name": "denice",
            "user_name": "Me",
            "type": "monitoring.alert",
            "message": "HOST ALERT ....",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)
        # ---

        # ---
        # Get history to confirm that backend is ready
        # ---
        response = requests.get(self.endpoint + '/history', auth=self.auth,
                                params={"sort": "-_id", "max_results": 25, "page": 1, 'embedded': json.dumps({"logcheckresult": 1})})
        resp = response.json()
        pprint(resp['_items'])
        self.assertEqual(len(resp['_items']), 5)

        # Backend real history
        # The commented fields are the one existing in the backend but filtered by the WS
        backend_real_history = [
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:16 GMT',
                # u'_etag': u'9f07c7285b37bb3d336a96ede3d3fd2a774c4c4c',
                u'_id': u'593039d406fd4b3bf0e27d9f',
                # u'_links': {u'self': {u'href': u'history/593039d406fd4b3bf0e27d9f',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:16 GMT',
                u'host_name': u'denice',
                u'message': u'HOST ALERT ....',
                u'type': u'monitoring.alert',
                u'user_name': u'Me'
            },
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:15 GMT',
                # u'_etag': u'24cd486a1a28859a0177fbe15d1ead61f78f7b2c',
                u'_id': u'593039d306fd4b3bf0e27d9e',
                # u'_links': {u'self': {u'href': u'history/593039d306fd4b3bf0e27d9e',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:15 GMT',
                u'host_name': u'denice',
                u'message': u'OK[HARD] (False,False): All is ok',
                u'service_name': u'Zombies',
                u'type': u'check.result',
                u'user_name': u'Alignak'
            },
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:14 GMT',
                # u'_etag': u'4c4ee43a4fac0b91dcfddb011619007dedb1cd95',
                u'_id': u'593039d206fd4b3bf0e27d9d',
                # u'_links': {u'self': {u'href': u'history/593039d206fd4b3bf0e27d9d',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:14 GMT',
                u'host_name': u'chazay',
                u'message': u'OK[HARD] (False,False): All is ok',
                u'service_name': u'Processus',
                u'type': u'check.result',
                u'user_name': u'Alignak'
            },
            {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'_etag': u'76dd35f575244848dd41f67ad3109cf6f1f9a33c',
             u'_id': u'593039d106fd4b3bf0e27d9c',
             # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9c',
             #                       u'title': u'History'}},
             # u'_realm': u'593039cc06fd4b3bf0e27d88',
             # u'_sub_realm': True,
             # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'host': u'593039cc06fd4b3bf0e27d90',
             u'host_name': u'srv001',
             u'logcheckresult': {
                 u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 # u'_etag': u'10a3935b1158fe4c8f62962a14b1050fef32df4b',
                 # u'_id': u'593039d106fd4b3bf0e27d9b',
                 # u'_realm': u'593039cc06fd4b3bf0e27d88',
                 # u'_sub_realm': True,
                 # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 u'acknowledged': False,
                 u'acknowledgement_type': 1,
                 u'downtimed': False,
                 u'execution_time': 0.12,
                 # u'host': u'593039cc06fd4b3bf0e27d90',
                 # u'host_name': u'srv001',
                 u'last_check': 1496332753,
                 u'last_state': u'UP',
                 u'last_state_changed': 0,
                 u'last_state_id': 0,
                 u'last_state_type': u'HARD',
                 u'latency': 0.0,
                 u'long_output': u'Check long_output',
                 u'output': u'Check output',
                 u'passive_check': False,
                 u'perf_data': u'perf_data',
                 # u'service': u'593039cf06fd4b3bf0e27d98',
                 # u'service_name': u'ping',
                 u'state': u'UP',
                 u'state_changed': False,
                 u'state_id': 0,
                 u'state_type': u'HARD'
             },
             u'message': u'UP[HARD] (False/False): Check output',
             # u'service': u'593039cf06fd4b3bf0e27d98',
             u'service_name': u'ping',
             u'type': u'check.result',
             # u'user': None,
             u'user_name': u'Alignak'
             },
            {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'_etag': u'c3cd29587ad328325dc48af677b3a36157361a84',
             u'_id': u'593039d106fd4b3bf0e27d9a',
             # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9a',
             #                       u'title': u'History'}},
             # u'_realm': u'593039cc06fd4b3bf0e27d88',
             # u'_sub_realm': True,
             # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'host': u'593039cc06fd4b3bf0e27d90',
             u'host_name': u'srv001',
             u'logcheckresult': {
                 u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 # u'_etag': u'0ea4c16f1e651a02772aa2bfa83070b47e7f6531',
                 # u'_id': u'593039d106fd4b3bf0e27d99',
                 # u'_realm': u'593039cc06fd4b3bf0e27d88',
                 # u'_sub_realm': True,
                 # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 u'acknowledged': False,
                 u'acknowledgement_type': 1,
                 u'downtimed': False,
                 u'execution_time': 0.12,
                 # u'host': u'593039cc06fd4b3bf0e27d90',
                 # u'host_name': u'srv001',
                 u'last_check': 1496332754,
                 u'last_state': u'UP',
                 u'last_state_changed': 0,
                 u'last_state_id': 0,
                 u'last_state_type': u'HARD',
                 u'latency': 0.0,
                 u'long_output': u'Check long_output',
                 u'output': u'Check output',
                 u'passive_check': False,
                 u'perf_data': u'perf_data',
                 # u'service': None,
                 # u'service_name': u'',
                 u'state': u'UP',
                 u'state_changed': False,
                 u'state_id': 0,
                 u'state_type': u'HARD'
             },
             u'message': u'UP[HARD] (False/False): Check output',
             # u'service': None,
             u'service_name': u'',
             u'type': u'check.result',
             # u'user': None,
             u'user_name': u'Alignak'
             }
        ]
        # ---

        # ---
        # # Directly call the module function
        # search = {
        #     'page': 1,
        #     'max_results': 25
        # }
        # result = my_module.getBackendHistory(search)
        # print(result)
        # print("Page: %d, got: %d items" % (search["page"], len(result['items'])))
        # for item in result['items']:
        #     print(item)
        # assert len(result['items']) == 5

        # ---
        # Do not allow GET request on /alignak_logs - not yet authorized!
        response = requests.get('http://127.0.0.1:8888/alignak_logs')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': username, 'password': password}
        response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # ---
        # Get the alignak default history
        response = session.get('http://127.0.0.1:8888/alignak_logs')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        # Remove fields that will obviously be different!
        for item in result['items']:
            del(item['_id'])
            del(item['_created'])
            # if 'logcheckresult' in item:
            #     del (item['logcheckresult']['_created'])
        for item in backend_real_history:
            del(item['_id'])
            del(item['_created'])
            if 'logcheckresult' in item:
                del (item['logcheckresult']['_created'])
        self.assertEqual(len(result['items']), 5)
        # Too complex comparison!!!
        # self.assertEqual(backend_real_history, result['items'])
        # assert cmp(backend_real_history, result['items']) == 0
        # ---

        # ---
        # Get the alignak default history, filter to get only check.result
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:check.result')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 4)
        # ---

        # ---
        # Get the alignak default history, filter to get only for a user
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Alignak')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 4)
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Me')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # ---

        # ---
        # Get the alignak default history, filter to get only for an host
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 1)
        # Implicit host_name
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 1)
        # Unknown search field
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=name:chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        # All history items because name is not aknown search field! So we get all items...
        self.assertEqual(len(result['items']), 5)

        # Some other hosts...
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 2)
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:srv001')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 2)

        # Several hosts...
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice host_name:srv001')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 4)   # 2 for each host

        # Not an host...
        # TODO: looks that ths criteria is not correctly implemented :(
        # response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!denice')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # self.assertEqual(len(result['items']), 3)
        # ---

        # ---
        # Get the alignak default history, NOT for an host
        # todo: temporarily skipped
        # response = requests.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!Chazay')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # for item in result['items']:
        #     print(item)
        # self.assertEqual(len(result['items']), 2)
        # ---

        # ---
        # Get the alignak default history, only for a service
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=service_name:Processus')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # ---

        # ---
        # Get the alignak default history, for an host and a service
        # todo multi search query to be improved!
        # response = session.get('http://127.0.0.1:8888/alignak_logs?search="host_name:chazay service_name=Processus"')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # for item in result['items']:
        #     print(item)
        # self.assertEqual(len(result['items']), 3)
        # ---

        # ---
        # Get the alignak default history, unknown event type
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:XXX')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        # ---

        # ---
        # Get the alignak default history, page count
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=2&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=3&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=4&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # Over the limits !
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=5&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=50&count=50')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        # ---

        # ---
        # Get the alignak history, page count greater than the number of items
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=25')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        pprint(result)
        self.assertEqual(len(result['items']), 5)   # Got 5 items
        self.assertEqual(result['_meta']['max_results'], 25)
        self.assertEqual(result['_meta']['page'], 1)
        self.assertEqual(result['_meta']['total'], 5)

        response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=50')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        pprint(result)
        self.assertEqual(len(result['items']), 5)   # Got 5 items
        self.assertEqual(result['_meta']['max_results'], 50)
        self.assertEqual(result['_meta']['page'], 1)
        self.assertEqual(result['_meta']['total'], 5)

        # ---

        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')
Example #34
0
    def test_module_zzz_run(self):
        """
        Test the module API
        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # Get the module API list and request on each endpoint
        response = requests.get('http://127.0.0.1:8888')
        api_list = response.json()
        for endpoint in api_list:
            print("Trying %s" % (endpoint))
            response = requests.get('http://127.0.0.1:8888/' + endpoint)
            print("Response %d: %s" % (response.status_code, response.content))
            self.assertEqual(response.status_code, 200)
            if response.status_code == 200:
                print("Got %s: %s" % (endpoint, response.json()))
            else:
                print("Error %s: %s" % (response.status_code, response.content))

        time.sleep(1)

        # Do not allow GET request on /command
        response = requests.get('http://127.0.0.1:8888/command')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ko')
        self.assertEqual(result['_result'], 'You must only POST on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # You must have parameters when POSTing on /command
        headers = {'Content-Type': 'application/json'}
        data = {}
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ko')
        self.assertEqual(result['_result'], 'You must POST parameters on this endpoint.')

        self.assertEqual(my_module.received_commands, 0)

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "Command",
            "element": "test_host",
            "parameters": "abc;1"
        }
        self.assertEqual(my_module.received_commands, 0)
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND;test_host;abc;1')

        # Not during unit tests ... because module queues are not functional!
        # time.sleep(1)
        # self.assertEqual(my_module.received_commands, 1)

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host;test_service",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "element": "test_host/test_service",    # Accept / as an host/service separator
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'], 'COMMAND_COMMAND;test_host;test_service;1;abc;2')

        # Request to execute an external command (Alignak modern syntax)
        headers = {'Content-Type': 'application/json'}
        data = {
            "command": "command_command",
            "host": "test_host",
            "service": "test_service",
            "user": "******",
            "parameters": "1;abc;2"
        }
        response = requests.post('http://127.0.0.1:8888/command', json=data, headers=headers)
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'ok')
        # Result is uppercase command, parameters are ordered
        self.assertEqual(result['_result'],
                         'COMMAND_COMMAND;test_host;test_service;test_user;1;abc;2')

        self.modulemanager.stop_all()
class TestModuleWsHistory(AlignakTest):

    @classmethod
    def setUpClass(cls):

        # Set test mode for alignak backend
        os.environ['TEST_ALIGNAK_BACKEND'] = '1'
        os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-ws-backend-test'

        # Delete used mongo DBs
        print ("Deleting Alignak backend DB...")
        exit_code = subprocess.call(
            shlex.split(
                'mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'])
        )
        assert exit_code == 0

        cls.p = subprocess.Popen(['uwsgi', '--plugin', 'python', '-w', 'alignakbackend:app',
                                  '--socket', '0.0.0.0:5000',
                                  '--protocol=http', '--enable-threads', '--pidfile',
                                  '/tmp/uwsgi.pid'])
        time.sleep(3)

        cls.endpoint = 'http://127.0.0.1:5000'

        # Backend authentication
        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # Get admin user token (force regenerate)
        response = requests.post(cls.endpoint + '/login', json=params, headers=headers)
        resp = response.json()
        cls.token = resp['token']
        cls.auth = requests.auth.HTTPBasicAuth(cls.token, '')

        # Get admin user
        response = requests.get(cls.endpoint + '/user', auth=cls.auth)
        resp = response.json()
        cls.user_admin = resp['_items'][0]

        # Get realms
        response = requests.get(cls.endpoint + '/realm', auth=cls.auth)
        resp = response.json()
        cls.realmAll_id = resp['_items'][0]['_id']

        # Add a user
        data = {'name': 'test', 'password': '******', 'back_role_super_admin': False,
                'host_notification_period': cls.user_admin['host_notification_period'],
                'service_notification_period': cls.user_admin['service_notification_period'],
                '_realm': cls.realmAll_id}
        response = requests.post(cls.endpoint + '/user', json=data, headers=headers,
                                 auth=cls.auth)
        resp = response.json()
        print("Created a new user: %s" % resp)

        # Get new user restrict role
        params = {'where': json.dumps({'user': resp['_id']})}
        response = requests.get(cls.endpoint + '/userrestrictrole', params=params, auth=cls.auth)
        resp = response.json()

        # Update user's rights - set full CRUD rights
        headers = {'Content-Type': 'application/json', 'If-Match': resp['_items'][0]['_etag']}
        data = {'crud': ['create', 'read', 'update', 'delete', 'custom']}
        resp = requests.patch(cls.endpoint + '/userrestrictrole/' + resp['_items'][0]['_id'],
                              json=data, headers=headers, auth=cls.auth)
        resp = resp.json()
        assert resp['_status'] == 'OK'

        # Add command
        data = {
            "name": "ping",
            "command_line": "check_ping -H $HOSTADDRESS$",
            "_realm": cls.realmAll_id
        }
        requests.post(cls.endpoint + '/command', json=data, headers=headers, auth=cls.auth)
        response = requests.get(cls.endpoint + '/command', auth=cls.auth)
        resp = response.json()
        cls.rc = resp['_items']

        # Add an host
        data = {
            "name": "srv001",
            "address": "192.168.0.2",
            "business_impact": 5,
            "check_command": cls.rc[0]['_id'],
            "_realm": cls.realmAll_id
        }
        response = requests.post(cls.endpoint + '/host', json=data, headers=headers, auth=cls.auth)
        response = requests.get(cls.endpoint + '/host?where={"name":"srv001"}', auth=cls.auth)
        resp = response.json()
        cls.rh = resp['_items']

        # Add a service
        data = {
            "name": "ping",
            "host": cls.rh[0]['_id'],
            "check_command": cls.rc[0]['_id'],
            "business_impact": 4,
            "_realm": cls.realmAll_id
        }
        response = requests.post(cls.endpoint + '/service', json=data, headers=headers, auth=cls.auth)
        response = requests.get(cls.endpoint + '/service', auth=cls.auth)
        resp = response.json()
        cls.rs = resp['_items']

        cls.modulemanager = None

    @classmethod
    def tearDownClass(cls):
        cls.p.kill()

    def setUp(self):
        """Create resources in backend

        :return: None
        """

    def tearDown(self):
        for resource in ['logcheckresult', 'history']:
            requests.delete('http://127.0.0.1:5000/' + resource, auth=self.auth)
        if self.modulemanager:
            time.sleep(1)
            self.modulemanager.stop_all()

    def file_dump(self, data, filename):  # pylint: disable=no-self-use
        """Dump the data to a JSON formatted file
        :param data: data to be dumped
        :param filename: name of the file to use. Only the file name, not the full path!
        :return: dumped file absolute file name
        """
        dump = json.dumps(data, indent=4,
                          separators=(',', ': '), sort_keys=True)
        path = os.path.join(self.folder or os.getcwd(), filename)
        try:
            dfile = open(path, "wt")
            dfile.write(dump)
            dfile.close()
            return path
        except (OSError, IndexError) as exp:  # pragma: no cover, should never happen
            print("Error when writing the list dump file %s : %s" % (path, str(exp)))
            assert False
        return None

    def test_module_zzz_get_history_admin(self):
        """Test the module log collection functions
        :return:
        """
        self.print_header()
        self._get_history("admin", "admin")

    def test_module_zzz_get_history_test(self):
        """Test the module log collection functions
        :return:
        """
        self.print_header()
        self._get_history("test", "test")

    def _get_history(self, username, password):

        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Alignak backend URL
            'alignak_backend': 'http://127.0.0.1:5000',
            'username': '******',
            'password': '******',
            # Activate CherryPy file logs
            'log_access': '/tmp/alignak-module-ws-access.log',
            'log_error': '/tmp/alignak-module-ws-error.log',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        time.sleep(1)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # ---
        # Prepare the backend content...
        self.endpoint = 'http://127.0.0.1:5000'

        headers = {'Content-Type': 'application/json'}
        params = {'username': '******', 'password': '******'}
        # get token
        response = requests.post(self.endpoint + '/login', json=params, headers=headers)
        resp = response.json()
        self.token = resp['token']
        self.auth = requests.auth.HTTPBasicAuth(self.token, '')

        # Get default realm
        response = requests.get(self.endpoint + '/realm', auth=self.auth)
        resp = response.json()
        self.realm_all = resp['_items'][0]['_id']
        # ---

        # -------------------------------------------
        # Add a check result for an host
        data = {
            "last_check": 1496332753,
            "host": self.rh[0]['_id'],
            "service": None,
            'acknowledged': False,
            'state_id': 0,
            'state': 'UP',
            'state_type': 'HARD',
            'last_state_id': 0,
            'last_state': 'UP',
            'last_state_type': 'HARD',
            'state_changed': False,
            'latency': 0,
            'execution_time': 0.12,
            'output': 'Check output',
            'long_output': 'Check long_output',
            'perf_data': 'perf_data',
            "_realm": self.realm_all
        }
        response = requests.post(
            self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth
        )
        resp = response.json()
        self.assertEqual(resp['_status'], 'OK')

        # -------------------------------------------
        # Add a check result for a service
        data = {
            "last_check": 1496332754,
            "host": self.rh[0]['_id'],
            "service": self.rs[0]['_id'],
            'acknowledged': False,
            'state_id': 0,
            'state': 'UP',
            'state_type': 'HARD',
            'last_state_id': 0,
            'last_state': 'UP',
            'last_state_type': 'HARD',
            'state_changed': False,
            'latency': 0,
            'execution_time': 0.12,
            'output': 'Check output',
            'long_output': 'Check long_output',
            'perf_data': 'perf_data',
            "_realm": self.realm_all
        }
        response = requests.post(
            self.endpoint + '/logcheckresult', json=data, headers=headers, auth=self.auth
        )
        resp = response.json()
        self.assertEqual(resp['_status'], 'OK')
        # Add an history event
        data = {
            "host_name": "chazay",
            "service_name": "Processus",
            "user_name": "Alignak",
            "type": "check.result",
            "message": "OK[HARD] (False,False): All is ok",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        time.sleep(1)
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)

        # Add an history event
        time.sleep(1)
        data = {
            "host_name": "denice",
            "service_name": "Zombies",
            "user_name": "Alignak",
            "type": "check.result",
            "message": "OK[HARD] (False,False): All is ok",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)

        # Add an history event
        time.sleep(1)
        data = {
            "host_name": "denice",
            "user_name": "Me",
            "type": "monitoring.alert",
            "message": "HOST ALERT ....",
            "_realm": self.realm_all,
            "_sub_realm": True
        }
        requests.post(self.endpoint + '/history', json=data, headers=headers, auth=self.auth)
        # ---

        # ---
        # Get history to confirm that backend is ready
        # ---
        response = requests.get(self.endpoint + '/history', auth=self.auth,
                                params={"sort": "-_id", "max_results": 25, "page": 1, 'embedded': json.dumps({"logcheckresult": 1})})
        resp = response.json()
        pprint(resp['_items'])
        self.assertEqual(len(resp['_items']), 5)

        # Backend real history
        # The commented fields are the one existing in the backend but filtered by the WS
        backend_real_history = [
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:16 GMT',
                # u'_etag': u'9f07c7285b37bb3d336a96ede3d3fd2a774c4c4c',
                u'_id': u'593039d406fd4b3bf0e27d9f',
                # u'_links': {u'self': {u'href': u'history/593039d406fd4b3bf0e27d9f',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:16 GMT',
                u'host_name': u'denice',
                u'message': u'HOST ALERT ....',
                u'type': u'monitoring.alert',
                u'user_name': u'Me'
            },
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:15 GMT',
                # u'_etag': u'24cd486a1a28859a0177fbe15d1ead61f78f7b2c',
                u'_id': u'593039d306fd4b3bf0e27d9e',
                # u'_links': {u'self': {u'href': u'history/593039d306fd4b3bf0e27d9e',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:15 GMT',
                u'host_name': u'denice',
                u'message': u'OK[HARD] (False,False): All is ok',
                u'service_name': u'Zombies',
                u'type': u'check.result',
                u'user_name': u'Alignak'
            },
            {
                u'_created': u'Thu, 01 Jun 2017 15:59:14 GMT',
                # u'_etag': u'4c4ee43a4fac0b91dcfddb011619007dedb1cd95',
                u'_id': u'593039d206fd4b3bf0e27d9d',
                # u'_links': {u'self': {u'href': u'history/593039d206fd4b3bf0e27d9d',
                #                       u'title': u'History'}},
                # u'_realm': u'593039cc06fd4b3bf0e27d88',
                # u'_sub_realm': True,
                # u'_updated': u'Thu, 01 Jun 2017 15:59:14 GMT',
                u'host_name': u'chazay',
                u'message': u'OK[HARD] (False,False): All is ok',
                u'service_name': u'Processus',
                u'type': u'check.result',
                u'user_name': u'Alignak'
            },
            {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'_etag': u'76dd35f575244848dd41f67ad3109cf6f1f9a33c',
             u'_id': u'593039d106fd4b3bf0e27d9c',
             # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9c',
             #                       u'title': u'History'}},
             # u'_realm': u'593039cc06fd4b3bf0e27d88',
             # u'_sub_realm': True,
             # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'host': u'593039cc06fd4b3bf0e27d90',
             u'host_name': u'srv001',
             u'logcheckresult': {
                 u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 # u'_etag': u'10a3935b1158fe4c8f62962a14b1050fef32df4b',
                 # u'_id': u'593039d106fd4b3bf0e27d9b',
                 # u'_realm': u'593039cc06fd4b3bf0e27d88',
                 # u'_sub_realm': True,
                 # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 u'acknowledged': False,
                 u'acknowledgement_type': 1,
                 u'downtimed': False,
                 u'execution_time': 0.12,
                 # u'host': u'593039cc06fd4b3bf0e27d90',
                 # u'host_name': u'srv001',
                 u'last_check': 1496332753,
                 u'last_state': u'UP',
                 u'last_state_changed': 0,
                 u'last_state_id': 0,
                 u'last_state_type': u'HARD',
                 u'latency': 0.0,
                 u'long_output': u'Check long_output',
                 u'output': u'Check output',
                 u'passive_check': False,
                 u'perf_data': u'perf_data',
                 # u'service': u'593039cf06fd4b3bf0e27d98',
                 # u'service_name': u'ping',
                 u'state': u'UP',
                 u'state_changed': False,
                 u'state_id': 0,
                 u'state_type': u'HARD'
             },
             u'message': u'UP[HARD] (False/False): Check output',
             # u'service': u'593039cf06fd4b3bf0e27d98',
             u'service_name': u'ping',
             u'type': u'check.result',
             # u'user': None,
             u'user_name': u'Alignak'
             },
            {u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'_etag': u'c3cd29587ad328325dc48af677b3a36157361a84',
             u'_id': u'593039d106fd4b3bf0e27d9a',
             # u'_links': {u'self': {u'href': u'history/593039d106fd4b3bf0e27d9a',
             #                       u'title': u'History'}},
             # u'_realm': u'593039cc06fd4b3bf0e27d88',
             # u'_sub_realm': True,
             # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
             # u'host': u'593039cc06fd4b3bf0e27d90',
             u'host_name': u'srv001',
             u'logcheckresult': {
                 u'_created': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 # u'_etag': u'0ea4c16f1e651a02772aa2bfa83070b47e7f6531',
                 # u'_id': u'593039d106fd4b3bf0e27d99',
                 # u'_realm': u'593039cc06fd4b3bf0e27d88',
                 # u'_sub_realm': True,
                 # u'_updated': u'Thu, 01 Jun 2017 15:59:13 GMT',
                 u'acknowledged': False,
                 u'acknowledgement_type': 1,
                 u'downtimed': False,
                 u'execution_time': 0.12,
                 # u'host': u'593039cc06fd4b3bf0e27d90',
                 # u'host_name': u'srv001',
                 u'last_check': 1496332754,
                 u'last_state': u'UP',
                 u'last_state_changed': 0,
                 u'last_state_id': 0,
                 u'last_state_type': u'HARD',
                 u'latency': 0.0,
                 u'long_output': u'Check long_output',
                 u'output': u'Check output',
                 u'passive_check': False,
                 u'perf_data': u'perf_data',
                 # u'service': None,
                 # u'service_name': u'',
                 u'state': u'UP',
                 u'state_changed': False,
                 u'state_id': 0,
                 u'state_type': u'HARD'
             },
             u'message': u'UP[HARD] (False/False): Check output',
             # u'service': None,
             u'service_name': u'',
             u'type': u'check.result',
             # u'user': None,
             u'user_name': u'Alignak'
             }
        ]
        # ---

        # ---
        # # Directly call the module function
        # search = {
        #     'page': 1,
        #     'max_results': 25
        # }
        # result = my_module.getBackendHistory(search)
        # print(result)
        # print("Page: %d, got: %d items" % (search["page"], len(result['items'])))
        # for item in result['items']:
        #     print(item)
        # assert len(result['items']) == 5

        # ---
        # Do not allow GET request on /alignak_logs - not yet authorized!
        response = requests.get('http://127.0.0.1:8888/alignak_logs')
        self.assertEqual(response.status_code, 401)

        session = requests.Session()

        # Login with username/password (real backend login)
        headers = {'Content-Type': 'application/json'}
        params = {'username': username, 'password': password}
        response = session.post('http://127.0.0.1:8888/login', json=params, headers=headers)
        assert response.status_code == 200
        resp = response.json()

        # ---
        # Get the alignak default history
        response = session.get('http://127.0.0.1:8888/alignak_logs')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        # Remove fields that will obviously be different!
        for item in result['items']:
            del(item['_id'])
            del(item['_created'])
            # if 'logcheckresult' in item:
            #     del (item['logcheckresult']['_created'])
        for item in backend_real_history:
            del(item['_id'])
            del(item['_created'])
            if 'logcheckresult' in item:
                del (item['logcheckresult']['_created'])
        self.assertEqual(len(result['items']), 5)
        # Too complex comparison!!!
        # self.assertEqual(backend_real_history, result['items'])
        # assert cmp(backend_real_history, result['items']) == 0
        # ---

        # ---
        # Get the alignak default history, filter to get only check.result
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:check.result')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 4)
        # ---

        # ---
        # Get the alignak default history, filter to get only for a user
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Alignak')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 4)
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=user_name:Me')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # ---

        # ---
        # Get the alignak default history, filter to get only for an host
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 1)
        # Implicit host_name
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 1)
        # Unknown search field
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=name:chazay')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        # All history items because name is not aknown search field! So we get all items...
        self.assertEqual(len(result['items']), 5)

        # Some other hosts...
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 2)
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:srv001')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 2)

        # Several hosts...
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:denice host_name:srv001')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(len(result['items']), 4)   # 2 for each host

        # Not an host...
        # TODO: looks that ths criteria is not correctly implemented :(
        # response = session.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!denice')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # self.assertEqual(len(result['items']), 3)
        # ---

        # ---
        # Get the alignak default history, NOT for an host
        # todo: temporarily skipped
        # response = requests.get('http://127.0.0.1:8888/alignak_logs?search=host_name:!Chazay')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # for item in result['items']:
        #     print(item)
        # self.assertEqual(len(result['items']), 2)
        # ---

        # ---
        # Get the alignak default history, only for a service
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=service_name:Processus')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # ---

        # ---
        # Get the alignak default history, for an host and a service
        # todo multi search query to be improved!
        # response = session.get('http://127.0.0.1:8888/alignak_logs?search="host_name:chazay service_name=Processus"')
        # self.assertEqual(response.status_code, 200)
        # result = response.json()
        # for item in result['items']:
        #     print(item)
        # self.assertEqual(len(result['items']), 3)
        # ---

        # ---
        # Get the alignak default history, unknown event type
        response = session.get('http://127.0.0.1:8888/alignak_logs?search=type:XXX')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        # ---

        # ---
        # Get the alignak default history, page count
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=2&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=3&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=4&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 1)
        # Over the limits !
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=5&count=1')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=50&count=50')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        for item in result['items']:
            print(item)
        self.assertEqual(len(result['items']), 0)
        # ---

        # ---
        # Get the alignak history, page count greater than the number of items
        response = session.get('http://127.0.0.1:8888/alignak_logs?start=1&count=25')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        pprint(result)
        self.assertEqual(len(result['items']), 5)   # Got 5 items
        self.assertEqual(result['_meta']['max_results'], 25)
        self.assertEqual(result['_meta']['page'], 1)
        self.assertEqual(result['_meta']['total'], 5)

        response = session.get('http://127.0.0.1:8888/alignak_logs?start=0&count=50')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        pprint(result)
        self.assertEqual(len(result['items']), 5)   # Got 5 items
        self.assertEqual(result['_meta']['max_results'], 50)
        self.assertEqual(result['_meta']['page'], 1)
        self.assertEqual(result['_meta']['total'], 5)

        # ---

        # Logout
        response = session.get('http://127.0.0.1:8888/logout')
        self.assertEqual(response.status_code, 200)
        result = response.json()
        self.assertEqual(result['_status'], 'OK')
        self.assertEqual(result['_result'], 'Logged out')

    @pytest.mark.skip("Internal function to get from an existing backend")
    def _get_from_backend(self, backend_url='http://127.0.01:5000',
                          host_name='test', file_name='history.json'):
        """Get the all history for an host in an existing backend.
        Dumps the resulting information as a JSON array to a file

        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Alignak backend URL
            'alignak_backend': backend_url,
            'username': '******',
            'password': '******',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        time.sleep(2)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # ---

        # Start with first page ... max_results=3
        page = 1
        count = 25
        items = []
        search = {
            'page': page,
            'max_results': count
        }
        where = Helper.decode_search(host_name)
        if where:
            search.update({'where': json.dumps(where)})

        while count > 0:
            result = my_module.getBackendHistory(search)
            count = len(result['items'])
            print("Page: %d, got: %d items" % (search["page"], count))
            for item in result['items']:
                sys.stdout.write('.')
                # print(item)
            items.extend(result['items'])
            search["page"] += 1
        print("Got: %d items" % len(items))

        self.folder = '/tmp'
        self.file_dump(items, file_name)
Example #36
0
    def test_module_manager(self):
        """
        Test if the module manager manages correctly all the modules
        :return:
        """
        self.print_header()
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        time_hacker.set_real_time()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load and initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        # Loading module logs
        self.assert_any_log_match(re.escape(
            "Importing Python module 'alignak_module_ws' for web-services..."
        ))
        self.assert_any_log_match(re.escape(
            "Module properties: {'daemons': ['receiver'], 'phases': ['running'], "
            "'type': 'web-services', 'external': True}"
        ))
        self.assert_any_log_match(re.escape(
            "Imported 'alignak_module_ws' for web-services"
        ))
        self.assert_any_log_match(re.escape(
            "Loaded Python module 'alignak_module_ws' (web-services)"
        ))
        self.assert_any_log_match(re.escape(
            "Give an instance of alignak_module_ws for alias: web-services"
        ))

        my_module = self.modulemanager.instances[0]

        # Get list of not external modules
        self.assertListEqual([], self.modulemanager.get_internal_instances())
        for phase in ['configuration', 'late_configuration', 'running', 'retention']:
            self.assertListEqual([], self.modulemanager.get_internal_instances(phase))

        # Get list of external modules
        self.assertListEqual([my_module], self.modulemanager.get_external_instances())
        for phase in ['configuration', 'late_configuration', 'retention']:
            self.assertListEqual([], self.modulemanager.get_external_instances(phase))
        for phase in ['running']:
            self.assertListEqual([my_module], self.modulemanager.get_external_instances(phase))

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        # Clear logs
        self.clear_logs()

        # Kill the external module (normal stop is .stop_process)
        my_module.kill()
        time.sleep(0.1)
        self.assert_log_match("Killing external module", 0)
        self.assert_log_match("External module killed", 1)

        # Should be dead (not normally stopped...) but we still know a process for this module!
        self.assertIsNotNone(my_module.process)

        # Nothing special ...
        self.modulemanager.check_alive_instances()
        self.assert_log_match("The external module web-services died unexpectedly!", 2)
        self.assert_log_match("Setting the module web-services to restart", 3)

        # Try to restart the dead modules
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 4)

        # In fact it's too early, so it won't do it
        # The module instance is still dead
        self.assertFalse(my_module.process.is_alive())

        # So we lie, on the restart tries ...
        my_module.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 5)

        # The module instance is now alive again
        self.assertTrue(my_module.process.is_alive())
        self.assert_log_match("I'm stopping module 'web-services'", 6)
        self.assert_log_match("Starting external process for module web-services", 7)
        self.assert_log_match("web-services is now started", 8)

        # There is nothing else to restart in the module manager
        self.assertEqual([], self.modulemanager.to_restart)

        # Clear logs
        self.clear_logs()

        # Now we look for time restart so we kill it again
        my_module.kill()
        time.sleep(0.2)
        self.assertFalse(my_module.process.is_alive())
        self.assert_log_match("Killing external module", 0)
        self.assert_log_match("External module killed", 1)

        # Should be too early
        self.modulemanager.check_alive_instances()
        self.assert_log_match("The external module web-services died unexpectedly!", 2)
        self.assert_log_match("Setting the module web-services to restart", 3)

        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 4)

        # In fact it's too early, so it won't do it
        # The module instance is still dead
        self.assertFalse(my_module.process.is_alive())

        # So we lie, on the restart tries ...
        my_module.last_init_try = -5
        self.modulemanager.check_alive_instances()
        self.modulemanager.try_to_restart_deads()
        self.assert_log_match("Trying to initialize module: web-services", 5)

        # The module instance is now alive again
        self.assertTrue(my_module.process.is_alive())
        self.assert_log_match("I'm stopping module 'web-services'", 6)
        self.assert_log_match("Starting external process for module web-services", 7)
        self.assert_log_match("web-services is now started", 8)

        # And we clear all now
        self.modulemanager.stop_all()
        # Stopping module logs

        self.assert_log_match("Request external process to stop for web-services", 9)
        self.assert_log_match(re.escape("I'm stopping module 'web-services' (pid="), 10)
        self.assert_log_match(
            re.escape("'web-services' is still alive after normal kill, I help it to die"), 11
        )
        self.assert_log_match("Killing external module ", 12)
        self.assert_log_match("External module killed", 13)
        self.assert_log_match("External process stopped.", 14)
    def _get_from_backend(self, backend_url='http://127.0.01:5000',
                          host_name='test', file_name='history.json'):
        """Get the all history for an host in an existing backend.
        Dumps the resulting information as a JSON array to a file

        :return:
        """
        self.print_header()
        # Obliged to call to get a self.logger...
        self.setup_with_file('cfg/cfg_default.cfg')
        self.assertTrue(self.conf_is_correct)

        # -----
        # Provide parameters - logger configuration file (exists)
        # -----
        # Clear logs
        self.clear_logs()

        # Create an Alignak module
        mod = Module({
            'module_alias': 'web-services',
            'module_types': 'web-services',
            'python_name': 'alignak_module_ws',
            # Set Arbiter address as empty to not poll the Arbiter else the test will fail!
            'alignak_host': '',
            'alignak_port': 7770,
            # Alignak backend URL
            'alignak_backend': backend_url,
            'username': '******',
            'password': '******',
        })

        # Create the modules manager for a daemon type
        self.modulemanager = ModulesManager('receiver', None)

        # Load an initialize the modules:
        #  - load python module
        #  - get module properties and instances
        self.modulemanager.load_and_init([mod])

        my_module = self.modulemanager.instances[0]

        # Clear logs
        self.clear_logs()

        # Start external modules
        self.modulemanager.start_external_instances()

        # Starting external module logs
        self.assert_log_match("Trying to initialize module: web-services", 0)
        self.assert_log_match("Starting external module web-services", 1)
        self.assert_log_match("Starting external process for module web-services", 2)
        self.assert_log_match("web-services is now started", 3)

        time.sleep(2)

        # Check alive
        self.assertIsNotNone(my_module.process)
        self.assertTrue(my_module.process.is_alive())

        time.sleep(1)

        # ---

        # Start with first page ... max_results=3
        page = 1
        count = 25
        items = []
        search = {
            'page': page,
            'max_results': count
        }
        where = Helper.decode_search(host_name)
        if where:
            search.update({'where': json.dumps(where)})

        while count > 0:
            result = my_module.getBackendHistory(search)
            count = len(result['items'])
            print("Page: %d, got: %d items" % (search["page"], count))
            for item in result['items']:
                sys.stdout.write('.')
                # print(item)
            items.extend(result['items'])
            search["page"] += 1
        print("Got: %d items" % len(items))

        self.folder = '/tmp'
        self.file_dump(items, file_name)