def test_2_delete_exceptions(self): """ Test delete a timeperiod with errors (so exceptions) :return: None """ backend = Backend(self.backend_address) backend.login("admin", "admin") # Create a new timeperiod data = { "name": "Testing TP", "alias": "Test TP", "dateranges": [ {u"monday": u"09:00-17:00"}, {u"tuesday": u"09:00-17:00"}, {u"wednesday": u"09:00-17:00"}, {u"thursday": u"09:00-17:00"}, {u"friday": u"09:00-17:00"}, ], "_realm": self.realmAll_id, } response = backend.post("timeperiod", data=data) assert_true(response["_status"] == "OK") timeperiod_id = response["_id"] timeperiod_etag = response["_etag"] with assert_raises(BackendException) as cm: headers = {"If-Match": timeperiod_etag} response = backend.delete("/".join(["timeperiod", "5" + timeperiod_id]), headers) ex = cm.exception print("exception:", str(ex.code)) assert_true(ex.code == 1003, str(ex))
def test_1_patch_successful_inception(self): """ Test patch a user successfully with inception :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'] # user_etag = resp['_items'][0]['_etag'] data = {'alias': 'modified test'} headers = {'If-Match': 'foo'} response = backend.patch('/'.join(['user', user_id]), data=data, headers=headers, inception=True) assert_true(response['_status'] == 'OK')
def test_1_delete_successful(self): """ Test delete a timeperiod successfully :return: None """ backend = Backend(self.backend_address) backend.login("admin", "admin") # Create a new timeperiod data = { "name": "Testing TP", "alias": "Test TP", "dateranges": [ {u"monday": u"09:00-17:00"}, {u"tuesday": u"09:00-17:00"}, {u"wednesday": u"09:00-17:00"}, {u"thursday": u"09:00-17:00"}, {u"friday": u"09:00-17:00"}, ], "_realm": self.realmAll_id, } response = backend.post("timeperiod", data=data) assert_true(response["_status"] == "OK") timeperiod_id = response["_id"] timeperiod_etag = response["_etag"] headers = {"If-Match": timeperiod_etag} response = backend.delete("/".join(["timeperiod", timeperiod_id]), headers=headers) assert_true(response["_status"] == "OK")
def test_1_post_successful(self): """ Test post a timeperiod successfully :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # Create a new timeperiod print('create a timeperiod') data = { "name": "Testing TP", "alias": "Test TP", "dateranges": [ {u'monday': u'09:00-17:00'}, {u'tuesday': u'09:00-17:00'}, {u'wednesday': u'09:00-17:00'}, {u'thursday': u'09:00-17:00'}, {u'friday': u'09:00-17:00'} ], "_realm": self.realmAll_id } response = backend.post('timeperiod', data=data) assert_true('_created' in response) assert_true('_updated' in response) assert_true(response['_created'] == response['_updated'])
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_2_post_exceptions(self): """ Test post a user with errors (so exceptions) :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # Create a new user, bad parameters # Mandatory field user_name is missing ... data = { "name": "Testing user", "alias": "Fred", "back_role_super_admin": False, "back_role_admin": [], "min_business_impact": 0, } with assert_raises(BackendException) as cm: backend.post('user', data=data) ex = cm.exception print('exception:', str(ex.code), ex.message, ex.response) if "_issues" in ex.response: for issue in ex.response["_issues"]: print("Issue: %s - %s" % (issue, ex.response["_issues"][issue])) assert_true(ex.code == 422) assert_true(ex.response["_issues"])
def test_01_creation(self): """ Create connection with the backend :return: None """ print('') print('test creation') print('Create client API for URL:', self.backend_address) backend = Backend(self.backend_address) print('object:', backend) print('authenticated:', backend.authenticated) print('endpoint:', backend.url_endpoint_root) print('token:', backend.token) assert_false(backend.authenticated) assert_true(backend.url_endpoint_root == self.backend_address) assert_equal(backend.token, None) print('Create client API (trailing slash is removed)') backend = Backend(self.backend_address + '/') print('object:', backend) print('authenticated:', backend.authenticated) print('endpoint:', backend.url_endpoint_root) print('token:', backend.token) assert_false(backend.authenticated) assert_true(backend.url_endpoint_root == self.backend_address) assert_equal(backend.token, None)
class TestRecalculateLivestate(unittest2.TestCase): @classmethod def setUpClass(cls): cls.p = subprocess.Popen( ["uwsgi", "-w", "alignakbackend:app", "--socket", "0.0.0.0:5000", "--protocol=http", "--enable-threads"] ) time.sleep(3) cls.backend = Backend("http://127.0.0.1:5000") cls.backend.login("admin", "admin", "force") cls.backend.delete("host", {}) cls.backend.delete("service", {}) cls.backend.delete("command", {}) cls.backend.delete("livestate", {}) cls.backend.delete("livesynthesis", {}) def test_recalculate(self): # add host data = json.loads(open("cfg/host_srv001.json").read()) self.backend.post("host", data) rh = self.backend.get("host") # Add command data = json.loads(open("cfg/command_ping.json").read()) self.backend.post("command", data) # Check if command right in backend rc = self.backend.get("command") self.assertEqual(rc["_items"][0]["command_name"], "ping") # Add service data = json.loads(open("cfg/service_srv001_ping.json").read()) data["host_name"] = rh["_items"][0]["_id"] data["check_command"] = rc["_items"][0]["_id"] self.backend.post("service", data) # Check if service right in backend rs = self.backend.get("service") self.assertEqual(rs["_items"][0]["service_description"], "ping") self.backend.delete("livestate", {}) self.p.kill() time.sleep(3) self.p = subprocess.Popen( ["uwsgi", "-w", "alignakbackend:app", "--socket", "0.0.0.0:5000", "--protocol=http", "--enable-threads"] ) time.sleep(3) # Check if livestate right recalculate self.backend = Backend("http://127.0.0.1:5000") self.backend.login("admin", "admin", "force") r = self.backend.get("livestate") self.assertEqual(len(r["_items"]), 2) self.assertEqual(r["_items"][1]["last_state"], "OK") self.assertEqual(r["_items"][1]["last_state_type"], "HARD") self.assertEqual(r["_items"][1]["last_check"], 0) self.assertEqual(r["_items"][1]["state_type"], "HARD") self.assertEqual(r["_items"][1]["state"], "OK") self.assertEqual(r["_items"][1]["host_name"], rh["_items"][0]["_id"]) self.assertEqual(r["_items"][1]["service_description"], rs["_items"][0]["_id"]) self.backend.delete("contact", {}) self.p.kill()
def test_3_patch_connection_error(self): """ Backend connection error when updating an object... :return: None """ print('test connection error when updating an object') # Create client API 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'] user_etag = resp['_items'][0]['_etag'] print("stop the alignak backend") self.pid.kill() with assert_raises(BackendException) as cm: data = {'alias': 'modified test'} headers = {'If-Match': user_etag} response = backend.patch('/'.join(['user', user_id]), data=data, headers=headers) assert_true(response['_status'] == 'OK') ex = cm.exception self.assertEqual(ex.code, 1000)
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
def login(self, username=None, password=None): """ Connect to app_backend with credentials in settings.cfg. :return: True if connected or False if not :rtype: bool """ connect = False # Credentials if not username and not password: if self.user: username = self.user['token'] else: username = get_app_config('Alignak', 'username') password = get_app_config('Alignak', 'password') # Create Backend object backend_url = get_app_config('Alignak', 'backend') processes = int(get_app_config('Alignak', 'processes')) self.backend = Backend(backend_url, processes=processes) logger.debug('Backend URL : %s', backend_url) logger.info('Try to connect to app_backend...') if username and password: # Username & password : not recommended, without "widgets.login.py" form. try: connect = self.backend.login(username, password) if connect: self.user['username'] = username self.user['token'] = self.backend.token logger.info('Connection by password: %s', str(connect)) except BackendException as e: # pragma: no cover logger.error('Connection to Backend has failed: %s', str(e)) elif username and not password: # Username as token : recommended self.backend.authenticated = True if self.user: self.backend.token = self.user['token'] else: self.backend.token = username self.user['token'] = username # Test to check token self.connected = True connect = bool(self.get('livesynthesis')) logger.info('Connection by token: %s', str(connect)) else: # Else exit logger.error( 'Connection to Backend has failed.\nCheck [Backend] section in configuration file.' ) connect = False self.connected = connect return connect
class TestRecalculateLivestate(unittest2.TestCase): @classmethod def setUpClass(cls): cls.p = subprocess.Popen(['uwsgi', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads']) time.sleep(3) cls.backend = Backend('http://127.0.0.1:5000') cls.backend.login("admin", "admin", "force") cls.backend.delete("host", {}) cls.backend.delete("service", {}) cls.backend.delete("command", {}) cls.backend.delete("livestate", {}) cls.backend.delete("livesynthesis", {}) def test_recalculate(self): # add host data = json.loads(open('cfg/host_srv001.json').read()) self.backend.post("host", data) rh = self.backend.get('host') # Add command data = json.loads(open('cfg/command_ping.json').read()) self.backend.post("command", data) # Check if command right in backend rc = self.backend.get('command') self.assertEqual(rc['_items'][0]['command_name'], "ping") # Add service data = json.loads(open('cfg/service_srv001_ping.json').read()) data['host_name'] = rh['_items'][0]['_id'] data['check_command'] = rc['_items'][0]['_id'] self.backend.post("service", data) # Check if service right in backend rs = self.backend.get('service') self.assertEqual(rs['_items'][0]['service_description'], "ping") self.backend.delete("livestate", {}) self.p.kill() time.sleep(3) self.p = subprocess.Popen(['uwsgi', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads']) time.sleep(3) # Check if livestate right recalculate self.backend = Backend('http://127.0.0.1:5000') self.backend.login("admin", "admin", "force") r = self.backend.get('livestate') self.assertEqual(len(r['_items']), 2) self.assertEqual(r['_items'][1]['last_state'], 'OK') self.assertEqual(r['_items'][1]['last_state_type'], 'HARD') self.assertEqual(r['_items'][1]['last_check'], 0) self.assertEqual(r['_items'][1]['state_type'], 'HARD') self.assertEqual(r['_items'][1]['state'], 'OK') self.assertEqual(r['_items'][1]['host_name'], rh['_items'][0]['_id']) self.assertEqual(r['_items'][1]['service_description'], rs['_items'][0]['_id']) self.assertEqual(r['_items'][1]['type'], 'service') self.backend.delete("contact", {}) self.p.kill()
def test_0(self): print "" # Login and delete defined contacts ... self.backend.login("admin", "admin") self.backend.delete("contact", {}) # No login possible ... assert not self.backend.login("admin", "admin") # Stop and restart backend ... print ("") print ("stop backend") self.p.kill() print ("") print ("start backend") self.p = subprocess.Popen(['uwsgi', '-w', 'alignakbackend:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads']) time.sleep(1) self.backend = Backend('http://127.0.0.1:5000') # Login is now possible because backend recreated super admin user assert self.backend.login("admin", "admin") print "Super admin is now defined in backend ..." token = self.backend.token assert token print ("") print ("stop backend") self.p.kill()
def test_05_login(self): """ Test with right username / password :return: None """ print('test connection error when login') # Create client API backend = Backend(self.backend_address) print('Login ... must be refused!') with assert_raises(BackendException) as cm: backend.login('admin', 'admin') ex = cm.exception self.assertEqual(ex.code, 1000)
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.debug("inner properties: %s", self.__dict__) logger.debug("received configuration: %s", mod_conf.__dict__) self.url = getattr(mod_conf, "api_url", "http://localhost:5000") self.backend = Backend(self.url) self.backend.token = getattr(mod_conf, "token", "") self.backend_connected = False if self.backend.token == "": self.getToken( getattr(mod_conf, "username", ""), getattr(mod_conf, "password", ""), getattr(mod_conf, "allowgeneratetoken", False), )
def setUpClass(cls): # Set test mode for applications backend os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ['ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-backend-import-test' os.environ['ALIGNAK_BACKEND_CONFIGURATION_FILE'] = './cfg/settings/settings.json' cls.maxDiff = None # Delete used mongo DBs exit_code = subprocess.call( shlex.split('mongo %s --eval "db.dropDatabase()"' % os.environ['ALIGNAK_BACKEND_MONGO_DBNAME']) ) assert exit_code == 0 time.sleep(1) test_dir = os.path.dirname(os.path.realpath(__file__)) print("Current test directory: %s" % test_dir) print("Starting Alignak backend...") cls.p = subprocess.Popen(['uwsgi', '--plugin', 'python', '-w', 'alignak_backend.app:app', '--socket', '0.0.0.0:5000', '--protocol=http', '--enable-threads', '--pidfile', '/tmp/uwsgi.pid']) time.sleep(1) print("Started as %s" % cls.p.pid) cls.backend = Backend('http://127.0.0.1:5000') cls.backend.login("admin", "admin", "force") cls.backend.delete("host", {}) cls.backend.delete("service", {}) cls.backend.delete("command", {}) cls.backend.delete("livesynthesis", {})
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_2_all_pages(self): """ Get all items (so all pages) of a resource :return: None """ print('') print('get all elements on an endpoint') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Get all elements print('get all hostgroups at once') params = {'max_results': 3} items = backend.get_all('hostgroup', params=params) hosts = items['_items'] self.assertEqual(len(hosts), 101)
def test_recalculate(self): # add host data = json.loads(open("cfg/host_srv001.json").read()) self.backend.post("host", data) rh = self.backend.get("host") # Add command data = json.loads(open("cfg/command_ping.json").read()) self.backend.post("command", data) # Check if command right in backend rc = self.backend.get("command") self.assertEqual(rc["_items"][0]["command_name"], "ping") # Add service data = json.loads(open("cfg/service_srv001_ping.json").read()) data["host_name"] = rh["_items"][0]["_id"] data["check_command"] = rc["_items"][0]["_id"] self.backend.post("service", data) # Check if service right in backend rs = self.backend.get("service") self.assertEqual(rs["_items"][0]["service_description"], "ping") self.backend.delete("livesynthesis", {}) self.p.kill() time.sleep(3) self.p = subprocess.Popen( ["uwsgi", "-w", "alignakbackend:app", "--socket", "0.0.0.0:5000", "--protocol=http", "--enable-threads"] ) time.sleep(3) # Check if livestate right recalculate self.backend = Backend("http://127.0.0.1:5000") self.backend.login("admin", "admin", "force") r = self.backend.get("livesynthesis") self.assertEqual(len(r["_items"]), 1) self.assertEqual(r["_items"][0]["hosts_total"], 1) self.assertEqual(r["_items"][0]["hosts_up_hard"], 0) self.assertEqual(r["_items"][0]["hosts_up_soft"], 0) self.assertEqual(r["_items"][0]["hosts_down_hard"], 0) self.assertEqual(r["_items"][0]["hosts_down_soft"], 0) self.assertEqual(r["_items"][0]["hosts_unreachable_hard"], 1) self.assertEqual(r["_items"][0]["hosts_unreachable_soft"], 0) self.assertEqual(r["_items"][0]["hosts_acknowledged"], 0) self.assertEqual(r["_items"][0]["services_total"], 1) self.assertEqual(r["_items"][0]["services_ok_hard"], 1) self.assertEqual(r["_items"][0]["services_ok_soft"], 0) self.assertEqual(r["_items"][0]["services_warning_hard"], 0) self.assertEqual(r["_items"][0]["services_warning_soft"], 0) self.assertEqual(r["_items"][0]["services_critical_hard"], 0) self.assertEqual(r["_items"][0]["services_critical_soft"], 0) self.assertEqual(r["_items"][0]["services_unknown_hard"], 0) self.assertEqual(r["_items"][0]["services_unknown_soft"], 0) self.backend.delete("contact", {}) self.p.kill()
def test_02_bad_parameters(self): global backend_address print '' print 'test refused connection with username/password' # Create client API backend = Backend(backend_address) print "no username or no password, login refused - exception 1001" with assert_raises(BackendException) as cm: result = backend.login(None, None) ex = cm.exception # raised exception is available through exception property of context print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'authenticated:', backend.authenticated print "invalid username/password, login refused - returns false" result = backend.login('admin', 'bad_password') assert_false(backend.authenticated)
def test_2_all_pages(self): """ Get all items (so all pages) of a resource :return: None """ print('get all elements on an endpoint') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Get all elements print('get all hostgroups at once') params = {'max_results': 3} items = backend.get_all('hostgroup', params=params) hostgroups = items['_items'] for hostgroup in hostgroups: print("Group: %s" % hostgroup['name']) self.assertEqual(len(hostgroups), 101)
def test_1_patch_successful(self): """ Test patch a user successfully :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'] user_etag = resp['_items'][0]['_etag'] data = {'alias': 'modified test'} headers = {'If-Match': user_etag} response = backend.patch('/'.join(['user', user_id]), data=data, headers=headers) assert_true(response['_status'] == 'OK')
def test_1_domains(self): """ Test get domains (= all resource/enpoints available) :return: None """ # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Get all available endpoints print('get all domains') # Filter the templates ... items = backend.get_domains() print("Got %d elements: %s" % (len(items), items)) assert_true('_items' not in items) # assert_true(len(items) == 26) for item in items: assert_true('href' in item) assert_true('title' in item) print("Domain: ", item)
def test_03_token_generate(self): global backend_address print '' print 'force authentication token generation' # Create client API backend = Backend(backend_address) print 'request new token generation' result = backend.login('admin', 'admin', 'force') assert_true(backend.authenticated) token1 = backend.token print 'token1:', token1 print 'request new token generation' result = backend.login('admin', 'admin', 'force') print 'authenticated:', backend.authenticated assert_true(backend.authenticated) token2 = backend.token print 'token2:', token2 assert_true(token1 != token2)
def configure(self, endpoint): """ Initialize backend connection ... """ # Backend API start point if endpoint.endswith('/'): # pragma: no cover - test url is complying ... self.url_endpoint_root = endpoint[0:-1] else: self.url_endpoint_root = endpoint logger.info("backend endpoint: %s", self.url_endpoint_root) self.backend = Backend(self.url_endpoint_root)
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_2_patch_exception(self): """ Test patch a user with errors (so exceptions) :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'] user_etag = resp['_items'][0]['_etag'] with assert_raises(BackendException) as cm: data = {'alias': 'modified with no header'} backend.patch('/'.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 = {'bad_field': 'bad field name ... unknown in data model'} headers = {'If-Match': user_etag} backend.patch('/'.join(['user', user_id]), data=data, headers=headers, inception=True) ex = cm.exception assert_true(ex.code == 422) with assert_raises(BackendException) as cm: data = {'alias': 'modified test again and again'} headers = {'If-Match': "567890987678"} response = backend.patch('/'.join(['user', user_id]), data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 412, str(ex))
def test_3_delete_connection_error(self): """ Backend connection error when deleting an object... :return: None """ print('test connection error when deleting an object') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Create a new timeperiod data = { "name": "Testing TP 2", "alias": "Test TP 2", "dateranges": [{ u'monday': u'09:00-17:00' }, { u'tuesday': u'09:00-17:00' }, { u'wednesday': u'09:00-17:00' }, { u'thursday': u'09:00-17:00' }, { u'friday': u'09:00-17:00' }], "_realm": self.realmAll_id } response = backend.post('timeperiod', data=data) assert_true(response['_status'] == 'OK') timeperiod_id = response['_id'] timeperiod_etag = response['_etag'] headers = {'If-Match': timeperiod_etag} response = backend.delete('/'.join(['timeperiod', timeperiod_id]), headers=headers) assert_true(response['_status'] == 'OK') print("stop the alignak backend") self.pid.kill() with assert_raises(BackendException) as cm: headers = {'If-Match': timeperiod_etag} response = backend.delete('/'.join(['timeperiod', timeperiod_id]), headers=headers) assert_true(response['_status'] == 'OK') ex = cm.exception self.assertEqual(ex.code, 1000)
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)
def test_03_token_generate(self): """ Test token generation :return: None """ print('') print('force authentication token generation') # Create client API backend = Backend(self.backend_address) print('request new token generation') backend.login('admin', 'admin', 'force') assert_true(backend.authenticated) token1 = backend.token print('token1:', token1) print('request new token generation') backend.login('admin', 'admin', 'force') print('authenticated:', backend.authenticated) assert_true(backend.authenticated) token2 = backend.token print('token2:', token2) assert_true(token1 != token2)
def test_02_bad_parameters(self): """ Test with bad username/password :return: None """ print('') print('test refused connection with username/password') # Create client API backend = Backend(self.backend_address) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login(None, None) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1000, str(ex)) assert_true("Missing mandatory parameters" in str(ex)) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login('', '') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1000, str(ex)) assert_true("Missing mandatory parameters" in str(ex)) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login('admin', '') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1000, str(ex)) print("invalid username/password, login refused") result = backend.login('admin', 'bad_password') assert_false(result) assert_false(backend.authenticated)
def test_2_patch_exception(self): """ Test patch a user with errors (so exceptions) :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'] user_etag = resp['_items'][0]['_etag'] with assert_raises(BackendException) as cm: data = {'alias': 'modified with no header'} backend.patch('/'.join(['user', user_id]), data=data) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1005, str(ex)) with assert_raises(BackendException) as cm: data = {'bad_field': 'bad field name ... unknown in data model'} headers = {'If-Match': user_etag} backend.patch('/'.join(['user', user_id]), data=data, headers=headers, inception=True) ex = cm.exception print('exception:', str(ex.code), ex.message, ex.response) if "_issues" in ex.response: for issue in ex.response["_issues"]: print("Issue: %s - %s" % (issue, ex.response["_issues"][issue])) assert_true(ex.code == 422) assert_true(ex.response["_issues"]) with assert_raises(BackendException) as cm: data = {'alias': 'modified test again and again'} headers = {'If-Match': "567890987678"} response = backend.patch('/'.join(['user', user_id]), data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 412, str(ex))
def __init__(self, backend_endpoint='http://127.0.0.1:5000', glpi=None): """ Create an instance """ # Set a unique id for each DM object self.__class__.id += 1 # Associated backend object self.backend_endpoint = backend_endpoint self.backend = Backend(backend_endpoint) # Associated Glpi backend object self.glpi = None if glpi: self.glpi = Glpi(glpi.get('glpi_ws_backend', None)) self.glpi_ws_login = glpi.get('glpi_ws_login', None) self.glpi_ws_password = glpi.get('glpi_ws_password', None) # Backend available objects (filled with objects received from backend) # self.backend_available_objets = [] # Get known objects type from the imported modules # Search for classes including an _type attribute self.known_classes = [] for k, v in globals().items(): if isinstance(globals()[k], type) and '_type' in globals()[k].__dict__: self.known_classes.append(globals()[k]) logger.debug( "Known class %s for object type: %s", globals()[k], globals()[k].getType() ) self.connected = False self.logged_in_user = None self.connection_message = None self.loading = 0 self.loaded = False self.refresh_required = False self.refresh_done = False self.updated = datetime.utcnow()
def test_02_bad_parameters(self): """ Test with bad username/password :return: None """ print('') print('test refused connection with username/password') # Create client API backend = Backend(self.backend_address) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login(None, None) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) assert_true("Missing mandatory parameters" in str(ex)) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login('', '') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) assert_true("Missing mandatory parameters" in str(ex)) print('Login - missing credentials ...') with assert_raises(BackendException) as cm: backend.login('admin', '') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print("invalid username/password, login refused - returns false") result = backend.login('admin', 'bad_password') assert_false(result) assert_false(backend.authenticated)
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.debug("inner properties: %s", self.__dict__) logger.debug("received configuration: %s", mod_conf.__dict__) self.url = getattr(mod_conf, 'api_url', 'http://localhost:5000') self.backend = Backend(self.url) self.backend.token = getattr(mod_conf, 'token', '') self.backend_connected = False if self.backend.token == '': self.getToken(getattr(mod_conf, 'username', ''), getattr(mod_conf, 'password', ''), getattr(mod_conf, 'allowgeneratetoken', False)) self.logged_in = self.backendConnection() self.ref_live = { 'host': {}, 'service': {} } self.mapping = { 'host': {}, 'service': {} } self.hosts = {} self.services = {} self.loaded_hosts = False self.loaded_services = False
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_2_delete_exceptions(self): """ Test delete a timeperiod with errors (so exceptions) :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # Create a new timeperiod data = { "name": "Testing TP", "alias": "Test TP", "dateranges": [{ u'monday': u'09:00-17:00' }, { u'tuesday': u'09:00-17:00' }, { u'wednesday': u'09:00-17:00' }, { u'thursday': u'09:00-17:00' }, { u'friday': u'09:00-17:00' }], "_realm": self.realmAll_id } response = backend.post('timeperiod', data=data) assert_true(response['_status'] == 'OK') timeperiod_id = response['_id'] timeperiod_etag = response['_etag'] with assert_raises(BackendException) as cm: headers = {'If-Match': timeperiod_etag} response = backend.delete( '/'.join(['timeperiod', '5' + timeperiod_id]), headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 404, str(ex))
def test_4_connection_error(self): """ Backend connection error when getting an object... :return: None """ print('test connection error when getting an object') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') print("stop the alignak backend") self.pid.kill() with assert_raises(BackendException) as cm: print('get all hostgroups at once') params = {'max_results': 3} backend.get_all('hostgroup', params=params) ex = cm.exception self.assertEqual(ex.code, 1000)
def test_1_delete_successful(self): """ Test delete a timeperiod successfully :return: None """ backend = Backend(self.backend_address) backend.login('admin', 'admin') # Create a new timeperiod data = { "name": "Testing TP", "alias": "Test TP", "dateranges": [{ u'monday': u'09:00-17:00' }, { u'tuesday': u'09:00-17:00' }, { u'wednesday': u'09:00-17:00' }, { u'thursday': u'09:00-17:00' }, { u'friday': u'09:00-17:00' }], "_realm": self.realmAll_id } response = backend.post('timeperiod', data=data) assert_true(response['_status'] == 'OK') timeperiod_id = response['_id'] timeperiod_etag = response['_etag'] headers = {'If-Match': timeperiod_etag} response = backend.delete('/'.join(['timeperiod', timeperiod_id]), headers=headers) assert_true(response['_status'] == 'OK')
def test_12_all_pages(self): global backend_address print '' print 'get all elements on an endpoint' # Create client API backend = Backend(backend_address) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) # Get all available endpoints print 'get all domains' items = backend.get_domains() print "Got %d elements:" % len(items) assert_true('_items' not in items) assert_true(len(items) > 0) for item in items: if item['href'] in ['loghost', 'logservice']: continue assert_true('href' in item) assert_true('title' in item) print "Domain: ", item # Get all elements print 'get all %s at once' % item['href'] items = backend.get_all(item['href']) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('_etag' in item) print "etag: ", item['_etag'] # Get all available endpoints print 'get all domains' items = backend.get_domains() print "Got %d elements:" % len(items) assert_true('_items' not in items) assert_true(len(items) > 0) for item in items: if item['href'] in ['loghost', 'logservice']: continue assert_true('href' in item) assert_true('title' in item) print "Domain: ", item # Get all elements print 'get all %s at once' % item['href'] params = {'max_results': 2} items = backend.get_all(item['href'], params=params) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('_etag' in item) print "etag: ", item['_etag'] # Get all hosts print 'get all hosts at once, 1 item per page' params = {'max_results':1} items = backend.get_all(item['href'], params=params) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('_etag' in item) print "etag: ", item['_etag']
def test_04_connection_username(self): global backend_address print '' print 'test accepted connection with username/password' # Create client API backend = Backend(backend_address) print 'Login ...' result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) print 'Logout ...' result = backend.logout() print 'authenticated:', backend.authenticated print 'token:', backend.token assert_false(backend.authenticated) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) print 'Logout ...' result = backend.logout() print 'authenticated:', backend.authenticated print 'token:', backend.token assert_false(backend.authenticated) print 'Logout ...' result = backend.logout() print 'authenticated:', backend.authenticated print 'token:', backend.token assert_false(backend.authenticated) print 'get object ... must be refused!' with assert_raises(BackendException) as cm: items = backend.get('host') ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'get_all object ... must be refused!' with assert_raises(BackendException) as cm: items = backend.get_all('host') ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'get all domains ... must be refused!' with assert_raises(BackendException) as cm: items = backend.get_domains() ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'post data ... must be refused!' with assert_raises(BackendException) as cm: data = { 'fake': 'fake' } response = backend.post('contact', data=data) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'patch data ... must be refused!' with assert_raises(BackendException) as cm: data = { 'fake': 'fake' } headers = { 'If-Match': '' } response = backend.patch('contact', data=data, headers=headers) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex)) print 'delete data ... must be refused!' with assert_raises(BackendException) as cm: data = { 'fake': 'fake' } headers = { 'If-Match': '' } response = backend.delete('contact', headers=headers) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1001, str(ex))
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.default_realm = None 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_connected = False self.backend_connection_retry_planned = 0 try: self.backend_connection_retry_delay = int( getattr(mod_conf, 'backend_connection_retry_delay', '10')) except ValueError: self.backend_connection_retry_delay = 10 logger.info("backend connection retry delay: %.2f seconds", self.backend_connection_retry_delay) 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) self.backend_count = int(getattr(mod_conf, 'backend_count', '50')) logger.info("backend pagination count: %d items", self.backend_count) self.backend_token = getattr(mod_conf, 'token', '') self.backend = Backend(self.url, self.client_processes) self.manage_update_program_status = getattr(mod_conf, 'update_program_status', '0') == '1' logger.info("manage update_program_status broks: %s", self.manage_update_program_status) # Log in to the backend self.logged_in = False self.backend_connected = self.backend_connection() # Get the default realm self.default_realm = self.get_default_realm() self.ref_live = {'host': {}, 'service': {}, 'user': {}} self.mapping = {'host': {}, 'service': {}, 'user': {}} # Objects reference self.load_protect_delay = int( getattr(mod_conf, 'load_protect_delay', '300')) self.last_load = 0 # Backend to be posted data self.logcheckresults = []
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
def test_multiprocess(self): """ Test multiprocess get right all elements :return: None """ print('') print('test creation') print('Create client API for URL:', self.backend_address) backend = Backend(self.backend_address, 8) backend.login('admin', 'admin') items = backend.get('realm') realm_id = items['_items'][0]['_id'] # add 2000 commands backend.delete("command", {}) data = {'command_line': 'check_ping', '_realm': realm_id} for i in range(1, 2001): data['name'] = "cmd %d" % i backend.post('command', data) # get without multiprocess backend_yannsolo = Backend(self.backend_address) backend_yannsolo.login('admin', 'admin') start_time = time.time() resp = backend_yannsolo.get_all('command', {'max_results': 20}) threads_1 = time.time() - start_time self.assertEqual(len(resp['_items']), 2002, "Number of commands in non multiprocess mode") # get with multiprocess (8 processes) start_time = time.time() resp = backend.get_all('command', {'max_results': 20}) threads_8 = time.time() - start_time self.assertEqual(len(resp['_items']), 2002, "Number of commands in multiprocess mode") ids = [] for dat in resp['_items']: ids.append(dat['_id']) self.assertEqual(len(ids), 2002, "Number of id") # remove duplicates ids_final = set(ids) self.assertEqual(len(ids_final), 2002, "Number of id unique") print(threads_1) print(threads_8)
class AppBackend(object): """ Class who collect informations with Backend-Client and returns data for Alignak-App. """ def __init__(self): self.backend = None self.user = {} self.connected = False self.app = None def login(self, username=None, password=None): """ Connect to app_backend with credentials in settings.cfg. :return: True if connected or False if not :rtype: bool """ connect = False # Credentials if not username and not password: if self.user: username = self.user['token'] else: username = get_app_config('Alignak', 'username') password = get_app_config('Alignak', 'password') # Create Backend object backend_url = get_app_config('Alignak', 'backend') processes = int(get_app_config('Alignak', 'processes')) self.backend = Backend(backend_url, processes=processes) logger.debug('Backend URL : %s', backend_url) logger.info('Try to connect to app_backend...') if username and password: # Username & password : not recommended, without "widgets.login.py" form. try: connect = self.backend.login(username, password) if connect: self.user['username'] = username self.user['token'] = self.backend.token logger.info('Connection by password: %s', str(connect)) except BackendException as e: # pragma: no cover logger.error('Connection to Backend has failed: %s', str(e)) elif username and not password: # Username as token : recommended self.backend.authenticated = True if self.user: self.backend.token = self.user['token'] else: self.backend.token = username self.user['token'] = username # Test to check token self.connected = True connect = bool(self.get('livesynthesis')) logger.info('Connection by token: %s', str(connect)) else: # Else exit logger.error( 'Connection to Backend has failed.\nCheck [Backend] section in configuration file.' ) connect = False self.connected = connect return connect def get(self, endpoint, params=None, projection=None): """ GET on alignak Backend REST API. :param endpoint: endpoint (API URL) :type endpoint: str :param params: dict of parameters for the app_backend API :type params: dict|None :param projection: list of field to get, if None, get all :type projection: list|None :return desired request of app_backend :rtype: dict """ request = None if params is None: params = {'max_results': 50} if projection is not None: generate_proj = {} for field in projection: generate_proj[field] = 1 params['projection'] = json.dumps(generate_proj) if self.connected: # Request try: request = self.backend.get_all(endpoint, params) logger.debug('GET: %s', endpoint) logger.debug('..with params: %s', str(params)) logger.debug('...Response > %s', str(request['_status'])) except BackendException as e: logger.error('GET failed: %s', str(e)) logger.warning( 'Application will check the connection with Backend...') self.connected = False if not self.app.reconnect_mode: self.app.reconnecting.emit(self, str(e)) return request return request def post(self, endpoint, data, headers=None): # pragma: no cover - Post already test by client """ POST on alignak Backend REST API :param endpoint: endpoint (API URL) :type endpoint: str :param data: properties of item to create | add :type data: dict :param headers: headers (example: Content-Type) :type headers: dict|None :return: response (creation information) :rtype: dict """ resp = None if self.connected: try: resp = self.backend.post(endpoint, data, headers=headers) logger.debug('POST on %s', endpoint) logger.debug('..with data: %s', str(data)) logger.debug('...Response > %s', str(resp)) except BackendException as e: logger.error('POST failed: %s', str(e)) logger.warning( 'Application will check the connection with Backend...') self.connected = False if not self.app.reconnect_mode: self.app.reconnecting.emit(self, str(e)) return resp return resp def get_host(self, key, value, projection=None): """ Return the host corresponding to "key"/"value" pair :param key: key corresponding to value :type key: str :param value: value of key :type value: str :param projection: list of field to get, if None, get all :type projection: list|None :return: None if not found or item dict :rtype: dict|None """ params = {'where': json.dumps({'_is_template': False, key: value})} hosts = self.get('host', params, projection=projection) if hosts and len(hosts['_items']) > 0: # pylint: disable=len-as-condition wanted_host = hosts['_items'][0] else: wanted_host = None return wanted_host def get_service(self, host_id, service_id, projection=None): """ Returns the desired service of the specified host :param host_id: "_id" of host :type host_id: str :param service_id: "_id" of wanted service :type service_id: str :param projection: list of field to get, if None, get all :type projection: list|None :return: wanted service :rtype: dict """ params = { 'where': json.dumps({ '_is_template': False, 'host': host_id }) } services = self.get('service', params=params, projection=projection) wanted_service = None if services: if len(services['_items']) > 0: # pylint: disable=len-as-condition wanted_service = services['_items'][0] for service in services['_items']: if service['_id'] == service_id: wanted_service = service return wanted_service def get_host_with_services(self, host_name): """ Returns the desired host and all its services :param host_name: desired host :type host_name: str :return dict with host data and its associated services :rtype: dict """ host_data = None host_projection = [ 'name', 'alias', 'ls_state', '_id', 'ls_acknowledged', 'ls_downtimed', 'ls_last_check', 'ls_output', 'address', 'business_impact', 'parents', 'ls_last_state_changed' ] host = self.get_host('name', host_name, projection=host_projection) if host: params = { 'where': json.dumps({ '_is_template': False, 'host': host['_id'] }) } service_projection = [ 'name', 'alias', 'display_name', 'ls_state', 'ls_acknowledged', 'ls_downtimed', 'ls_last_check', 'ls_output', 'business_impact', 'customs', '_overall_state_id', 'aggregation', 'ls_last_state_changed' ] services = self.get('service', params=params, projection=service_projection) services_host = services['_items'] host_data = {'host': host, 'services': services_host} return host_data def get_user(self, projection=None): """ Get current user. The token must already be acquired :param projection: list of field to get, if None, get all :type projection: list|None :return user items :rtype dict|None """ params = {'where': json.dumps({'token': self.user['token']})} if projection is not None: generate_proj = {} for field in projection: generate_proj[field] = 1 params['projection'] = json.dumps(generate_proj) user = self.get('user', params, projection=projection) if user: return user['_items'][0] return None def synthesis_count(self): """ Get on "synthesis" endpoint and return the states of hosts and services :return: states of hosts and services. :rtype: dict """ states = { 'hosts': { 'up': 0, 'down': 0, 'unreachable': 0, 'acknowledge': 0, 'downtime': 0 }, 'services': { 'ok': 0, 'critical': 0, 'unknown': 0, 'warning': 0, 'unreachable': 0, 'acknowledge': 0, 'downtime': 0 } } live_synthesis = self.get('livesynthesis') if live_synthesis: for realm in live_synthesis['_items']: states['hosts']['up'] += realm['hosts_up_soft'] states['hosts']['up'] += realm['hosts_up_hard'] states['hosts']['unreachable'] += realm[ 'hosts_unreachable_soft'] states['hosts']['unreachable'] += realm[ 'hosts_unreachable_hard'] states['hosts']['down'] += realm['hosts_down_soft'] states['hosts']['down'] += realm['hosts_down_hard'] states['hosts']['acknowledge'] += realm['hosts_acknowledged'] states['hosts']['downtime'] += realm['hosts_in_downtime'] states['services']['ok'] += realm['services_ok_soft'] states['services']['ok'] += realm['services_ok_hard'] states['services']['warning'] += realm['services_warning_soft'] states['services']['warning'] += realm['services_warning_hard'] states['services']['critical'] += realm[ 'services_critical_soft'] states['services']['critical'] += realm[ 'services_critical_hard'] states['services']['unknown'] += realm['services_unknown_soft'] states['services']['unknown'] += realm['services_unknown_hard'] states['services']['unreachable'] += realm[ 'services_unreachable_soft'] states['services']['unreachable'] += realm[ 'services_unreachable_hard'] states['services']['acknowledge'] += realm[ 'services_acknowledged'] states['services']['downtime'] += realm['services_in_downtime'] logger.info('Store current states...') return states
def test_3_page_after_page(self): """ Get page after page manually :return: None """ print('backend connection with username/password') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Start with first page ... max_results=3 last_page = False parameters = {'max_results': 3, 'page': 1} items = [] while not last_page: resp = backend.get('hostgroup', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) assert_equal(total, 101) assert_equal(max_results, 3) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 else: last_page = True assert_equal(page_number, 34) items.extend(resp['_items']) print("----------") print("Got %d elements:" % len(items)) assert_equal(len(items), 101) # Start with first page ... max_results=10 last_page = False parameters = {'max_results': 10, 'page': 1} items = [] while not last_page: resp = backend.get('hostgroup', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) assert_equal(total, 101) assert_equal(max_results, 10) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 else: last_page = True assert_equal(page_number, 11) items.extend(resp['_items']) # Start with first page ... no max_results last_page = False parameters = {'page': 1} items = [] while not last_page: resp = backend.get('hostgroup', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) assert_equal(total, 101) assert_equal(max_results, 25) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 else: last_page = True assert_equal(page_number, 5) items.extend(resp['_items']) print("----------") print("Got %d elements:" % len(items)) assert_equal(len(items), 101)
def test_13_page_after_page(self): global backend_address print '' print 'backend connection with username/password' # Create client API backend = Backend(backend_address) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) # Start with first page ... last_page = False parameters = { 'where': '{"register":true}', 'max_results': 2, 'page': 1 } items = [] while not last_page: resp = backend.get('host', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) print resp['_meta'] page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) print "Got %d elements out of %d (page %d):" % (max_results, total, page_number) for item in resp['_items']: assert_true('host_name' in item) print "Host: ", item['host_name'] if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 parameters['max_results'] = max_results else: last_page = True items.extend(resp['_items']) print "----------" print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('host_name' in item) print "Host: ", item['host_name'] # Start with first page ... last_page = False parameters = { 'where': '{"register":true}', 'max_results': 10, 'page': 1 } items = [] while not last_page: resp = backend.get('service', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) print resp['_meta'] page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) print "Got %d elements out of %d (page %d):" % (max_results, total, page_number) for item in resp['_items']: assert_true('host_name' in item) assert_true('service_description' in item) print "Service: %s/%s" % (item['host_name'], item['service_description']) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 parameters['max_results'] = max_results else: last_page = True items.extend(resp['_items']) print "----------" print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('host_name' in item) assert_true('service_description' in item) print "Service: %s/%s" % (item['host_name'], item['service_description'])
def test_21_post_patch_delete(self): global backend_address print '' print 'post/delete/patch some elements' # Create client API backend = Backend(backend_address) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) # Get all contacts print 'get all contacts at once' parameters = { 'where': '{"register":true}' } items = backend.get_all('contact', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) for item in items: assert_true('contact_name' in item) assert_true('_id' in item) assert_true('_etag' in item) print "Contact: ", item['contact_name'], item['_id'] # Test contact still exists ... delete him! if item['contact_name'] == 'test': headers = { 'If-Match': item['_etag'] } response = backend.delete('/'.join(['contact', item['_id']]), headers) print "Response:", response # Get all timeperiods print 'get all timeperiods at once' parameters = { 'where': '{"register":true}' } items = backend.get_all('timeperiod', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) tp_id = '' for item in items: assert_true('timeperiod_name' in item) assert_true('_id' in item) tp_id = item['_id'] print item print "TP: %s (%s), id=%s" % (item['timeperiod_name'], item['name'], item['_id']) if not tp_id: # Create a new timeperiod print 'create a timeperiod' data = { "timeperiod_name": "test", "name": "Testing TP", "alias": "Test TP", "dateranges": [ {u'monday': u'09:00-17:00'}, {u'tuesday': u'09:00-17:00'}, {u'wednesday': u'09:00-17:00'}, {u'thursday': u'09:00-17:00'}, {u'friday': u'09:00-17:00'} ], "register": True } response = backend.post('timeperiod', data=data) print "Response:", response assert_true('_created' in response) assert_true('_updated' in response) assert_true(response['_created'] == response['_updated']) # Get all timeperiods print 'get all timeperiods at once' parameters = { 'where': '{"register":true}' } items = backend.get_all('timeperiod', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) tp_id = '' for item in items: assert_true('timeperiod_name' in item) assert_true('_id' in item) tp_id = item['_id'] print "TP: %s (%s), id=%s" % (item['timeperiod_name'], item['name'], item['_id']) assert_true(tp_id != '') # Create a new contact, bad parameters print 'create a contact, missing fields' # Mandatory field contact_name is missing ... data = { "name": "Testing contact", "alias": "Fred", "back_role_super_admin": False, "back_role_admin": [], "min_business_impact": 0, } with assert_raises(BackendException) as cm: response = backend.post('contact', data=data) ex = cm.exception print 'exception:', str(ex.code), ex.message, ex.response if "_issues" in ex.response: for issue in ex.response["_issues"]: print "Issue: %s - %s" %(issue, ex.response["_issues"][issue]) assert_true(ex.code == 422) assert_true(ex.response["_issues"]) # Create a new contact print 'create a contact' data = { "contact_name": "test", "name": "Testing contact", "alias": "Fred", "back_role_super_admin": False, "back_role_admin": [], "min_business_impact": 0, "email": "*****@*****.**", "is_admin": False, "expert": False, "can_submit_commands": False, "host_notifications_enabled": True, "host_notification_period": tp_id, "host_notification_commands": [ ], "host_notification_options": [ "d", "u", "r" ], "service_notifications_enabled": True, "service_notification_period": tp_id, "service_notification_commands": [ ], "service_notification_options": [ "w", "u", "c", "r" ], "retain_status_information": False, "note": "Monitoring template : default", "retain_nonstatus_information": False, "definition_order": 100, "address1": "", "address2": "", "address3": "", "address4": "", "address5": "", "address6": "", "pager": "", "notificationways": [], "register": True } response = backend.post('contact', data=data) print "Response:", response assert_true('_created' in response) assert_true('_updated' in response) assert_true(response['_created'] == response['_updated']) # Get all contacts print 'get all contacts at once' # Filter the templates ... parameters = { 'where': '{"register":true}' } items = backend.get_all('contact', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) assert_true(len(items) > 0) # Search test contact contact_id = '' contact_etag = '' for item in items: assert_true('contact_name' in item) print "Contact: ", item['contact_name'] if item['contact_name'] == 'test': contact_id = item['_id'] contact_etag = item['_etag'] assert_true(contact_id != '') assert_true(contact_etag != '') print 'changing contact alias ... no _etag' print 'id:', contact_id print 'etag:', contact_etag with assert_raises(BackendException) as cm: data = {'alias': 'modified with no header'} # headers['If-Match'] = contact_etag response = backend.patch('/'.join(['contact', contact_id]), data=data) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1005, str(ex)) print 'changing contact alias ...' print 'id:', contact_id print 'etag:', contact_etag data = {'alias': 'modified test'} headers = {'If-Match': contact_etag} response = backend.patch('/'.join(['contact', contact_id]), data=data, headers=headers) print 'response:', response assert_true(response['_status'] == 'OK') response = backend.get('/'.join(['contact', contact_id])) print 'response:', response assert_true(response['alias'] == 'modified test') print 'changing contact alias ... bad _etag (inception = True)' print 'id:', contact_id print 'etag:', contact_etag data = {'alias': 'modified test again'} headers = {'If-Match': contact_etag} response = backend.patch('/'.join(['contact', contact_id]), data=data, headers=headers, inception=True) print 'response:', response assert_true(response['_status'] == 'OK') response = backend.get('/'.join(['contact', contact_id])) print 'response:', response assert_true(response['alias'] == 'modified test again') print 'changing contact unknown field ... must be refused' print 'id:', contact_id print 'etag:', contact_etag with assert_raises(BackendException) as cm: data = {'bad_field': 'bad field name ... unknown in data model'} headers = {'If-Match': contact_etag} response = backend.patch('/'.join(['contact', contact_id]), data=data, headers=headers, inception=True) ex = cm.exception print 'exception:', str(ex.code), ex.message, ex.response if "_issues" in ex.response: for issue in ex.response["_issues"]: print "Issue: %s - %s" %(issue, ex.response["_issues"][issue]) assert_true(ex.code == 422) assert_true(ex.response["_issues"]) print 'changing contact alias ... bad _etag (inception = False)' print 'id:', contact_id print 'etag:', contact_etag with assert_raises(BackendException) as cm: data = {'alias': 'modified test again and again'} headers = {'If-Match': contact_etag} response = backend.patch('/'.join(['contact', contact_id]), data=data, headers=headers) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 412, str(ex)) response = backend.get('/'.join(['contact', contact_id])) print 'response:', response # Not changed ! assert_true(response['alias'] == 'modified test again') response = backend.get('/'.join(['contact', contact_id])) print 'response:', response # Not changed ! assert_true(response['alias'] == 'modified test again') print 'deleting contact ... bad href' with assert_raises(BackendException) as cm: headers = { 'If-Match': item['_etag'] } response = backend.delete('/'.join(['contact', '5'+item['_id']]), headers) print "Response:", response ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1003, str(ex))
class __BackendConnection(object): """ Base class for all objects state management (displayed icon, ...) """ def __init__(self, backend_endpoint='http://127.0.0.1:5002'): self.backend_endpoint = backend_endpoint self.backend = Backend(backend_endpoint) self.connected = False def login(self, username, password=None): """ Log into the backend If password is provided, use the backend login function to authenticate the user If no password is provided, the username is assumed to be an authentication token and we use the backend connect function. """ logger.info("login, connection requested, login: %s", username) self.connected = False if not username: # pragma: no cover, should not happen # Refuse backend login without username logger.warning("No login without username!") return self.connected if not password: # pragma: no cover, should not happen # Set backend token (no login request). logger.debug("Update backend token") self.backend.token = username self.connected = True return self.connected try: # Backend real login logger.info("Requesting backend authentication, username: %s", username) self.connected = self.backend.login(username, password) except BackendException: # pragma: no cover, should not happen logger.warning("configured backend is not available!") except Exception as e: # pragma: no cover, should not happen logger.warning("User login exception: %s", str(e)) logger.error("traceback: %s", traceback.format_exc()) logger.info("login result: %s", self.connected) return self.connected def logout(self): """ Log out from the backend Do nothing except setting 'connected' attribute to False """ logger.info("logout") self.connected = False def count(self, object_type, params=None): """ If params is a string, it is considered to be an object id and params is modified to {'_id': params}. Else, params is used to 'get' objects from the backend. """ logger.debug("count, %s, params: %s", object_type, params) if isinstance(params, basestring): params = {'where': {'_id': params}} # Update backend search parameters if params is None: params = {'page': 0, 'max_results': 1} if 'where' in params: params['where'] = json.dumps(params['where']) if 'max_results' not in params: params['max_results'] = 1 logger.debug( "count, search in the backend for %s: parameters=%s", object_type, params ) try: result = self.backend.get(object_type, params=params) except BackendException as e: # pragma: no cover, simple protection logger.warning("count, backend exception for %s: %s", object_type, str(e)) return 0 logger.debug("count, search result for %s: result=%s", object_type, result) if not result['_status'] == 'OK': # pragma: no cover, should not happen error = [] if "content" in result: error.append(result['content']) if "_issues" in result: error.append(result['_issues']) logger.warning("count, %s: %s, not found: %s", object_type, params, error) return 0 # If more than one element is found, we get an _items list if '_items' in result: logger.debug("count, found in the backend: %s: %s", object_type, result['_items']) return result['_meta']['total'] return 0 # pragma: no cover, simple protection def get(self, object_type, params=None, all_elements=False): """ If params is a string, it is considered to be an object id and params is modified to {'_id': params}. Else, params is used to 'get' objects from the backend. Returns an object or an array of matching objects. All extra attributes (_links, _status, _meta, ...) are not returned but an '_total' attribute is added in each element to get the total count of elements stored in the backend. Returns None if the search failed. Do not raise any exception to the caller. If all_elements is True, it calls the get_all function of the backend client to get all the elements without any pagination activated. """ logger.debug("get, %s, params: %s", object_type, params) if isinstance(params, basestring): params = {'where': {'_id': params}} logger.debug("get, %s, params: %s", object_type, params) # Update backend search parameters if params is None: params = {'page': 0, 'max_results': BACKEND_PAGINATION_LIMIT} if 'where' in params: params['where'] = json.dumps(params['where']) if 'embedded' in params: params['embedded'] = json.dumps(params['embedded']) if 'where' not in params: params['where'] = {} if 'page' not in params: params['page'] = 0 if 'max_results' not in params: params['max_results'] = BACKEND_PAGINATION_LIMIT logger.debug( "get, search in the backend for %s: parameters=%s", object_type, params ) try: if all_elements: result = self.backend.get_all(object_type, params=params) else: result = self.backend.get(object_type, params=params) except BackendException as e: # pragma: no cover, simple protection logger.warning("get, backend exception for %s: %s", object_type, str(e)) return None logger.debug( "search, search result for %s: result=%s", object_type, result ) if result['_status'] != 'OK': # pragma: no cover, should not happen error = [] if "content" in result: error.append(result['content']) if "_issues" in result: error.append(result['_issues']) logger.warning("get, %s: %s, not found: %s", object_type, params, error) raise ValueError( '%s, search: %s was not found in the backend, error: %s' % ( object_type, params, error ) ) # If more than one element is found, we get an _items list if '_items' in result: if '_meta' in result: for item in result['_items']: item.update({'_total': result['_meta']['total']}) logger.debug("get, found in the backend: %s: %s", object_type, result['_items']) return result['_items'] if '_status' in result: result.pop('_status') if '_meta' in result: # result.update({'_total': result['_meta']['total']}) result['_total'] = result['_meta']['total'] logger.debug("get, found one in the backend: %s: %s", object_type, result) return result def post(self, object_type, data=None, files=None): """ Add an element """ logger.info("post, request to add a %s: data: %s", object_type, data) # Do not set header to use the client default behavior: # - set headers as {'Content-Type': 'application/json'} # - encode provided data to JSON headers = None if files: logger.info("post, request to add a %s with files: %s", object_type, files) # Set header to disable client default behavior headers = {'Content-type': 'multipart/form-data'} try: result = self.backend.post(object_type, data=data, files=files, headers=headers) logger.debug("post, response: %s", result) if result['_status'] != 'OK': logger.warning("post, error: %s", result) return None except BackendException as e: # pragma: no cover, simple protection logger.error("post, backend exception: %s", str(e)) logger.error("- response: %s", e.response) return None except Exception as e: # pragma: no cover, simple protection logger.warning("post, error: %s", str(e)) return None return result['_id'] def delete(self, object_type, object_id): """ Delete an element - object_type is the element type - object_id is the element identifier """ logger.info("delete, request to delete the %s: %s", object_type, object_id) try: # Get most recent version of the element element = self.get('/'.join([object_type, object_id])) logger.debug("delete, element: %s", element) except ValueError: # pragma: no cover, simple protection logger.warning("delete, object %s, _id=%s not found", object_type, object_id) return False try: # Request deletion headers = {'If-Match': element['_etag']} endpoint = '/'.join([object_type, object_id]) logger.info("delete, endpoint: %s", endpoint) result = self.backend.delete(endpoint, headers) logger.debug("delete, response: %s", result) if result['_status'] != 'OK': # pragma: no cover, should never happen error = [] if "content" in result: error.append(result["content"]) if "_issues" in result: error.append(result["_issues"]) for issue in result["_issues"]: error.append(result["_issues"][issue]) logger.warning("delete, error: %s", error) return False except BackendException as e: # pragma: no cover, should never happen logger.error("delete, backend exception: %s", str(e)) return False except ValueError: # pragma: no cover, should never happen logger.warning("delete, not found %s: %s", object_type, element) return False return True def update(self, object_type, object_id, data): """ Update an element - object_type is the element type - object_id is the element identifier """ logger.info("update, request to update the %s: %s", object_type, object_id) try: # Get most recent version of the element element = self.get('/'.join([object_type, object_id])) logger.debug("update, element: %s", element) except ValueError: # pragma: no cover, simple protection logger.warning("update, object %s, _id=%s not found", object_type, object_id) return False try: # Request update headers = {'If-Match': element['_etag']} endpoint = '/'.join([object_type, object_id]) logger.info("update, endpoint: %s, data: %s", endpoint, data) result = self.backend.patch(endpoint, data, headers) logger.debug("update, response: %s", result) if result['_status'] != 'OK': # pragma: no cover, should never happen error = [] if "content" in result: error.append(result["content"]) if "_issues" in result: error.append(result["_issues"]) for issue in result["_issues"]: error.append(result["_issues"][issue]) logger.warning("update, error: %s", error) return False except BackendException as e: # pragma: no cover, should never happen logger.error("update, backend exception: %s", str(e)) return False except ValueError: # pragma: no cover, should never happen logger.warning("update, not found %s: %s", object_type, element) return False return True
def test_11_domains_and_some_elements(self): global backend_address print '' print 'get all domains and some elements' # Create client API backend = Backend(backend_address) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) # Get all available endpoints print 'get all domains' # Filter the templates ... items = backend.get_domains() print "Got %d elements:" % len(items) assert_true('_items2' not in items) assert_true(len(items) > 0) for item in items: assert_true('href' in item) assert_true('title' in item) print "Domain: ", item # Get all hosts print 'get all hosts at once' # Filter the templates ... parameters = { 'where': '{"register":true}', 'max_results': 1 } items = backend.get_all('host', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('host_name' in item) print "Host: ", item['host_name'] # Get all services print 'get all services at once' # Filter the templates ... parameters = { 'where': '{"register":true}' } items = backend.get_all('service', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('host_name' in item) assert_true('service_description' in item) print "Service: %s/%s" % (item['host_name'], item['service_description']) # Get all contacts print 'get all contacts at once' # Filter the templates ... parameters = { 'where': '{"register":true}' } items = backend.get_all('contact', params=parameters) print "Got %d elements:" % len(items) assert_true('_items' not in items) # assert_true(len(items) > 0) for item in items: assert_true('contact_name' in item) print "Contact: ", item['contact_name']
def test_04_login(self): """ Test with right username / password :return: None """ print('') print('test accepted connection with username/password') # Create client API backend = Backend(self.backend_address) print('Login ...') assert backend.login('admin', 'admin') print('authenticated:', backend.authenticated) print('token:', backend.token) assert_true(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('Login ...') print('authenticated:', backend.authenticated) assert backend.login('admin', 'admin') print('authenticated:', backend.authenticated) print('token:', backend.token) assert_true(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('get object ... must be refused!') with assert_raises(BackendException) as cm: backend.get('host') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 401, str(ex)) print('get_all object ... must be refused!') with assert_raises(BackendException) as cm: backend.get_all('host') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 401, str(ex)) print('get all domains ... must be refused!') with assert_raises(BackendException) as cm: backend.get_domains() ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 401, str(ex)) print('post data ... must be refused!') with assert_raises(BackendException) as cm: data = {'fake': 'fake'} backend.post('user', data=data) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 401, str(ex)) print('patch data ... must be refused!') with assert_raises(BackendException) as cm: data = {'fake': 'fake'} headers = {'If-Match': ''} backend.patch('user', data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 405, str(ex)) print('delete data ... must be refused!') with assert_raises(BackendException) as cm: headers = {'If-Match': ''} backend.delete('user', headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 401, str(ex))
def test_04_login(self): """ Test with right username / password :return: None """ print('') print('test accepted connection with username/password') # Create client API backend = Backend(self.backend_address) print('Login ...') assert backend.login('admin', 'admin') print('authenticated:', backend.authenticated) print('token:', backend.token) assert_true(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('Login ...') print('authenticated:', backend.authenticated) assert backend.login('admin', 'admin') print('authenticated:', backend.authenticated) print('token:', backend.token) assert_true(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('Logout ...') backend.logout() print('authenticated:', backend.authenticated) print('token:', backend.token) assert_false(backend.authenticated) print('get object ... must be refused!') with assert_raises(BackendException) as cm: backend.get('host') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print('get_all object ... must be refused!') with assert_raises(BackendException) as cm: backend.get_all('host') ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print('get all domains ... must be refused!') with assert_raises(BackendException) as cm: backend.get_domains() ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print('post data ... must be refused!') with assert_raises(BackendException) as cm: data = {'fake': 'fake'} backend.post('user', data=data) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print('patch data ... must be refused!') with assert_raises(BackendException) as cm: data = {'fake': 'fake'} headers = {'If-Match': ''} backend.patch('user', data=data, headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex)) print('delete data ... must be refused!') with assert_raises(BackendException) as cm: headers = {'If-Match': ''} backend.delete('user', headers=headers) ex = cm.exception print('exception:', str(ex.code)) assert_true(ex.code == 1001, str(ex))
def setUpClass(cls): # Set test mode for alignak backend # Uncomment to log the bakend REST API # os.environ['TEST_ALIGNAK_BACKEND'] = '1' os.environ[ 'ALIGNAK_BACKEND_MONGO_DBNAME'] = 'alignak-module-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.backend = Backend('http://127.0.0.1:5000') cls.backend.login("admin", "admin", "force") realms = cls.backend.get_all('realm') for cont in realms['_items']: cls.realm_all = cont['_id'] # Get admin user users = cls.backend.get_all('user') for user in users['_items']: if user['name'] == 'admin': cls.user_admin = user # add commands data = json.loads(open('cfg/command_ping.json').read()) data['_realm'] = cls.realm_all data_cmd_ping = cls.backend.post("command", data) data = json.loads(open('cfg/command_http.json').read()) data['_realm'] = cls.realm_all data_cmd_http = cls.backend.post("command", data) cls.ping_cmd = data_cmd_http['_id'] # add 1 host data = json.loads(open('cfg/host_srv001.json').read()) data['check_command'] = data_cmd_ping['_id'] del data['realm'] data['_realm'] = cls.realm_all cls.data_host = cls.backend.post("host", data) # add 2 services data = json.loads(open('cfg/service_srv001_ping.json').read()) data['host'] = cls.data_host['_id'] data['check_command'] = data_cmd_ping['_id'] data['_realm'] = cls.realm_all cls.data_srv_ping = cls.backend.post("service", data) data = json.loads(open('cfg/service_srv001_http.json').read()) data['host'] = cls.data_host['_id'] data['check_command'] = data_cmd_http['_id'] data['_realm'] = cls.realm_all cls.data_srv_http = cls.backend.post("service", data) # Start arbiter module modconf = Module() modconf.module_alias = "backend_arbiter" modconf.username = "******" modconf.password = "******" modconf.api_url = 'http://127.0.0.1:5000' # Update default check timers # check every x min if config in backend changed, if yes it will reload it # Default, every 5 minutes modconf.verify_modification = 1 # verify_modification 5 cls.arbmodule = AlignakBackendArbiter(modconf) cls.objects = cls.arbmodule.get_objects()
def test_22_post_patch_delete(self): global backend_address print '' print 'post/delete/patch some hostgroups' # Create client API backend = Backend(backend_address) print 'Login ...' print 'authenticated:', backend.authenticated result = backend.login('admin', 'admin') print 'authenticated:', backend.authenticated print 'token:', backend.token assert_true(backend.authenticated) # Get all hostgroups print 'get all hostgroups at once' items = backend.get_all('hostgroup') print "Got %d elements:" % len(items) assert_true('_items' not in items) for item in items: assert_true('hostgroup_name' in item) assert_true('_id' in item) assert_true('_etag' in item) print "Group: ", item['hostgroup_name'], item['_id'] # Test contact still exists ... delete him! if item['hostgroup_name'] == 'test': headers = { 'If-Match': item['_etag'] } response = backend.delete('/'.join(['hostgroup', item['_id']]), headers) print "Response:", response # Create a new hostgroup, bad parameters print 'create a hostgroup, missing fields' # Mandatory field hostgroup_name is missing ... data = { "name": "Testing hostgroup", "alias": "Fred", "back_role_super_admin": False, "back_role_admin": [], "min_business_impact": 0, } with assert_raises(BackendException) as cm: response = backend.post('hostgroup', data=data) ex = cm.exception print 'exception:', str(ex.code), ex.message, ex.response if "_issues" in ex.response: for issue in ex.response["_issues"]: print "Issue: %s - %s" %(issue, ex.response["_issues"][issue]) assert_true(ex.code == 422) assert_true(ex.response["_issues"]) # Create a new hostgroup print 'create a hostgroup' data = { "hostgroup_name": "test", "name": "Testing hostgroup", "alias": "Fred", "note": "Hostgroup note ...", "realm": "all" } response = backend.post('hostgroup', data=data) print "Response:", response assert_true('_created' in response) assert_true('_updated' in response) assert_true(response['_created'] == response['_updated']) # Get all hostgroups print 'get all hostgroups at once' # Filter the templates ... items = backend.get_all('hostgroup') print "Got %d elements:" % len(items) assert_true('_items' not in items) assert_true(len(items) > 0) # Search test hostgroup hostgroup_id = '' hostgroup_etag = '' for item in items: assert_true('hostgroup_name' in item) print "hostgroup: ", item['hostgroup_name'] if item['hostgroup_name'] == 'test': hostgroup_id = item['_id'] hostgroup_etag = item['_etag'] assert_true(hostgroup_id != '') assert_true(hostgroup_etag != '') print 'changing hostgroup alias ... no _etag' print 'id:', hostgroup_id print 'etag:', hostgroup_etag with assert_raises(BackendException) as cm: data = {'alias': 'modified with no header'} # headers['If-Match'] = hostgroup_etag response = backend.patch('/'.join(['hostgroup', hostgroup_id]), data=data) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1005, str(ex)) print 'changing hostgroup alias ...' print 'id:', hostgroup_id print 'etag:', hostgroup_etag data = {'alias': 'modified test'} headers = {'If-Match': hostgroup_etag} response = backend.patch('/'.join(['hostgroup', hostgroup_id]), data=data, headers=headers) print 'response:', response assert_true(response['_status'] == 'OK') response = backend.get('/'.join(['hostgroup', hostgroup_id])) print 'response:', response assert_true(response['alias'] == 'modified test') print 'changing hostgroup alias ... bad _etag (inception = True)' print 'id:', hostgroup_id print 'etag:', hostgroup_etag data = {'alias': 'modified test again'} headers = {'If-Match': hostgroup_etag} response = backend.patch('/'.join(['hostgroup', hostgroup_id]), data=data, headers=headers, inception=True) print 'response:', response assert_true(response['_status'] == 'OK') response = backend.get('/'.join(['hostgroup', hostgroup_id])) print 'response:', response assert_true(response['alias'] == 'modified test again') print 'changing hostgroup alias ... bad _etag (inception = False)' print 'id:', hostgroup_id print 'etag:', hostgroup_etag with assert_raises(BackendException) as cm: data = {'alias': 'modified test again and again'} headers = {'If-Match': hostgroup_etag} response = backend.patch('/'.join(['hostgroup', hostgroup_id]), data=data, headers=headers) ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 412, str(ex)) response = backend.get('/'.join(['hostgroup', hostgroup_id])) print 'response:', response # Not changed ! assert_true(response['alias'] == 'modified test again') response = backend.get('/'.join(['hostgroup', hostgroup_id])) print 'response:', response # Not changed ! assert_true(response['alias'] == 'modified test again') print 'deleting hostgroup ... bad href' with assert_raises(BackendException) as cm: headers = { 'If-Match': item['_etag'] } response = backend.delete('/'.join(['hostgroup', '5'+item['_id']]), headers) print "Response:", response ex = cm.exception print 'exception:', str(ex.code) assert_true(ex.code == 1003, str(ex))
class AlignakBackendArbiter(BaseModule): # pylint: disable=too-many-public-methods """ This class is used to get configuration from 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.debug("inner properties: %s", self.__dict__) logger.debug("received configuration: %s", mod_conf.__dict__) self.my_arbiter = None # Alignak backend importation script is running self.backend_import = False if 'ALIGNAK_BACKEND_IMPORT_RUN' in os.environ and os.environ['ALIGNAK_BACKEND_IMPORT_RUN']: logger.info("Alignak backend importation script is active.") self.backend_import = True self.url = getattr(mod_conf, 'api_url', 'http://localhost:5000') self.backend = Backend(self.url) self.backend.token = getattr(mod_conf, 'token', '') self.backend_connected = False if self.backend.token == '': self.getToken(getattr(mod_conf, 'username', ''), getattr(mod_conf, 'password', ''), getattr(mod_conf, 'allowgeneratetoken', False)) self.bypass_verify_mode = int(getattr(mod_conf, 'bypass_verify_mode', 0)) == 1 logger.info( "bypass objects loading when Arbiter is in verify mode: %s", self.bypass_verify_mode ) self.verify_modification = int(getattr(mod_conf, 'verify_modification', 5)) logger.info( "configuration reload check period: %s minutes", self.verify_modification ) self.action_check = int(getattr(mod_conf, 'action_check', 15)) logger.info( "actions check period: %s seconds", self.action_check ) self.next_check = 0 self.next_action_check = 0 self.time_loaded_conf = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") self.configraw = {} self.config = {'commands': [], 'timeperiods': [], 'hosts': [], 'hostgroups': [], 'services': [], 'contacts': [], 'contactgroups': [], 'servicegroups': [], 'realms': [], 'hostdependencies': [], 'hostescalations': [], 'servicedependencies': [], 'serviceescalations': [], 'triggers': []} # 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("In loop") time.sleep(1) def hook_read_configuration(self, arbiter): """ Hook in arbiter used on configuration parsing start. This is useful to get our arbiter object and its parameters. :param arbiter: alignak.daemons.arbiterdaemon.Arbiter :type arbiter: object :return: None """ self.my_arbiter = arbiter def getToken(self, username, password, generatetoken): """ Authenticate and get the token :param username: login name :type username: str :param password: password :type password: str :param generatetoken: if True allow generate token, otherwise not generate :type generatetoken: bool :return: None """ if self.backend_import: # Do no try to login when importing a configuration into the backend logger.info("Alignak backend importation script is active. " "No backend connection.") return generate = 'enabled' if not generatetoken: generate = 'disabled' try: self.backend.login(username, password, generate) self.backend_connected = True except BackendException as exp: logger.warning("Alignak backend is not available for login. " "No backend connection.") logger.exception("Exception: %s", exp) self.backend_connected = False def single_relation(self, resource, mapping, ctype): """ Convert single embedded data to name of relation_data Example: {'contacts': {'_id': a3659204fe,'name':'admin'}} converted to: {'contacts': 'admin'} :param resource: dictionary got from alignak-backend :type resource: dict :param mapping: key value of resource :type mapping: str :param ctype: type of configraw (hosts, services, commands...) :type ctype: str """ if mapping in resource: if resource[mapping] is not None: if resource[mapping] in self.configraw[ctype]: resource[mapping] = self.configraw[ctype][resource[mapping]] def multiple_relation(self, resource, mapping, ctype): """ Convert multiple embedded data to name of relation_data Example: {'contacts': [{'_id': a3659204fe,'contact_name':'admin'}, {'_id': a3659204ff,'contact_name':'admin2'}]} converted to: {'contacts': 'admin,admin2'} :param resource: dictionary got from alignak-backend :type resource: dict :param mapping: key value of resource :type mapping: str :param ctype: type of configraw (hosts, services, commands...) :type ctype: str """ if mapping in resource: members = [] for member in resource[mapping]: if member in self.configraw[ctype]: members.append(self.configraw[ctype][member]) resource[mapping] = ','.join(members) @classmethod def clean_unusable_keys(cls, resource): """ Delete keys of dictionary not used :param resource: dictionary got from alignak-backend :type resource: dict :return: """ fields = [ '_links', '_updated', '_created', '_etag', '_id', 'name', 'ui', '_realm', '_sub_realm', '_users_read', '_users_update', '_users_delete', '_parent', '_tree_parents', '_all_children', '_level', 'customs', 'host', 'service', 'back_role_super_admin', 'token', '_templates', '_template_fields', 'note', '_is_template', '_templates_with_services', '_templates_from_host_template', 'merge_host_users', 'hosts_critical_threshold', 'hosts_warning_threshold', 'services_critical_threshold', 'services_warning_threshold', 'global_critical_threshold', 'global_warning_threshold', '_children', 'hostgroups', 'hosts', 'dependent_hostgroups', 'dependent_hosts', 'servicegroups', 'services', 'dependent_servicegroups', 'dependent_services', 'usergroups', 'users', 'location', 'duplicate_foreach', 'tags', 'ls_acknowledged', 'ls_current_attempt', 'ls_downtimed', 'ls_execution_time', 'ls_grafana', 'ls_grafana_panelid', 'ls_impact', 'ls_last_check', 'ls_last_state', 'ls_last_state_changed', 'ls_last_state_type', 'ls_latency', 'ls_long_output', 'ls_max_attempts', 'ls_next_check', 'ls_output', 'ls_perf_data', 'ls_state', 'ls_state_id', 'ls_state_type' ] for field in fields: if field in resource: del resource[field] @classmethod def convert_lists(cls, resource): """ Convert lists into string with values separated with comma :param resource: ressource :type resource: dict :return: None """ for prop in resource: if isinstance(resource[prop], list): resource[prop] = u','.join(str(e) for e in resource[prop]) # Is it really useful ... considered as not useful! # elif isinstance(resource[prop], dict): # logger.warning("=====> %s", prop) # logger.warning(resource[prop]) def get_realms(self): """ Get realms from alignak_backend :return: None """ self.configraw['realms'] = {} all_realms = self.backend.get_all('realm') logger.info("Got %d realms", len(all_realms['_items'])) for realm in all_realms['_items']: logger.info("- %s", realm['name']) self.configraw['realms'][realm['_id']] = realm['name'] realm['imported_from'] = u'alignakbackend' realm['realm_name'] = realm['name'] realm['realm_members'] = [] self.clean_unusable_keys(realm) del realm['notes'] del realm['alias'] # self.convert_lists(realm) logger.debug("- realm: %s", realm) self.config['realms'].append(realm) def get_commands(self): """ Get commands from alignak_backend :return: None """ self.configraw['commands'] = {} all_commands = self.backend.get_all('command') logger.info("Got %d commands", len(all_commands['_items'])) for command in all_commands['_items']: logger.info("- %s", command['name']) self.configraw['commands'][command['_id']] = command['name'] command['imported_from'] = u'alignakbackend' command['command_name'] = command['name'] self.clean_unusable_keys(command) del command['alias'] del command['notes'] self.convert_lists(command) logger.debug("- command: %s", command) self.config['commands'].append(command) def get_timeperiods(self): """ Get timeperiods from alignak_backend :return: None """ self.configraw['timeperiods'] = {} all_timeperiods = self.backend.get_all('timeperiod') logger.info("Got %d timeperiods", len(all_timeperiods['_items'])) for timeperiod in all_timeperiods['_items']: logger.info("- %s", timeperiod['name']) self.configraw['timeperiods'][timeperiod['_id']] = timeperiod['name'] timeperiod['imported_from'] = u'alignakbackend' timeperiod['timeperiod_name'] = timeperiod['name'] for daterange in timeperiod['dateranges']: timeperiod.update(daterange) del timeperiod['dateranges'] self.clean_unusable_keys(timeperiod) del timeperiod['notes'] self.convert_lists(timeperiod) logger.debug("- timeperiod: %s", timeperiod) self.config['timeperiods'].append(timeperiod) def get_contactgroups(self): """ Get contactgroups from alignak_backend :return: None """ self.configraw['contactgroups'] = {} all_contactgroups = self.backend.get_all('usergroup') logger.info("Got %d contactgroups", len(all_contactgroups['_items'])) for contactgroup in all_contactgroups['_items']: logger.info("- %s", contactgroup['name']) self.configraw['contactgroups'][contactgroup['_id']] = contactgroup['name'] for contactgroup in all_contactgroups['_items']: contactgroup[u'imported_from'] = u'alignakbackend' contactgroup[u'contactgroup_name'] = contactgroup['name'] contactgroup[u'contactgroup_members'] = contactgroup['usergroups'] contactgroup[u'members'] = contactgroup['users'] # members self.multiple_relation(contactgroup, 'members', 'contacts') # contactgroup_members self.multiple_relation(contactgroup, 'contactgroup_members', 'contactgroups') self.clean_unusable_keys(contactgroup) del contactgroup['notes'] self.convert_lists(contactgroup) logger.debug("- contacts group: %s", contactgroup) self.config['contactgroups'].append(contactgroup) def get_contacts(self): """ Get contacts from alignak_backend :return: None """ self.configraw['contacts'] = {} all_contacts = self.backend.get_all('user') logger.info("Got %d contacts", len(all_contacts['_items'])) for contact in all_contacts['_items']: logger.info("- %s", contact['name']) self.configraw['contacts'][contact['_id']] = contact['name'] contact['imported_from'] = u'alignakbackend' contact['contact_name'] = contact['name'] # host_notification_period self.single_relation(contact, 'host_notification_period', 'timeperiods') # service_notification_period self.single_relation(contact, 'service_notification_period', 'timeperiods') # host_notification_commands self.multiple_relation(contact, 'host_notification_commands', 'commands') # service_notification_commands self.multiple_relation(contact, 'service_notification_commands', 'commands') # contactgroups self.multiple_relation(contact, 'contactgroups', 'contactgroups') if 'host_notification_commands' not in contact: contact['host_notification_commands'] = '' if 'service_notification_commands' not in contact: contact['service_notification_commands'] = '' if 'host_notification_period' not in contact: contact['host_notification_period'] = \ self.config['timeperiods'][0]['timeperiod_name'] contact['host_notifications_enabled'] = False if 'service_notification_period' not in contact: contact['service_notification_period'] = \ self.config['timeperiods'][0]['timeperiod_name'] contact['service_notifications_enabled'] = False for key, value in contact['customs'].iteritems(): contact[key] = value self.clean_unusable_keys(contact) del contact['notes'] del contact['ui_preferences'] self.convert_lists(contact) logger.debug("- contact: %s", contact) self.config['contacts'].append(contact) def get_hostgroups(self): """ Get hostgroups from alignak_backend :return: None """ self.configraw['hostgroups'] = {} all_hostgroups = self.backend.get_all('hostgroup') logger.info("Got %d hostgroups", len(all_hostgroups['_items'])) for hostgroup in all_hostgroups['_items']: logger.info("- %s", hostgroup['name']) self.configraw['hostgroups'][hostgroup['_id']] = hostgroup['name'] for hostgroup in all_hostgroups['_items']: self.configraw['hostgroups'][hostgroup['_id']] = hostgroup['name'] hostgroup[u'imported_from'] = u'alignakbackend' hostgroup[u'hostgroup_name'] = hostgroup['name'] hostgroup[u'hostgroup_members'] = hostgroup['hostgroups'] hostgroup[u'members'] = hostgroup['hosts'] # members self.multiple_relation(hostgroup, 'members', 'hosts') # hostgroup_members self.multiple_relation(hostgroup, 'hostgroup_members', 'hostgroups') self.clean_unusable_keys(hostgroup) self.convert_lists(hostgroup) logger.debug("- hosts group: %s", hostgroup) self.config['hostgroups'].append(hostgroup) def get_hosts(self): """ Get hosts from alignak_backend :return: None """ self.configraw['hosts'] = {} all_hosts = self.backend.get_all('host', {"where": '{"_is_template": false}'}) logger.info("Got %d hosts", len(all_hosts['_items'])) for host in all_hosts['_items']: logger.info("- %s", host['name']) self.configraw['hosts'][host['_id']] = host['name'] host[u'host_name'] = host['name'] host[u'imported_from'] = u'alignakbackend' # check_command if 'check_command' in host: if host['check_command'] is None: host['check_command'] = '' elif host['check_command'] in self.configraw['commands']: host['check_command'] = self.configraw['commands'][host['check_command']] else: host['check_command'] = '' if 'check_command_args' in host: if 'check_command' not in host: host['check_command'] = '' elif host['check_command_args'] != '': host['check_command'] += '!' host['check_command'] += host['check_command_args'] del host['check_command_args'] host[u'contacts'] = [] if 'users' in host: host[u'contacts'] = host['users'] host[u'contact_groups'] = [] if 'usergroups' in host: host[u'contact_groups'] = host['usergroups'] # check_period self.single_relation(host, 'check_period', 'timeperiods') # realm self.single_relation(host, '_realm', 'realms') host['realm'] = host['_realm'] # notification_period self.single_relation(host, 'notification_period', 'timeperiods') # maintenance_period self.single_relation(host, 'maintenance_period', 'timeperiods') # snapshot_period self.single_relation(host, 'snapshot_period', 'timeperiods') # event_handler self.single_relation(host, 'event_handler', 'commands') # parents # ## self.multiple_relation(host, 'parents', 'host_name') host[u'parents'] = '' # hostgroups self.multiple_relation(host, 'hostgroup_name', 'hostgroups') # contacts self.multiple_relation(host, 'contacts', 'contacts') # contact_groups self.multiple_relation(host, 'contact_groups', 'contactgroups') # escalations # ## self.multiple_relation(host, 'escalations', 'escalation_name') del host['escalations'] if 'alias' in host and host['alias'] == '': del host['alias'] if 'realm' in host: if host['realm'] is None: del host['realm'] for key, value in host['customs'].iteritems(): host[key] = value # Fix #9: inconsistent state when no retention module exists if 'ls_last_state' in host: if host['ls_state'] == 'UNREACHABLE': host['initial_state'] = 'u' if host['ls_state'] == 'DOWN': host['initial_state'] = 'd' if host['ls_state'] == 'UP': host['initial_state'] = 'o' logger.debug( "- host current live state is %s, " "set initial_state as '%s'", host['ls_state'], host['initial_state'] ) self.clean_unusable_keys(host) self.convert_lists(host) logger.debug("- host: %s", host) self.config['hosts'].append(host) def get_servicegroups(self): """ Get servicegroups from alignak_backend :return: None """ self.configraw['servicegroups'] = {} all_servicegroups = self.backend.get_all('servicegroup') logger.info("Got %d servicegroups", len(all_servicegroups['_items'])) for servicegroup in all_servicegroups['_items']: logger.info("- %s", servicegroup['name']) self.configraw['servicegroups'][servicegroup['_id']] = servicegroup['name'] for servicegroup in all_servicegroups['_items']: self.configraw['servicegroups'][servicegroup['_id']] = servicegroup['name'] servicegroup['imported_from'] = u'alignakbackend' servicegroup['servicegroup_name'] = servicegroup['name'] servicegroup[u'servicegroup_members'] = servicegroup['servicegroups'] # members members = [] for service in servicegroup['services']: if service not in self.configraw['services']: continue for svc in self.config['services']: if self.configraw['services'][service] == svc['service_description']: members.append("%s,%s" % (svc['host_name'], svc['service_description'])) servicegroup['members'] = ','.join(members) # servicegroup_members self.multiple_relation(servicegroup, 'servicegroup_members', 'servicegroups') self.clean_unusable_keys(servicegroup) self.convert_lists(servicegroup) logger.debug("- services group: %s", servicegroup) self.config['servicegroups'].append(servicegroup) def get_services(self): """ Get services from alignak_backend :return: None """ self.configraw['services'] = {} params = {'embedded': '{"escalations":1,"service_dependencies":1}', "where": '{"_is_template": false}'} all_services = self.backend.get_all('service', params) logger.info("Got %d services", len(all_services['_items'])) for service in all_services['_items']: logger.info("- %s", service['name']) self.configraw['services'][service['_id']] = service['name'] service['imported_from'] = u'alignakbackend' service['service_description'] = service['name'] service['host_name'] = service['host'] service['merge_host_contacts'] = service['merge_host_users'] service['hostgroup_name'] = service['hostgroups'] service[u'contacts'] = [] if 'users' in service: service[u'contacts'] = service['users'] service[u'contact_groups'] = [] if 'usergroups' in service: service[u'contact_groups'] = service['usergroups'] # check_command if 'check_command' in service: if service['check_command'] is None: del service['check_command'] elif service['check_command'] in self.configraw['commands']: service['check_command'] = self.configraw['commands'][service['check_command']] else: del service['check_command'] if 'check_command_args' in service: if 'check_command' not in service: service['check_command'] = '' else: service['check_command'] += '!' service['check_command'] += service['check_command_args'] del service['check_command_args'] # host_name self.single_relation(service, 'host_name', 'hosts') # check_period self.single_relation(service, 'check_period', 'timeperiods') # notification_period self.single_relation(service, 'notification_period', 'timeperiods') # maintenance_period self.single_relation(service, 'maintenance_period', 'timeperiods') # snapshot_period self.single_relation(service, 'snapshot_period', 'timeperiods') # event_handler self.single_relation(service, 'event_handler', 'commands') # servicegroups self.multiple_relation(service, 'servicegroups', 'servicegroups') # contacts self.multiple_relation(service, 'contacts', 'contacts') # contact_groups self.multiple_relation(service, 'contact_groups', 'contactgroups') # escalations # ## self.multiple_relation(service, 'escalations', 'escalation_name') if 'escalation' in service and service['escalation'] == '': del service['escalation'] # service_dependencies # ## self.multiple_relation(service, 'service_dependencies', 'service_name') service['service_dependencies'] = '' if 'alias' in service and service['alias'] == '': del service['alias'] for key, value in service['customs'].iteritems(): service[key] = value # Fix #9: inconsistent state when no retention module exists if 'ls_last_state' in service: if service['ls_state'] == 'UNKNOWN': service['initial_state'] = 'u' if service['ls_state'] == 'CRITICAL': service['initial_state'] = 'c' if service['ls_state'] == 'WARNING': service['initial_state'] = 'w' if service['ls_state'] == 'UP': service['initial_state'] = 'o' logger.debug( "- service current live state is %s, " "set initial_state as '%s'", service['ls_state'], service['initial_state'] ) self.clean_unusable_keys(service) self.convert_lists(service) logger.debug("- service: %s", service) self.config['services'].append(service) def get_hostdependencies(self): """ Get hostdependencies from alignak_backend :return: None """ self.configraw['hostdependencies'] = {} all_hostdependencies = self.backend.get_all('hostdependency') logger.info("Got %d hostdependencies", len(all_hostdependencies['_items'])) for hostdependency in all_hostdependencies['_items']: logger.info("- %s", hostdependency['name']) self.configraw['hostdependencies'][hostdependency['_id']] = hostdependency['name'] hostdependency['imported_from'] = u'alignakbackend' # Do not exist in Alignak # hostdependency['hostdependency_name'] = hostdependency['name'] hostdependency['dependent_hostgroup_name'] = hostdependency['dependent_hostgroups'] hostdependency['dependent_host_name'] = hostdependency['dependent_hosts'] hostdependency['hostgroup_name'] = hostdependency['hostgroups'] hostdependency['host_name'] = hostdependency['hosts'] # dependent_host_name self.multiple_relation(hostdependency, 'dependent_host_name', 'hosts') # dependent_hostgroup_name self.multiple_relation(hostdependency, 'dependent_hostgroup_name', 'hostgroups') # host_name self.multiple_relation(hostdependency, 'host_name', 'hosts') # hostgroup_name self.multiple_relation(hostdependency, 'hostgroup_name', 'hostgroups') self.clean_unusable_keys(hostdependency) self.convert_lists(hostdependency) logger.debug("- hosts dependency: %s", hostdependency) self.config['hostdependencies'].append(hostdependency) def get_hostescalations(self): """ Get hostescalations from alignak_backend :return: None """ self.configraw['hostescalations'] = {} all_hostescalations = self.backend.get_all('hostescalation') logger.info("Got %d hostescalations", len(all_hostescalations['_items'])) for hostescalation in all_hostescalations['_items']: logger.info("- %s", hostescalation['name']) self.configraw['hostescalations'][hostescalation['_id']] = hostescalation['name'] hostescalation['hostescalation_name'] = hostescalation['name'] hostescalation['imported_from'] = u'alignakbackend' # host_name self.single_relation(hostescalation, 'host_name', 'hosts') # hostgroup_name self.multiple_relation(hostescalation, 'hostgroup_name', 'hostgroups') # contacts self.multiple_relation(hostescalation, 'contacts', 'contacts') # contact_groups self.multiple_relation(hostescalation, 'contact_groups', 'contactgroups') self.clean_unusable_keys(hostescalation) self.convert_lists(hostescalation) logger.debug("- host escalation: %s", hostescalation) self.config['hostescalations'].append(hostescalation) def get_servicedependencies(self): """ Get servicedependencies from alignak_backend :return: None """ self.configraw['servicedependencies'] = {} all_servicedependencies = self.backend.get_all('servicedependency') logger.info("Got %d servicedependencies", len(all_servicedependencies['_items'])) for servicedependency in all_servicedependencies['_items']: logger.info("- %s", servicedependency['name']) self.configraw['servicedependencies'][servicedependency['_id']] = \ servicedependency['name'] servicedependency['imported_from'] = u'alignakbackend' # Do not exist in Alignak # servicedependency['servicedependency_name'] = servicedependency['name'] servicedependency['dependent_hostgroup_name'] = \ servicedependency['dependent_hostgroups'] servicedependency['dependent_host_name'] = \ servicedependency['dependent_hosts'] servicedependency['dependent_service_description'] = \ servicedependency['dependent_services'] servicedependency['hostgroup_name'] = servicedependency['hostgroups'] servicedependency['host_name'] = servicedependency['hosts'] servicedependency['service_description'] = servicedependency['services'] # dependent_host_name self.multiple_relation(servicedependency, 'dependent_host_name', 'hosts') # dependent_hostgroup_name self.multiple_relation(servicedependency, 'dependent_hostgroup_name', 'hostgroups') # service_description self.multiple_relation(servicedependency, 'service_description', 'services') # dependent_service_description self.multiple_relation(servicedependency, 'dependent_service_description', 'services') # host_name self.multiple_relation(servicedependency, 'host_name', 'hosts') # hostgroup_name self.multiple_relation(servicedependency, 'hostgroup_name', 'hostgroups') self.clean_unusable_keys(servicedependency) self.convert_lists(servicedependency) if not servicedependency['hostgroup_name']: del servicedependency['hostgroup_name'] if not servicedependency['dependent_hostgroup_name']: del servicedependency['dependent_hostgroup_name'] logger.debug("- services dependency: %s", servicedependency) self.config['servicedependencies'].append(servicedependency) def get_serviceescalations(self): """ Get serviceescalations from alignak_backend :return: None """ self.configraw['serviceescalations'] = {} all_serviceescalations = self.backend.get_all('serviceescalation') logger.info("Got %d serviceescalations", len(all_serviceescalations['_items'])) for serviceescalation in all_serviceescalations['_items']: logger.info("- %s", serviceescalation['name']) self.configraw['serviceescalations'][serviceescalation['_id']] = \ serviceescalation['name'] serviceescalation['serviceescalation_name'] = serviceescalation['name'] serviceescalation['imported_from'] = u'alignakbackend' # host_name self.single_relation(serviceescalation, 'host_name', 'hosts') # hostgroup_name self.multiple_relation(serviceescalation, 'hostgroup_name', 'hostgroups') # service_description self.single_relation(serviceescalation, 'service_description', 'services') # contacts self.multiple_relation(serviceescalation, 'contacts', 'contacts') # contact_groups self.multiple_relation(serviceescalation, 'contact_groups', 'contactgroups') self.clean_unusable_keys(serviceescalation) self.convert_lists(serviceescalation) logger.debug("- service escalation: %s", serviceescalation) self.config['serviceescalations'].append(serviceescalation) def get_objects(self): """ Get objects from alignak-backend :return: configuration objects :rtype: dict """ if not self.backend_connected: logger.error("Alignak backend connection is not available. " "Skipping objects load and provide an empty list to the Arbiter.") return self.config if self.my_arbiter and self.my_arbiter.verify_only: logger.info("my Arbiter is in verify only mode") if self.bypass_verify_mode: logger.info("configured to bypass the objects loading. " "Skipping objects load and provide an empty list to the Arbiter.") return self.config if self.backend_import: logger.info("Alignak backend importation script is active. " "Provide an empty objects list to the Arbiter.") return self.config start_time = time.time() try: self.get_realms() self.get_commands() self.get_timeperiods() self.get_contacts() self.get_contactgroups() self.get_hosts() self.get_hostgroups() self.get_services() self.get_servicegroups() self.get_hostdependencies() self.get_hostescalations() self.get_servicedependencies() self.get_serviceescalations() except BackendException as exp: logger.warning("Alignak backend is not available for reading. " "Backend communication error.") logger.exception("Exception: %s", exp) self.backend_connected = False self.time_loaded_conf = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") now = time.time() logger.info( "backend configuration loaded in %s seconds", (now - start_time) ) # Schedule next configuration reload check in 10 minutes (need time to finish load config) self.next_check = int(now) + (60 * self.verify_modification) self.next_action_check = int(now) + self.action_check logger.info( "next configuration reload check in %s seconds ---", (self.next_check - int(now)) ) logger.info( "next actions check in %s seconds ---", (self.next_action_check - int(now)) ) return self.config def hook_tick(self, arbiter): """ Hook in arbiter used to check if configuration has changed in the backend since last configuration loaded :param arbiter: alignak.daemons.arbiterdaemon.Arbiter :type arbiter: object :return: None """ try: now = int(time.time()) if now > self.next_check: logger.info( "Check if system configuration changed in the backend..." ) resources = [ 'realm', 'command', 'timeperiod', 'usergroup', 'user', 'hostgroup', 'host', 'hostdependency', 'hostescalation', 'servicegroup', 'service', 'servicedependency', 'serviceescalation' ] reload_conf = False for resource in resources: ret = self.backend.get(resource, {'where': '{"_updated":{"$gte": "' + self.time_loaded_conf + '"}}'}) logger.info( " - backend updated resource: %s, count: %d", resource, ret['_meta']['total'] ) if ret['_meta']['total'] > 0: reload_conf = True if reload_conf: logger.warning( "Hey, we must reload configuration from the backend!" ) with open(arbiter.pidfile, 'r') as f: arbiterpid = f.readline() os.kill(int(arbiterpid), signal.SIGHUP) self.next_check = now + (60 * self.verify_modification) logger.debug( "next configuration reload check in %s seconds ---", (self.next_check - now) ) if now > self.next_action_check: logger.debug("Check if acknowledgements are required...") self.get_acknowledge(arbiter) logger.debug("Check if downtime scheduling are required...") self.get_downtime(arbiter) logger.debug("Check if re-checks are required...") self.get_forcecheck(arbiter) self.next_action_check = now + self.action_check logger.debug( "next actions check in %s seconds ---", (self.next_action_check - int(now)) ) except Exception as exp: logger.warning("hook_tick exception: %s", str(exp)) logger.exception("Exception: %s", exp) @staticmethod def convert_date_timestamp(mydate): """ Convert date/time of backend into timestamp :param mydate: the date :type mydate: str :return: the timestamp :rtype: int """ return int(time.mktime(datetime.strptime(mydate, "%a, %d %b %Y %H:%M:%S %Z"). timetuple())) def get_acknowledge(self, arbiter): """ Get acknowledge from backend :return: None """ all_ack = self.backend.get_all('actionacknowledge', {'where': '{"processed": false}', 'embedded': '{"host": 1, "service": 1, "user": 1}'}) for ack in all_ack['_items']: sticky = 1 if ack['sticky']: sticky = 2 if ack['action'] == 'add': if ack['service']: command = '[{}] ACKNOWLEDGE_SVC_PROBLEM;{};{};{};{};{};{};{}\n'.\ format(self.convert_date_timestamp(ack['_created']), ack['host']['name'], ack['service']['name'], sticky, int(ack['notify']), int(ack['persistent']), ack['user']['name'], ack['comment']) else: # logger.warning(time.time()) # logger.warning(self.convert_date_timestamp(ack['_created'])) command = '[{}] ACKNOWLEDGE_HOST_PROBLEM;{};{};{};{};{};{}\n'. \ format(self.convert_date_timestamp(ack['_created']), ack['host']['name'], sticky, int(ack['notify']), int(ack['persistent']), ack['user']['name'], ack['comment']) elif ack['action'] == 'delete': if ack['service']: command = '[{}] REMOVE_SVC_ACKNOWLEDGEMENT;{};{}\n'.\ format(self.convert_date_timestamp(ack['_created']), ack['host']['name'], ack['service']['name']) else: command = '[{}] REMOVE_HOST_ACKNOWLEDGEMENT;{}\n'. \ format(self.convert_date_timestamp(ack['_created']), ack['host']['name']) headers = {'Content-Type': 'application/json', 'If-Match': ack['_etag']} data = {'processed': True} self.backend.patch('actionacknowledge/' + ack['_id'], data, headers) logger.info("build external command: %s", str(command)) ext = ExternalCommand(command) arbiter.external_commands.append(ext) def get_downtime(self, arbiter): """ Get downtime from backend :return: None """ all_downt = self.backend.get_all('actiondowntime', {'where': '{"processed": false}', 'embedded': '{"host": 1, "service": 1, ' '"user": 1}'}) # pylint: disable=too-many-format-args for downt in all_downt['_items']: if downt['action'] == 'add': if downt['service']: command = '[{}] SCHEDULE_SVC_DOWNTIME;{};{};{};{};{};{};{};{};{}\n'.\ format(self.convert_date_timestamp(downt['_created']), downt['host']['name'], downt['service']['name'], downt['start_time'], downt['end_time'], int(downt['fixed']), 0, downt['duration'], downt['user']['name'], downt['comment']) elif downt['host'] and 'name' in downt['host']: command = '[{}] SCHEDULE_HOST_DOWNTIME;{};{};{};{};{};{};{};{}\n'.\ format(self.convert_date_timestamp(downt['_created']), downt['host']['name'], downt['start_time'], downt['end_time'], int(downt['fixed']), 0, downt['duration'], downt['user']['name'], downt['comment']) elif downt['action'] == 'delete': if downt['service']: command = '[{}] DEL_ALL_SVC_DOWNTIMES;{};{}\n'.\ format(self.convert_date_timestamp(downt['_created']), downt['host']['name'], downt['service']['name']) else: command = '[{}] DEL_ALL_HOST_DOWNTIMES;{}\n'. \ format(self.convert_date_timestamp(downt['_created']), downt['host']['name']) headers = {'Content-Type': 'application/json', 'If-Match': downt['_etag']} data = {'processed': True} self.backend.patch('actiondowntime/' + downt['_id'], data, headers) logger.info("build external command: %s", str(command)) ext = ExternalCommand(command) arbiter.external_commands.append(ext) def get_forcecheck(self, arbiter): """ Get forcecheck from backend :return: None """ all_fcheck = self.backend.get_all('actionforcecheck', {'where': '{"processed": false}', 'embedded': '{"host": 1, "service": 1}'}) for fcheck in all_fcheck['_items']: timestamp = self.convert_date_timestamp(fcheck['_created']) if fcheck['service']: command = '[{}] SCHEDULE_FORCED_SVC_CHECK;{};{};{}\n'.\ format(timestamp, fcheck['host']['name'], fcheck['service']['name'], timestamp) else: command = '[{}] SCHEDULE_FORCED_HOST_CHECK;{};{}\n'.\ format(timestamp, fcheck['host']['name'], timestamp) headers = {'Content-Type': 'application/json', 'If-Match': fcheck['_etag']} data = {'processed': True} self.backend.patch('actionforcecheck/' + fcheck['_id'], data, headers) logger.info("build external command: %s", str(command)) ext = ExternalCommand(command) arbiter.external_commands.append(ext)
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.debug("inner properties: %s", self.__dict__) logger.debug("received configuration: %s", mod_conf.__dict__) self.my_arbiter = None # Alignak backend importation script is running self.backend_import = False if 'ALIGNAK_BACKEND_IMPORT_RUN' in os.environ and os.environ['ALIGNAK_BACKEND_IMPORT_RUN']: logger.info("Alignak backend importation script is active.") self.backend_import = True self.url = getattr(mod_conf, 'api_url', 'http://localhost:5000') self.backend = Backend(self.url) self.backend.token = getattr(mod_conf, 'token', '') self.backend_connected = False if self.backend.token == '': self.getToken(getattr(mod_conf, 'username', ''), getattr(mod_conf, 'password', ''), getattr(mod_conf, 'allowgeneratetoken', False)) self.bypass_verify_mode = int(getattr(mod_conf, 'bypass_verify_mode', 0)) == 1 logger.info( "bypass objects loading when Arbiter is in verify mode: %s", self.bypass_verify_mode ) self.verify_modification = int(getattr(mod_conf, 'verify_modification', 5)) logger.info( "configuration reload check period: %s minutes", self.verify_modification ) self.action_check = int(getattr(mod_conf, 'action_check', 15)) logger.info( "actions check period: %s seconds", self.action_check ) self.next_check = 0 self.next_action_check = 0 self.time_loaded_conf = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") self.configraw = {} self.config = {'commands': [], 'timeperiods': [], 'hosts': [], 'hostgroups': [], 'services': [], 'contacts': [], 'contactgroups': [], 'servicegroups': [], 'realms': [], 'hostdependencies': [], 'hostescalations': [], 'servicedependencies': [], 'serviceescalations': [], 'triggers': []}
def __init__(self, backend_endpoint='http://127.0.0.1:5002'): self.backend_endpoint = backend_endpoint self.backend = Backend(backend_endpoint) self.connected = False
def test_3_page_after_page(self): """ Get page after page manually :return: None """ print('') print('backend connection with username/password') # Create client API backend = Backend(self.backend_address) backend.login('admin', 'admin') # Start with first page ... last_page = False parameters = {'max_results': 3, 'page': 1} items = [] while not last_page: resp = backend.get('hostgroup', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) assert_equal(total, 101) assert_equal(max_results, 3) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 else: last_page = True assert_equal(page_number, 34) items.extend(resp['_items']) print("----------") print("Got %d elements:" % len(items)) assert_equal(len(items), 101) # Start with first page ... last_page = False parameters = {'max_results': 10, 'page': 1} items = [] while not last_page: resp = backend.get('hostgroup', params=parameters) assert_true('_items' in resp) assert_true('_links' in resp) assert_true('_meta' in resp) page_number = int(resp['_meta']['page']) total = int(resp['_meta']['total']) max_results = int(resp['_meta']['max_results']) assert_equal(total, 101) assert_equal(max_results, 10) if 'next' in resp['_links']: # It has pagination, so get items of all pages parameters['page'] = page_number + 1 else: last_page = True assert_equal(page_number, 11) items.extend(resp['_items']) print("----------") print("Got %d elements:" % len(items)) assert_equal(len(items), 101)