def test_2_put_exception_method_not_allowed(self): """ Test put a user with errors (so exceptions) because PUT method not allowed on this endpoint :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # get user admin params = {"where": {"name": "admin"}} response = requests.get(self.backend_address + '/user', json=params, auth=self.auth) resp = response.json() user_id = resp['_items'][0]['_id'] with assert_raises(BackendException) as cm: data = {'alias': 'modified with no header'} backend.put('/'.join(['user', user_id]), data=data) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1000, str(ex)) with assert_raises(BackendException) as cm: data = {'alias': 'modified test again and again'} headers = {'If-Match': "567890987678"} response = backend.put('/'.join(['user', user_id]), data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 405, str(ex))
def test_1_put_successful(self): """ Test put an alignakretention successfully :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # get alignakretention params = {} response = requests.get(self.backend_address + '/alignakretention', json=params, auth=self.auth) resp = response.json() ar_id = resp['_items'][0]['_id'] ar_etag = resp['_items'][0]['_etag'] data = { 'host': 'srv001', 'latency': 2, 'last_state_type': 'HARD', 'state': 'UP', 'last_chk': 0, } headers = {'If-Match': ar_etag} response = backend.put('/'.join(['alignakretention', ar_id]), data=data, headers=headers) assert_true(response['_status'] == 'OK') response = requests.get(self.backend_address + '/alignakretention', json=params, auth=self.auth) resp = response.json() self.assertEqual('srv001', resp['_items'][0]['host']) self.assertEqual(2, resp['_items'][0]['latency'])
def test_3_put_exception_method_allowed(self): """ Test put a user with errors (so exceptions) because PUT method not allowed on this endpoint :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # get alignakretention params = {} response = requests.get(self.backend_address + '/alignakretention', json=params, auth=self.auth) resp = response.json() ar_id = resp['_items'][0]['_id'] with assert_raises(BackendException) as cm: data = { 'host': 'srv001', 'latency': 2, 'last_state_type': 'HARD', 'state': 'UP', 'last_chk': 0, } backend.put('/'.join(['alignakretention', ar_id]), data=data) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1000, str(ex)) with assert_raises(BackendException) as cm: data = { 'host': 'srv001', 'latency': 2, 'last_state_type': 'HARD', 'state': 'UP', 'last_chk': 0, } headers = {'If-Match': "567890987678"} response = backend.put('/'.join(['alignakretention', ar_id]), data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 412, str(ex))
def test_1_put_successful_inception(self): """ Test put an alignakretention successfully with inception :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # get alignakretention params = {} response = requests.get(self.backend_address + '/alignakretention', json=params, auth=self.auth) resp = response.json() ar_id = resp['_items'][0]['_id'] data = {'alias': 'modified test'} headers = {'If-Match': 'foo'} response = backend.put('/'.join(['alignakretention', ar_id]), data=data, headers=headers, inception=True) assert_true(response['_status'] == 'OK')
def test_4_put_connection_error(self): """ Backend connection error when replacing an object... :return: None """ print('test connection error when replacing an object') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # get alignakretention params = {} response = requests.get(self.backend_address + '/alignakretention', json=params, auth=self.auth) resp = response.json() ar_id = resp['_items'][0]['_id'] ar_etag = resp['_items'][0]['_etag'] print("stop the alignak backend") self.pid.kill() with assert_raises(BackendException) as cm: data = { 'host': 'srv001', 'latency': 2, 'last_state_type': 'HARD', 'state': 'UP', 'last_chk': 0, } headers = {'If-Match': ar_etag} response = backend.put('/'.join(['alignakretention', ar_id]), data=data, headers=headers) assert_true(response['_status'] == 'OK') ex = cm.exception self.assertEqual(ex.code, 1000)
class AlignakBackendScheduler(BaseModule): """ This class is used to send live states to alignak-backend """ def __init__(self, mod_conf): """Module initialization mod_conf is a dictionary that contains: - all the variables declared in the module configuration file - a 'properties' value that is the module properties as defined globally in this file :param mod_conf: module configuration file as a dictionary """ BaseModule.__init__(self, mod_conf) # pylint: disable=global-statement global logger logger = logging.getLogger('alignak.module.%s' % self.alias) logger.setLevel(getattr(mod_conf, 'log_level', logging.INFO)) logger.debug("inner properties: %s", self.__dict__) logger.debug("received configuration: %s", mod_conf.__dict__) self.client_processes = int(getattr(mod_conf, 'client_processes', 1)) logger.info("Number of processes used by backend client: %s", self.client_processes) self.backend_count = int(getattr(mod_conf, 'backend_count', '50')) logger.info("backend pagination count: %d items", self.backend_count) logger.info("StatsD configuration: %s:%s, prefix: %s, enabled: %s", getattr(mod_conf, 'statsd_host', 'localhost'), int(getattr(mod_conf, 'statsd_port', '8125')), getattr(mod_conf, 'statsd_prefix', 'alignak'), (getattr(mod_conf, 'statsd_enabled', '0') != '0')) self.statsmgr = Stats() self.statsmgr.register( self.alias, 'module', statsd_host=getattr(mod_conf, 'statsd_host', 'localhost'), statsd_port=int(getattr(mod_conf, 'statsd_port', '8125')), statsd_prefix=getattr(mod_conf, 'statsd_prefix', 'alignak'), statsd_enabled=(getattr(mod_conf, 'statsd_enabled', '0') != '0')) self.url = getattr(mod_conf, 'api_url', 'http://localhost:5000') logger.info("Alignak backend endpoint: %s", self.url) self.backend = Backend(self.url, self.client_processes) self.backend.token = getattr(mod_conf, 'token', '') self.backend_connected = False self.backend_errors_count = 0 self.backend_username = getattr(mod_conf, 'username', '') self.backend_password = getattr(mod_conf, 'password', '') self.backend_generate = getattr(mod_conf, 'allowgeneratetoken', False) if not self.backend.token: logger.warning( "no user token configured. " "It is recommended to set a user token rather than a user login " "in the configuration. Trying to get a token from the provided " "user login information...") self.getToken() else: self.backend_connected = True # Common functions def do_loop_turn(self): """This function is called/used when you need a module with a loop function (and use the parameter 'external': True) """ logger.info("[Backend Scheduler] In loop") time.sleep(1) def getToken(self): """Authenticate and get the token :return: None """ generate = 'enabled' if not self.backend_generate: generate = 'disabled' try: start = time.time() self.backend_connected = self.backend.login( self.backend_username, self.backend_password, generate) self.statsmgr.counter('backend-login', 1) self.statsmgr.timer('backend-login-time', time.time() - start) if not self.backend_connected: logger.warning("Backend login failed") self.token = self.backend.token self.backend_errors_count = 0 except BackendException as exp: # pragma: no cover - should not happen self.backend_connected = False self.backend_errors_count += 1 logger.warning( "Alignak backend is not available for login. " "No backend connection, attempt: %d", self.backend_errors_count) logger.debug("Exception: %s", exp) def raise_backend_alert(self, errors_count=10): """Raise a backend alert :return: True if the backend is not connected and the error count is greater than a defined threshold """ logger.debug( "Check backend connection, connected: %s, errors count: %d", self.backend_connected, self.backend_errors_count) if not self.backend_connected and self.backend_errors_count >= errors_count: return True return False def hook_load_retention(self, scheduler): """Load retention data from alignak-backend :param scheduler: scheduler instance of alignak :type scheduler: object :return: None """ all_data = {'hosts': {}, 'services': {}} if not self.backend_connected: self.getToken() if self.raise_backend_alert(errors_count=1): logger.warning("Alignak backend connection is not available. " "Loading retention data is not possible.") return None if not self.backend_connected: return None # Get data from the backend try: start = time.time() params = {"max_results": self.backend_count} response = self.backend.get_all('alignakretention', params) for host in response['_items']: # clean unusable keys hostname = host['host'] if 'retention_services' in host: for service in host['retention_services']: all_data['services'][(host['host'], service)] = \ host['retention_services'][service] for key in [ '_created', '_etag', '_id', '_links', '_updated', 'host', 'retention_services', '_user', 'schema_version' ]: if key in host: del host[key] all_data['hosts'][hostname] = host logger.info('%d hosts loaded from retention', len(all_data['hosts'])) self.statsmgr.counter('retention-load.hosts', len(all_data['hosts'])) logger.info('%d services loaded from retention', len(all_data['services'])) self.statsmgr.counter('retention-load.services', len(all_data['services'])) self.statsmgr.timer('retention-load.time', time.time() - start) scheduler.restore_retention_data(all_data) except BackendException: self.backend_connected = False self.backend_errors_count += 1 logger.warning( "Alignak backend connection fails. Check and fix your configuration" ) return False return True def hook_save_retention(self, scheduler): """Save retention data to alignak-backend :param scheduler: scheduler instance of alignak :type scheduler: object :return: None """ if not self.backend_connected: self.getToken() if self.raise_backend_alert(errors_count=1): logger.warning("Alignak backend connection is not available. " "Saving objects is not possible.") return None if not self.backend_connected: return None try: data_to_save = scheduler.get_retention_data() start_time = time.time() # get list of retention_data params = {"max_results": self.backend_count} response = self.backend.get_all('alignakretention', params) db_hosts = {} for host in response['_items']: db_hosts[host['host']] = host # add services in the hosts for host in data_to_save['hosts']: data_to_save['hosts'][host]['retention_services'] = {} data_to_save['hosts'][host]['host'] = host if 'services' in data_to_save: # Scheduler old-school: two separate dictionaries! for service in data_to_save['services']: data_to_save['hosts'][service[0]]['retention_services'][service[1]] = \ data_to_save['services'][service] for host in data_to_save['hosts']: if host in db_hosts: # if host in retention_data, PUT headers = {'Content-Type': 'application/json'} headers['If-Match'] = db_hosts[host]['_etag'] try: logger.debug('Host retention data: %s', data_to_save['hosts'][host]) self.backend.put( 'alignakretention/%s' % (db_hosts[host]['_id']), data_to_save['hosts'][host], headers, True) except BackendException as exp: # pragma: no cover - should not happen logger.error('Put alignakretention error') logger.error('Response: %s', exp.response) logger.exception("Exception: %s", exp) self.backend_connected = False return False else: # if not host in retention_data, POST try: logger.debug('Host retention data: %s', data_to_save['hosts'][host]) self.backend.post('alignakretention', data=data_to_save['hosts'][host]) except BackendException as exp: # pragma: no cover - should not happen logger.error('Post alignakretention error') logger.error('Response: %s', exp.response) logger.exception("Exception: %s", exp) self.backend_connected = False return False logger.info('%d hosts saved in retention', len(data_to_save['hosts'])) self.statsmgr.counter('retention-save.hosts', len(data_to_save['hosts'])) logger.info('%d services saved in retention', len(data_to_save['services'])) self.statsmgr.counter('retention-save.services', len(data_to_save['services'])) self.statsmgr.timer('retention-save.time', time.time() - start_time) now = time.time() logger.info("Retention saved in %s seconds", (now - start_time)) except BackendException: self.backend_connected = False self.backend_errors_count += 1 logger.warning( "Alignak backend connection fails. Check and fix your configuration" ) return False return True