def get_realm_members(self, element_id): """Get the realm hosts list""" datamgr = request.app.datamgr realm = datamgr.get_realm(element_id) if not realm: realm = datamgr.get_realm(search={ 'max_results': 1, 'where': { 'name': element_id } }) if not realm: return self.webui.response_invalid_parameters( _('Element does not exist: %s') % element_id) # Get elements from the data manager search = { 'where': { '_realm': realm.id }, 'sort': '-business_impact, -ls_state_id, -ls_last_state_changed' } hosts = datamgr.get_hosts(search=search) logger.debug("get_realm_members, search: %s, found %d hosts", search, len(hosts)) # Get element state configuration items_states = ElementState() items = [] items.append({ 'id': -1, 'type': 'host', 'tr': """ <table class="table table-invisible table-condensed"> <thead><tr> <th></th> <th>%s</th> <th>%s</th> <th>%s</th> <th>%s</th> <th>%s</th> </tr></thead> <tbody> </tbody> </table> """ % (_("BI"), _("Element"), _("Since"), _("Last check"), _("Output")) }) for member in hosts: logger.debug("Realm member: %s", member) cfg_state = items_states.get_icon_state('host', member.status) tr = """<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td class="hidden-xs">%s</td> <td class="hidden-xs">%s</td> <td class="hidden-sm hidden-xs">%s: %s</td> </tr>""" % (member.get_html_state(text=None, title=member.alias), Helper.get_html_business_impact( member.business_impact, icon=True, text=False), member.get_html_link(), Helper.print_duration(member.last_state_changed, duration_only=True, x_elts=2), Helper.print_duration( member.last_check, duration_only=True, x_elts=2), Helper.print_date(member.last_check), member.output) items.append({ 'id': member.id, 'type': 'host', 'name': member.name, 'alias': member.alias, 'status': member.status, 'icon': 'fa fa-%s item_%s' % (cfg_state['icon'], cfg_state['class']), 'state': member.get_html_state(text=None, title=member.alias), 'tr': tr }) response.status = 200 response.content_type = 'application/json' return json.dumps(items)
class test_helper(unittest.TestCase): def setUp(self): print "" print "setting up ..." alignak_webui.app.config['HOST'] = '127.0.0.1' alignak_webui.app.config['PORT'] = 80 alignak_webui.app.config['DEBUG'] = False alignak_webui.app.config['TESTING'] = True cfg_file = "settings.cfg" print 'Required configuration file:', cfg_file sett = Settings(alignak_webui.app) found_cfg_files = sett.read(cfg_file, {}) if not found_cfg_files: print "Required configuration file not found." sys.exit(1) print 'Found configuration file:', cfg_file self.helper = Helper(alignak_webui.app) def tearDown(self): print "" print "tearing down ..." def test_01_print_date(self): print "---" now = time.time() # Timestamp errors s = self.helper.print_date(None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.print_date(0) print "Result:", s self.assert_(s == 'n/a') # Now, default format s = self.helper.print_date(now) print "Result:", s # Now, specified format s = self.helper.print_date(now, fmt='%Y-%m-%d') print "Result:", s s = self.helper.print_date(now, fmt='%H:%M:%S') print "Result:", s def test_02_print_duration(self): print "---" now = time.time() # Timestamp errors s = self.helper.print_duration(None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.print_duration(0) print "Result:", s self.assert_(s == 'n/a') # Now, default format s = self.helper.print_duration(now) print "Result:", s self.assert_(s == 'Now') # In the past ... # 2s ago s = self.helper.print_duration(now - 2) print "Result:", s self.assert_(s == '2s ago') # Only the duration string s = self.helper.print_duration(now - 2, duration_only=True) print "Result:", s self.assert_(s == '2s') # Got 2minutes s = self.helper.print_duration(now - 120) print "Result:", s self.assert_(s == '2m ago') # Go 2hours ago s = self.helper.print_duration(now - 3600*2) print "Result:", s self.assert_(s == '2h ago') # Go 2 days ago s = self.helper.print_duration(now - 3600*24*2) print "Result:", s self.assert_(s == '2d ago') # Go 2 weeks ago s = self.helper.print_duration(now - 86400*14) print "Result:", s self.assert_(s == '2w ago') # Go 2 months ago s = self.helper.print_duration(now - 86400*56) print "Result:", s self.assert_(s == '2M ago') # Go 1 year ago s = self.helper.print_duration(now - 86400*365*2) print "Result:", s self.assert_(s == '2y ago') # Now a mix of all of this :) s = self.helper.print_duration(now - 2 - 120 - 3600*2 - 3600*24*2 - 86400*14 - 86400*56) print "Result:", s self.assert_(s == '2M 2w 2d 2h 2m 2s ago') # Now with a limit, because here it's just a nightmare to read s = self.helper.print_duration(now - 2 - 120 - 3600*2 - 3600*24*2 - 86400*14 - 86400*56, x_elts=2) print "Result:", s self.assert_(s == '2M 2w ago') # Return to the future # Get the 2s ago s = self.helper.print_duration(now + 2) print "Result:", s self.assert_(s == 'in 2s') # Got 2minutes s = self.helper.print_duration(now + 120) print "Result:", s self.assert_(s == 'in 2m') # Go 2hours ago s = self.helper.print_duration(now + 3600*2) print "Result:", s self.assert_(s == 'in 2h') # Go 2 days ago s = self.helper.print_duration(now + 3600*24*2) print "Result:", s self.assert_(s == 'in 2d') # Go 2 weeks ago s = self.helper.print_duration(now + 86400*14) print "Result:", s self.assert_(s == 'in 2w') # Go 2 months ago s = self.helper.print_duration(now + 86400*56) print "Result:", s self.assert_(s == 'in 2M') # Go 1 year ago s = self.helper.print_duration(now + 86400*365*2) print "Result:", s self.assert_(s == 'in 2y') # Now a mix of all of this :) s = self.helper.print_duration(now + 2 + 120 + 3600*2 + 3600*24*2 + 86400*14 + 86400*56) print "Result:", s self.assert_(s == 'in 2M 2w 2d 2h 2m 2s') # Now with a limit, because here it's just a nightmare to read s = self.helper.print_duration(now + 2 - 120 + 3600*2 + 3600*24*2 + 86400*14 + 86400*56, x_elts=2) print "Result:", s self.assert_(s == 'in 2M 2w') def test_03_get_business_impact_text(self): print "---" # Parameters errors s = self.helper.get_html_business_impact(10) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_business_impact(6, text=False) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_business_impact(-1) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_business_impact(1, False, False) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_business_impact(1, text=False, icon=False) print "Result:", s self.assert_(s == 'n/a') # Default ... text and stars s = self.helper.get_html_business_impact(0) print "Result:", s self.assert_(s == 'None') s = self.helper.get_html_business_impact(1) print "Result:", s self.assert_(s == 'Low') s = self.helper.get_html_business_impact(2) print "Result:", s self.assert_(s == 'Normal') s = self.helper.get_html_business_impact(3) print "Result:", s self.assert_(s == 'Important <i class="fa fa-star text-primary"></i>') s = self.helper.get_html_business_impact(4) print "Result:", s self.assert_(s == 'Very important <i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i>') s = self.helper.get_html_business_impact(5) print "Result:", s self.assert_(s == 'Business critical <i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i>') # Stars only ... s = self.helper.get_html_business_impact(0, text=False) print "Result:", s self.assert_(s == '') s = self.helper.get_html_business_impact(1, text=False) print "Result:", s self.assert_(s == '') s = self.helper.get_html_business_impact(2, text=False) print "Result:", s self.assert_(s == '') s = self.helper.get_html_business_impact(3, text=False) print "Result:", s self.assert_(s == '<i class="fa fa-star text-primary"></i>') s = self.helper.get_html_business_impact(4, text=False) print "Result:", s self.assert_(s == '<i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i>') s = self.helper.get_html_business_impact(5, text=False) print "Result:", s self.assert_(s == '<i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i><i class="fa fa-star text-primary"></i>') # Text only ... s = self.helper.get_html_business_impact(0, icon=False) print "Result:", s self.assert_(s == 'None') s = self.helper.get_html_business_impact(1, icon=False) print "Result:", s self.assert_(s == 'Low') s = self.helper.get_html_business_impact(2, icon=False) print "Result:", s self.assert_(s == 'Normal') s = self.helper.get_html_business_impact(3, icon=False) print "Result:", s self.assert_(s == 'Important') s = self.helper.get_html_business_impact(4, icon=False) print "Result:", s self.assert_(s == 'Very important') s = self.helper.get_html_business_impact(5, icon=False) def test_04_get_state_text(self): print "---" print "Parameters errors:" s = self.helper.get_html_state('', '') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('host', 'bad state') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('service', 'bad state') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('host', 'UP', extra='bad state') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('service', 'OK', extra='bad state') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('host', 'UP', icon=False, text=False) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_state('service', 'OK', icon=False, text=False) print "Result:", s self.assert_(s == 'n/a') def test_05_get_host_state_text(self): print "---" # Host, icon only (default) ... s = self.helper.get_html_state('host', 'UP') print "Result:", s self.assert_(s == '<center class="font-up"><span class="fa-stack" title="host state is UP"><i class="fa fa-circle fa-stack-2x font-up"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'DOWN') print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" title="host state is DOWN"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'UNREACHABLE') print "Result:", s self.assert_(s == '<center class="font-unreachable"><span class="fa-stack" title="host state is UNREACHABLE"><i class="fa fa-circle fa-stack-2x font-unreachable"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'UP', extra='FLAPPING') print "Result:", s self.assert_(s == '<center class="font-up"><span class="fa-stack" title="host state is UP and flapping"><i class="fa fa-circle fa-stack-2x font-up"></i><i class="fa fa-server fa-stack-1x font-up"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='FLAPPING') print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" title="host state is DOWN and flapping"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x font-down"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='ACKNOWLEDGED') print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" style="opacity: 0.5" title="host state is DOWN and acknowledged"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='IN_DOWNTIME') print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" style="opacity: 0.5" title="host state is DOWN but downtime is scheduled"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div></div></center>') # Host, text only ... s = self.helper.get_html_state('host', 'UP', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is UP') s = self.helper.get_html_state('host', 'DOWN', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is DOWN') s = self.helper.get_html_state('host', 'UNREACHABLE', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is UNREACHABLE') s = self.helper.get_html_state('host', 'UP', extra='FLAPPING', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is UP and flapping') s = self.helper.get_html_state('host', 'DOWN', extra='FLAPPING', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is DOWN and flapping') s = self.helper.get_html_state('host', 'DOWN', extra='ACKNOWLEDGED', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is DOWN and acknowledged') s = self.helper.get_html_state('host', 'DOWN', extra='IN_DOWNTIME', text=True, icon=False) print "Result:", s self.assert_(s == 'host state is DOWN but downtime is scheduled') # Host, icon and text ... s = self.helper.get_html_state('host', 'UP', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-up"><span class="fa-stack" title="host state is UP"><i class="fa fa-circle fa-stack-2x font-up"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div>host state is UP</div></center>') s = self.helper.get_html_state('host', 'DOWN', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" title="host state is DOWN"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div>host state is DOWN</div></center>') s = self.helper.get_html_state('host', 'UNREACHABLE', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-unreachable"><span class="fa-stack" title="host state is UNREACHABLE"><i class="fa fa-circle fa-stack-2x font-unreachable"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div>host state is UNREACHABLE</div></center>') s = self.helper.get_html_state('host', 'UP', extra='FLAPPING', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-up"><span class="fa-stack" title="host state is UP and flapping"><i class="fa fa-circle fa-stack-2x font-up"></i><i class="fa fa-server fa-stack-1x font-up"></i></span><div>host state is UP and flapping</div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='FLAPPING', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" title="host state is DOWN and flapping"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x font-down"></i></span><div>host state is DOWN and flapping</div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='ACKNOWLEDGED', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" style="opacity: 0.5" title="host state is DOWN and acknowledged"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div>host state is DOWN and acknowledged</div></center>') s = self.helper.get_html_state('host', 'DOWN', extra='IN_DOWNTIME', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-down"><span class="fa-stack" style="opacity: 0.5" title="host state is DOWN but downtime is scheduled"><i class="fa fa-circle fa-stack-2x font-down"></i><i class="fa fa-server fa-stack-1x fa-inverse"></i></span><div>host state is DOWN but downtime is scheduled</div></center>') def test_06_get_service_state_text(self): print "---" # service, icon only (default) ... s = self.helper.get_html_state('service', 'OK') print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK"><i class="fa fa-circle fa-stack-2x font-ok"></i><i class="fa fa-arrow-up fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'CRITICAL') print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" title="service state is CRITICAL"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'WARNING') print "Result:", s self.assert_(s == '<center class="font-warning"><span class="fa-stack" title="service state is WARNING"><i class="fa fa-circle fa-stack-2x font-warning"></i><i class="fa fa-exclamation fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'UNKNOWN') print "Result:", s self.assert_(s == '<center class="font-unknown"><span class="fa-stack" title="service state is UNKNOWN"><i class="fa fa-circle fa-stack-2x font-unknown"></i><i class="fa fa-question fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'ok', extra='FLAPPING') print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK and flapping"><i class="fa fa-circle fa-stack-2x font-ok"></i><i class="fa fa-arrow-up fa-stack-1x font-ok"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='FLAPPING') print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" title="service state is CRITICAL and flapping"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x font-critical"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='ACKNOWLEDGED') print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" style="opacity: 0.5" title="service state is CRITICAL and acknowledged"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div></div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='IN_DOWNTIME') print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" style="opacity: 0.5" title="service state is CRITICAL but downtime is scheduled"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div></div></center>') # service, text only ... s = self.helper.get_html_state('service', 'OK', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is OK') s = self.helper.get_html_state('service', 'CRITICAL', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is CRITICAL') s = self.helper.get_html_state('service', 'WARNING', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is WARNING') s = self.helper.get_html_state('service', 'UNKNOWN', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is UNKNOWN') s = self.helper.get_html_state('service', 'OK', extra='FLAPPING', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is OK and flapping') s = self.helper.get_html_state('service', 'CRITICAL', extra='FLAPPING', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is CRITICAL and flapping') s = self.helper.get_html_state('service', 'CRITICAL', extra='ACKNOWLEDGED', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is CRITICAL and acknowledged') s = self.helper.get_html_state('service', 'CRITICAL', extra='IN_DOWNTIME', text=True, icon=False) print "Result:", s self.assert_(s == 'service state is CRITICAL but downtime is scheduled') # service, icon and text ... s = self.helper.get_html_state('service', 'OK', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK"><i class="fa fa-circle fa-stack-2x font-ok"></i><i class="fa fa-arrow-up fa-stack-1x fa-inverse"></i></span><div>service state is OK</div></center>') s = self.helper.get_html_state('service', 'CRITICAL', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" title="service state is CRITICAL"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div>service state is CRITICAL</div></center>') s = self.helper.get_html_state('service', 'WARNING', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-warning"><span class="fa-stack" title="service state is WARNING"><i class="fa fa-circle fa-stack-2x font-warning"></i><i class="fa fa-exclamation fa-stack-1x fa-inverse"></i></span><div>service state is WARNING</div></center>') s = self.helper.get_html_state('service', 'UNKNOWN', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-unknown"><span class="fa-stack" title="service state is UNKNOWN"><i class="fa fa-circle fa-stack-2x font-unknown"></i><i class="fa fa-question fa-stack-1x fa-inverse"></i></span><div>service state is UNKNOWN</div></center>') s = self.helper.get_html_state('service', 'ok', extra='FLAPPING', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK and flapping"><i class="fa fa-circle fa-stack-2x font-ok"></i><i class="fa fa-arrow-up fa-stack-1x font-ok"></i></span><div>service state is OK and flapping</div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='FLAPPING', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" title="service state is CRITICAL and flapping"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x font-critical"></i></span><div>service state is CRITICAL and flapping</div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='ACKNOWLEDGED', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" style="opacity: 0.5" title="service state is CRITICAL and acknowledged"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div>service state is CRITICAL and acknowledged</div></center>') s = self.helper.get_html_state('service', 'CRITICAL', extra='IN_DOWNTIME', text=True, icon=True) print "Result:", s self.assert_(s == '<center class="font-critical"><span class="fa-stack" style="opacity: 0.5" title="service state is CRITICAL but downtime is scheduled"><i class="fa fa-circle fa-stack-2x font-critical"></i><i class="fa fa-arrow-down fa-stack-1x fa-inverse"></i></span><div>service state is CRITICAL but downtime is scheduled</div></center>') # Use label instead of built text ... s = self.helper.get_html_state('service', 'OK', text=True, icon=True, label='My own label') print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK"><i class="fa fa-circle fa-stack-2x font-ok"></i><i class="fa fa-arrow-up fa-stack-1x fa-inverse"></i></span><div>My own label</div></center>') # Specify disabled state ... s = self.helper.get_html_state('service', 'OK', text=True, icon=True, label='My own label', disabled=True) print "Result:", s self.assert_(s == '<center class="font-ok"><span class="fa-stack" title="service state is OK"><i class="fa fa-circle fa-stack-2x font-greyed"></i><i class="fa fa-arrow-up fa-stack-1x fa-inverse"></i></span><div>My own label</div></center>') def test_07_get_url(self): print "---" print "Parameters errors:" s = self.helper.get_html_url(None, None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_url('', '') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_url('host', None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_url('bad_type', 'bad') print "Result:", s self.assert_(s == '<a href="/bad_type/bad" title="bad">bad</a>') s = self.helper.get_html_url('host', 'host1') print "Result:", s self.assert_(s == '<a href="/host/host1" title="host1">host1</a>') s = self.helper.get_html_url('service', 'service1') print "Result:", s self.assert_(s == '<a href="/service/service1" title="service1">service1</a>') s = self.helper.get_html_url('host', 'test', 'My label ...') print "Result:", s self.assert_(s == '<a href="/host/test" title="test">My label ...</a>') s = self.helper.get_html_url('contact', 'bob', 'My label ...') print "Result:", s self.assert_(s == '<a href="/contact/bob" title="bob">My label ...</a>') def test_08_get_id(self): print "---" print "Parameters errors:" s = self.helper.get_html_id(None, None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_id('', '') print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_id('host', None) print "Result:", s self.assert_(s == 'n/a') s = self.helper.get_html_id('bad_type', 'bad') print "Result:", s self.assert_(s == 'bad_type-bad') s = self.helper.get_html_id('host', 'host1') print "Result:", s self.assert_(s == 'host-host1') s = self.helper.get_html_id('service', 'service1') print "Result:", s self.assert_(s == 'service-service1') s = self.helper.get_html_id('host', 'test*/-_+)') print "Result:", s self.assert_(s == 'host-test-_') def test_09_search(self): print "---" # Initialize backend communication ... frontend.configure(alignak_webui.app.config.get('ui.backend', 'http://localhost:5000')) print "Frontend: %s", frontend.url_endpoint_root # Configure users' management backend User.set_backend(frontend) # Force authentication ... connection = frontend.login('admin', 'admin', force=True) assert_true(frontend.authenticated) assert_true(frontend.token) connection = frontend.connect(username='******') assert_true(frontend.authenticated) assert_true(frontend.connected) ls = self.helper.get_livestate() print "Search on element type ..." search = self.helper.search_livestate(ls, "type:all") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "type:host") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "type:service") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "host") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "service") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "type:unknown") print "Result, found %d elements" % len(search) print "---" print "Search on element name and content ... " print "found in name ..." search = self.helper.search_livestate(ls, "charnay") print "Result, found %d elements" % len(search) # assert len(search) > 0 print "found in output ..." search = self.helper.search_livestate(ls, "time") print "Result, found %d elements" % len(search) # assert len(search) > 0 print "not found ..." search = self.helper.search_livestate(ls, "test") print "Result, found %d elements" % len(search) print "---" print "Search on element business impact ... " search = self.helper.search_livestate(ls, "bi:0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:=0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:>0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:>=0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:<5") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:<=5") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "bi:>3") print "Result, found %d elements" % len(search) # assert len(search) > 0 print "---" print "Search on element state ... " search = self.helper.search_livestate(ls, "is:ack") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:true") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:yes") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:1") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:ack") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:false") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:no") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "ack:0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:downtime") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:yes") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:true") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:1") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:false") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:no") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "downtime:0") print "Result, found %d elements" % len(search) assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:downtime") print "Result, found %d elements" % len(search) assert len(search) > 0 search = self.helper.search_livestate(ls, "is:0") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:1") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:2") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:3") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:up") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "up") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:down") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "down") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:unreachable") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "unreachable") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:ok") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "OK") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:warning") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "WARNING") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:critical") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "CRITICAL") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:unknown") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "UNKNOWN") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "is:pending") print "Result, found %d elements" % len(search) search = self.helper.search_livestate(ls, "PENDING") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:up") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:down") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:unreachable") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:ok") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:warning") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:critical") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:unknown") print "Result, found %d elements" % len(search) # assert len(search) > 0 search = self.helper.search_livestate(ls, "isnot:pending") print "Result, found %d elements" % len(search) # assert len(search) > 0 # Backend disconnection frontend.disconnect() def test_10_livesynthesis(self): print "---" # Initialize backend communication ... frontend.configure(alignak_webui.app.config.get('ui.backend', 'http://localhost:5000')) print "Frontend: %s", frontend.url_endpoint_root # Configure users' management backend User.set_backend(frontend) # Force authentication ... connection = frontend.login('admin', 'admin', force=True) assert_true(frontend.authenticated) assert_true(frontend.token) connection = frontend.connect(username='******') assert_true(frontend.authenticated) assert_true(frontend.connected) print "Get live synthesis ..." synthesis = self.helper.get_livesynthesis() print "Result:", synthesis assert_true('hosts_synthesis' in synthesis) assert_true('nb_elts' in synthesis['hosts_synthesis']) assert_true('services_synthesis' in synthesis) assert_true('nb_elts' in synthesis['services_synthesis']) print "Get HTML live synthesis ..." synthesis = self.helper.get_html_livesynthesis() print "Result:", synthesis assert 'hosts_states_popover' in synthesis assert 'host state is UP' in synthesis['hosts_states_popover'] assert 'host state is DOWN' in synthesis['hosts_states_popover'] assert 'host state is UNREACHABLE' in synthesis['hosts_states_popover'] assert 'hosts_state' in synthesis # assert False assert 'services_states_popover' in synthesis assert 'service state is OK' in synthesis['services_states_popover'] assert 'service state is WARNING' in synthesis['services_states_popover'] assert 'service state is CRITICAL' in synthesis['services_states_popover'] assert 'services_state' in synthesis # Backend disconnection frontend.disconnect() def test_11_livestate(self): print "---" # Initialize backend communication ... frontend.configure(alignak_webui.app.config.get('ui.backend', 'http://localhost:5000')) print "Frontend: %s", frontend.url_endpoint_root # Configure users' management backend User.set_backend(frontend) # Force authentication ... connection = frontend.login('admin', 'admin', force=True) assert_true(frontend.authenticated) assert_true(frontend.token) connection = frontend.connect(username='******') assert_true(frontend.authenticated) assert_true(frontend.connected) print "Get live state ..." print "Livestate_age: ", self.helper.livestate_age ls = self.helper.get_livestate() print "Livestate_age: ", self.helper.livestate_age print "Livestate: ", self.helper.livestate assert self.helper.livestate_age for item in ls: print "Item:", item assert_true('type' in item) assert_true('id' in item) assert_true('bi' in item) assert_true('name' in item) assert_true('friendly_name' in item) for item in self.helper.livestate: print "Item:", item assert_true('type' in item) assert_true('id' in item) assert_true('bi' in item) assert_true('name' in item) assert_true('friendly_name' in item) assert len(ls) == len(self.helper.livestate) print "Get HTML live state ..." print "Current user: "******"Items:", len(html['rows']) for bi in [0,1,2,3,4,5]: print "Get HTML live state (BI = %d) ..." % bi html = self.helper.get_html_livestate(bi=bi) assert 'bi' in html assert 'rows' in html assert 'panel_bi' in html print "Items:", len(html['rows']) / 2 # for row in html['rows']: # print "Item:", row print "Get HTML live state ... filter" html = self.helper.get_html_livestate(search_filter="type:host") assert 'bi' in html assert 'rows' in html assert 'panel_bi' in html print "Items:", len(html['rows']) for bi in [0,1,2,3,4,5]: print "Get HTML live state (BI = %d) ...and filter" % bi html = self.helper.get_html_livestate(bi=bi, search_filter="type:host") assert 'bi' in html assert 'rows' in html assert 'panel_bi' in html print "Items:", len(html['rows']) # Backend disconnection frontend.disconnect()
def get_realm_members(self, element_id): """Get the realm hosts list""" datamgr = request.app.datamgr realm = datamgr.get_realm(element_id) if not realm: realm = datamgr.get_realm(search={'max_results': 1, 'where': {'name': element_id}}) if not realm: return self.webui.response_invalid_parameters(_('Element does not exist: %s') % element_id) # Get elements from the data manager search = { 'where': {'_realm': realm.id}, 'sort': '-business_impact, -ls_state_id, -ls_last_state_changed' } hosts = datamgr.get_hosts(search=search) logger.debug("get_realm_members, search: %s, found %d hosts", search, len(hosts)) # Get element state configuration items_states = ElementState() items = [] items.append({ 'id': -1, 'type': 'host', 'tr': """ <table class="table table-invisible table-condensed"> <thead><tr> <th></th> <th>%s</th> <th>%s</th> <th>%s</th> <th>%s</th> <th>%s</th> </tr></thead> <tbody> </tbody> </table> """ % ( _("BI"), _("Element"), _("Since"), _("Last check"), _("Output") ) }) for member in hosts: logger.debug("Realm member: %s", member) cfg_state = items_states.get_icon_state('host', member.status) tr = """<tr> <td>%s</td> <td>%s</td> <td>%s</td> <td class="hidden-xs">%s</td> <td class="hidden-xs">%s</td> <td class="hidden-sm hidden-xs">%s: %s</td> </tr>""" % ( member.get_html_state(text=None, title=member.alias), Helper.get_html_business_impact(member.business_impact, icon=True, text=False), member.get_html_link(), Helper.print_duration(member.last_state_changed, duration_only=True, x_elts=2), Helper.print_duration(member.last_check, duration_only=True, x_elts=2), Helper.print_date(member.last_check), member.output ) items.append({ 'id': member.id, 'type': 'host', 'name': member.name, 'alias': member.alias, 'status': member.status, 'icon': 'fa fa-%s item_%s' % (cfg_state['icon'], cfg_state['class']), 'state': member.get_html_state(text=None, title=member.alias), 'tr': tr }) response.status = 200 response.content_type = 'application/json' return json.dumps(items)
def get_map_elements(self, hosts): # pylint:disable=no-self-use, too-many-locals """Get hosts valid for a map: :param hosts: list of hosts to search in :return: tuple with a list of positioned hosts and a list of not yet positioned hosts """ user = request.environ['beaker.session']['current_user'] datamgr = request.app.datamgr # Get elements from the data manager logger.info("worldmap, searching valid hosts...") default_lat = float(self.plugin_parameters['default_latitude']) default_lng = float(self.plugin_parameters['default_longitude']) positioned_hosts = [] for host in hosts: map_host = {} logger.debug("worldmap, found host '%s'", host.name) map_host['positioned'] = True if 'type' not in host.position or host.position['type'] != 'Point': # logger.warning("worldmap, host '%s', invalid position: %s", # host.name, host.position) # continue logger.warning("worldmap, host '%s' has an invalid position", host.name) continue else: logger.debug("worldmap, host '%s' located: %s", host.name, host.position) map_host['lat'] = host['position']['coordinates'][0] map_host['lng'] = host['position']['coordinates'][1] logger.debug("worldmap, host '%s' position: %s, %s", host.name, map_host['lat'], map_host['lng']) if map_host['lat'] == default_lat and map_host['lng'] == default_lng: logger.debug("worldmap, host '%s' is not yet positioned", host.name) map_host['positioned'] = False for attr in ['id', 'name', 'alias', 'business_impact', 'tags', 'position', 'tags', 'notes', 'notes_url', 'action_url', 'overall_state', 'overall_status', 'state_id', 'state_type', 'acknowledged', 'downtimed', 'last_check', 'output', 'long_output']: map_host[attr] = host[attr] host_iw = self.plugin_parameters['host_info_content'] host_iw = host_iw.replace("\n", '') host_iw = host_iw.replace("\r", '') host_iw = host_iw.replace("##id##", map_host['id']) host_iw = host_iw.replace("##name##", map_host['name']) host_iw = host_iw.replace("##state##", map_host['overall_status']) host_iw = host_iw.replace("##bi##", str(map_host['business_impact'])) host_iw = host_iw.replace("##url##", host.get_html_link()) host_iw = host_iw.replace("##html_bi##", Helper.get_html_business_impact(host.business_impact, icon=True, text=False)) host_iw = host_iw.replace("##html_state##", host.get_html_state(text=None, use_status=host.overall_status)) if user.is_power(): host_iw = host_iw.replace("##html_actions##", Helper.get_html_commands_buttons( host, _('<span class="fa fa-bolt"></span>') )) else: host_iw = host_iw.replace("##html_actions##", "") # Get host services # todo: using a projection with selected fields may help to improve more? search = { 'sort': '-_overall_state_id,name', 'where': {} } if self.plugin_parameters.get('services_excluded'): search['where'].update({'name': { "$regex": "^((?!%s).)*$" % self.plugin_parameters['services_excluded']}}) if self.plugin_parameters.get('services_included'): search['where'].update({'name': { "$regex": self.plugin_parameters['services_included']}}) if self.plugin_parameters.get('services_overall_state'): allowed_states = self.plugin_parameters.get('services_overall_state').split(',') allowed_states = [int(value) for value in allowed_states] # {'_overall_state_id': {'$in': [0, 3], '$nin': [4]}} search['where'].update({'_overall_state_id': {"$in": allowed_states}}) logger.info("worldmap, search services: %s", search) services = datamgr.get_host_services(host, search=search, embedded=False) services_iw = "" for service in services: svc_iw = self.plugin_parameters['service_info_content'] svc_iw = svc_iw.replace("\n", '') svc_iw = svc_iw.replace("\r", '') svc_iw = svc_iw.replace("##id##", service['id']) svc_iw = svc_iw.replace("##name##", service['name']) svc_iw = svc_iw.replace("##state##", service['overall_status']) svc_iw = svc_iw.replace("##bi##", str(service['business_impact'])) svc_iw = svc_iw.replace("##url##", service.get_html_link()) svc_iw = svc_iw.replace("##html_bi##", Helper.get_html_business_impact(service.business_impact, icon=True, text=False)) svc_iw = svc_iw.replace("##html_state##", service.get_html_state(text=None, use_status=service.overall_status)) if user.is_power(): svc_iw = svc_iw.replace("##html_actions##", Helper.get_html_commands_buttons( service, _('<span class="fa fa-bolt"></span>') )) else: svc_iw = svc_iw.replace("##html_actions##", "") services_iw += svc_iw logger.debug("worldmap, host '%s' services: %s", host.name, services) map_host.update({'services': services}) host_iw = host_iw.replace("##services##", services_iw) map_host.update({'content': host_iw}) positioned_hosts.append(map_host) return positioned_hosts
def table_data(self): # Because there are many locals needed :) # pylint: disable=too-many-locals """ Return elements data in json format as of Datatables SSP protocol More info: https://datatables.net/manual/server-side Example URL:: POST /? draw=1& columns[0][data]=alias& columns[0][name]=& columns[0][searchable]=true& columns[0][orderable]=true& columns[0][search][value]=& columns[0][search][regex]=false& ... order[0][column]=0& order[0][dir]=asc& start=0& length=10& search[value]=& search[regex]=false& Request parameters are Json formatted Request Parameters: - object_type: object type managed by the datatable - links: urel prefix to be used by the links in the table - embedded: true / false whether the table is embedded by an external application **Note**: those three first parameters are not datatable specific parameters :) - draw, index parameter to be returned in the response Pagination: - start / length, for pagination Searching: - search (value or regexp) search[value]: Global search value. To be applied to all columns which are searchable search[regex]: true if search[value] is a regex Sorting: - order[i][column] / order[i][dir] index of the columns to order and sort direction (asc/desc) Columns: - columns[i][data]: Column's data source, as defined by columns.data. - columns[i][name]: Column's name, as defined by columns.name. - columns[i][searchable]: Flag to indicate if this column is searchable (true). - columns[i][orderable]: Flag to indicate if this column is orderable (true). - columns[i][search][value]: Search value to apply to this specific column. - columns[i][search][regex]: Flag to indicate if the search term for this column is a regex. Response data: - draw - recordsTotal: total records, before filtering (i.e. total number of records in the database) - recordsFiltered: Total records, after filtering (i.e. total number of records after filtering has been applied - not just the number of records being returned for this page of data). - data: The data to be displayed in the table. an array of data source objects, one for each row, which will be used by DataTables. - error (optional): Error message if an error occurs Not included if there is no error. """ # Manage request parameters ... logger.info("request data for table: %s", request.params.get('object_type')) # Because of specific datatables parameters name (eg. columns[0] ...) # ... some parameters have been json.stringify on client side ! params = {} for key in request.params.keys(): if key == 'columns' or key == 'order' or key == 'search': params[key] = json.loads(request.params.get(key)) else: params[key] = request.params.get(key) # params now contains 'valid' query parameters as we should have found them ... logger.debug("table request parameters: %s", params) parameters = {} # Manage page number ... # start is the first requested row and we must transform to a page count ... first_row = int(params.get('start', '0')) # length is the number of requested rows rows_count = int(params.get('length', '25')) parameters['page'] = (first_row // rows_count) + 1 parameters['max_results'] = rows_count logger.info("get %d rows from row #%d -> page: %d", rows_count, first_row, parameters['page']) # Columns ordering # order:[{"column":2,"dir":"desc"}] if 'order' in params and 'columns' in params and params['order']: sorted_columns = [] for order in params['order']: idx = int(order['column']) if params['columns'][idx] and params['columns'][idx]['data']: logger.debug("sort by column %d (%s), order: %s ", idx, params['columns'][idx]['data'], order['dir']) if order['dir'] == 'desc': sorted_columns.append('-' + params['columns'][idx]['data']) else: sorted_columns.append(params['columns'][idx]['data']) if sorted_columns: parameters['sort'] = ','.join(sorted_columns) logger.info("backend order request parameters: %s", parameters) # Individual column search parameter searched_columns = [] if 'columns' in params and params['columns']: for column in params['columns']: if 'searchable' not in column or 'search' not in column: # pragma: no cover continue if 'value' not in column[ 'search'] or not column['search']['value']: continue logger.debug("search column '%s' for '%s'", column['data'], column['search']['value']) for field in self.table_columns: if field['data'] != column['data']: continue # Some specific types... if field['type'] == 'boolean': searched_columns.append({ column['data']: column['search']['value'] == 'true' }) elif field['type'] == 'integer': searched_columns.append( {column['data']: int(column['search']['value'])}) elif field['format'] == 'select': values = column['search']['value'].split(',') if len(values) > 1: searched_columns.append( {column['data']: { "$in": values }}) else: searched_columns.append( {column['data']: values[0]}) # ... the other fields :) else: # Do not care about 'smart' and 'caseInsensitive' boolean parameters ... if column['search']['regex']: searched_columns.append({ column['data']: { "$regex": ".*" + column['search']['value'] + ".*" } }) else: searched_columns.append( {column['data']: column['search']['value']}) break logger.info("backend search columns parameters: %s", searched_columns) # Global search parameter # search:{"value":"test","regex":false} searched_global = [] # pylint: disable=too-many-nested-blocks # Will be too complex else ... if 'search' in params and 'columns' in params and params['search']: if 'value' in params['search'] and params['search']['value']: logger.debug("search requested, value: %s ", params['search']['value']) for column in params['columns']: if 'searchable' in column and column['searchable']: logger.debug("search global '%s' for '%s'", column['data'], params['search']['value']) if 'regex' in params['search']: if params['search']['regex']: searched_global.append({ column['data']: { "$regex": ".*" + params['search']['value'] + ".*" } }) else: searched_global.append({ column['data']: params['search']['value'] }) logger.info("backend search global parameters: %s", searched_global) if searched_columns and searched_global: parameters['where'] = { "$and": [{ "$and": searched_columns }, { "$or": searched_global }] } if searched_columns: parameters['where'] = {"$and": searched_columns} if searched_global: parameters['where'] = {"$or": searched_global} # Embed linked resources parameters['embedded'] = {} for field in self.table_columns: if field['type'] == 'objectid' and field['format'] != 'objectid': parameters['embedded'].update({field['data']: 1}) if parameters['embedded']: logger.info("backend embedded parameters: %s", parameters['embedded']) # Update global table records count, require total count from backend self.records_total = self.backend.count(self.object_type) # Request objects from the backend ... logger.debug("table data get parameters: %s", parameters) items = self.backend.get(self.object_type, params=parameters) if not items: # Empty response return json.dumps({ # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": 0, "recordsFiltered": 0, "data": [] }) # Create an object ... object_class = [ kc for kc in self.datamgr.known_classes if kc.get_type() == self.object_type ][0] bo_object = object_class() # Update inner properties self.id_property = '_id' if hasattr(bo_object.__class__, 'id_property'): self.id_property = bo_object.__class__.id_property self.name_property = 'name' if hasattr(bo_object.__class__, 'name_property'): self.name_property = bo_object.__class__.name_property self.status_property = 'status' if hasattr(bo_object.__class__, 'status_property'): self.status_property = bo_object.__class__.status_property # Change item content ... for item in items: bo_object = object_class(item) logger.debug("livestate object item: %s", bo_object) for key in item.keys(): for field in self.table_columns: if field['data'] != key: continue if field['data'] == self.name_property: item[key] = bo_object.get_html_link( prefix=request.params.get('links')) if field['data'] == self.status_property: item[key] = bo_object.get_html_state() if field['data'] == "business_impact": item[key] = Helper.get_html_business_impact( bo_object.business_impact) # Specific fields type if field['type'] == 'datetime' or field['format'] == 'date': item[key] = bo_object.get_date(item[key]) if field['type'] == 'boolean': item[key] = Helper.get_on_off(item[key]) if field['type'] == 'list': item[key] = Helper.get_html_item_list( bo_object.id, key, getattr(bo_object, key), title=field['title']) if field['type'] == 'objectid' and \ key in parameters['embedded'] and item[key]: related_object_class = [ kc for kc in self.datamgr.known_classes if kc.get_type() == field['format'] ][0] linked_object = related_object_class(item[key]) item[key] = linked_object.get_html_link( prefix=request.params.get('links')) break # Very specific fields... if self.responsive: item['#'] = '' # Total number of filtered records self.records_filtered = self.records_total if 'where' in parameters and parameters['where'] != {}: logger.debug("update filtered records: %s", parameters['where']) self.records_filtered = len(items) logger.info("filtered records: %d out of total: %d", self.records_filtered, self.records_total) # Prepare response rsp = { # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": self.records_total, "recordsFiltered": self.records_filtered, "data": items } return json.dumps(rsp)
def table_data(self, plugin_table): # Because there are many locals needed :) # pylint: disable=too-many-locals """Return elements data in json format as of Datatables SSP protocol More info: https://datatables.net/manual/server-side Example URL:: POST /? draw=1& columns[0][data]=alias& columns[0][name]=& columns[0][searchable]=true& columns[0][orderable]=true& columns[0][search][value]=& columns[0][search][regex]=false& ... order[0][column]=0& order[0][dir]=asc& start=0& length=10& search[value]=& search[regex]=false& Request parameters are Json formatted Request Parameters: - object_type: object type managed by the datatable - links: url prefix to be used by the links in the table - embedded: true / false whether the table is embedded by an external application **Note**: those three first parameters are not datatable specific parameters :) - draw, index parameter to be returned in the response Pagination: - start / length, for pagination Searching: - search (value or regexp) search[value]: Global search value. To be applied to all columns which are searchable search[regex]: true if search[value] is a regex Sorting: - order[i][column] / order[i][dir] index of the columns to order and sort direction (asc/desc) Columns: - columns[i][data]: Column's data source, as defined by columns.data. - columns[i][name]: Column's name, as defined by columns.name. - columns[i][searchable]: Flag to indicate if this column is searchable (true). - columns[i][orderable]: Flag to indicate if this column is orderable (true). - columns[i][search][value]: Search value to apply to this specific column. - columns[i][search][regex]: Flag to indicate if the search term for this column is a regex. Response data: - draw - recordsTotal: total records, before filtering (i.e. total number of records in the database) - recordsFiltered: Total records, after filtering (i.e. total number of records after filtering has been applied - not just the number of records being returned for this page of data). - data: The data to be displayed in the table. an array of data source objects, one for each row, which will be used by DataTables. - error (optional): Error message if an error occurs Not included if there is no error. """ # Manage request parameters ... logger.info("request data for table: %s, templates: %s", request.forms.get('object_type'), self.templates) # Because of specific datatables parameters name (eg. columns[0] ...) # ... some parameters have been json.stringify on client side ! params = {} for key in list(request.params.keys()): if key in ['columns', 'order', 'search']: params[key] = json.loads(request.params.get(key)) else: params[key] = request.params.get(key) # params now contains 'valid' query parameters as we should have found them ... logger.debug("table request parameters: %s", params) parameters = {} # Manage page number ... # start is the first requested row and we must transform to a page count ... first_row = int(params.get('start', '0')) # length is the number of requested rows rows_count = int(params.get('length', '25')) parameters['page'] = (first_row // rows_count) + 1 parameters['max_results'] = rows_count logger.debug("get %d rows from row #%d -> page: %d", rows_count, first_row, parameters['page']) # Columns ordering # order:[{"column":2,"dir":"desc"}] if 'order' in params and 'columns' in params and params['order']: sorted_columns = [] for order in params['order']: idx = int(order['column']) if params['columns'][idx] and params['columns'][idx]['data']: logger.debug( "sort by column %d (%s), order: %s ", idx, params['columns'][idx]['data'], order['dir'] ) if order['dir'] == 'desc': sorted_columns.append('-' + params['columns'][idx]['data']) else: sorted_columns.append(params['columns'][idx]['data']) if sorted_columns: parameters['sort'] = ','.join(sorted_columns) logger.info("backend order request parameters: %s", parameters) # Individual column search parameter s_columns = [] if 'columns' in params and params['columns']: for column in params['columns']: if 'searchable' not in column or 'search' not in column: # pragma: no cover continue if 'value' not in column['search'] or not column['search']['value']: continue logger.debug("search column '%s' for '%s'", column['data'], column['search']['value']) for field in self.table_columns: if field['data'] != column['data']: continue # Some specific types... if field['type'] == 'boolean': s_columns.append( {column['data']: column['search']['value'] == 'true'} ) elif field['type'] == 'integer': s_columns.append( {column['data']: int(column['search']['value'])} ) elif field['format'] == 'select': values = column['search']['value'].split(',') if len(values) > 1: s_columns.append( { column['data']: { "$in": values } } ) else: s_columns.append( {column['data']: values[0]} ) # ... the other fields :) else: # Do not care about 'smart' and 'caseInsensitive' boolean parameters ... if column['search']['regex']: s_columns.append( { column['data']: { "$regex": ".*" + column['search']['value'] + ".*" } } ) else: s_columns.append( {column['data']: column['search']['value']} ) break logger.info("backend search individual columns parameters: %s", s_columns) # Global search parameter # search:{"value":"test","regex":false} s_global = {} # pylint: disable=too-many-nested-blocks # Will be too complex else ... if 'search' in params and 'columns' in params and params['search']: # params['search'] contains something like: {u'regex': False, u'value': u'name:pi1'} # global regex is always ignored ... in favor of the column declared regex logger.info("global search requested: %s ", params['search']) if 'value' in params['search'] and params['search']['value']: # There is something to search for... logger.debug("search requested, value: %s ", params['search']['value']) # New strategy: decode search patterns... search = Helper.decode_search(params['search']['value'], plugin_table) logger.info("decoded search pattern: %s", search) # Old strategy: search for the value in all the searchable columns... # if not search: # logger.info("applying datatable search pattern...") # for column in params['columns']: # if not column['searchable']: # continue # logger.debug("search global '%s' for '%s'", # column['data'], params['search']['value']) # if 'regex' in params['search']: # if params['search']['regex']: # s_global.update( # {column['data']: { # "$regex": ".*" + params['search']['value'] + ".*"}}) # else: # s_global.update({column['data']: params['search']['value']}) s_global = search logger.info("backend search global parameters: %s", s_global) # Specific hack to filter the log check results that are not dated! if self.object_type == 'logcheckresult': s_columns.append({"last_check": {"$ne": 0}}) if s_columns and s_global: parameters['where'] = {"$and": [{"$and": s_columns}, s_global]} elif s_columns: parameters['where'] = {"$and": s_columns} elif s_global: parameters['where'] = s_global # Embed linked resources / manage templated resources parameters['embedded'] = {} for field in self.embedded: parameters['embedded'].update({field: 1}) logger.debug("backend embedded parameters: %s", parameters['embedded']) # Count total elements excluding templates if necessary if self.is_templated: if self.ui_visibility: self.records_total = self.datamgr.my_backend.count( self.object_type, params={'where': {'_is_template': self.templates, 'webui_visible': True}} ) else: self.records_total = self.datamgr.my_backend.count( self.object_type, params={'where': {'_is_template': self.templates}} ) if 'where' in parameters: parameters['where'].update({'_is_template': self.templates}) else: parameters['where'] = {'_is_template': self.templates} else: if self.ui_visibility: self.records_total = self.datamgr.my_backend.count( self.object_type, params={'where': {'webui_visible': True}} ) else: self.records_total = self.datamgr.my_backend.count(self.object_type) if self.ui_visibility: if 'where' in parameters: parameters['where'].update({'webui_visible': True}) else: parameters['where'] = {'webui_visible': True} # Request objects from the backend ... logger.info("table data get parameters: %s", parameters) items = self.datamgr.my_backend.get(self.object_type, params=parameters) logger.info("table data got %d items", len(items)) if not items: logger.info("No backend elements match search criteria: %s", parameters) # Empty response return json.dumps({ # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": 0, "recordsFiltered": 0, "data": [] }) # Create an object ... object_class = [kc for kc in self.datamgr.known_classes if kc.get_type() == self.object_type] if not object_class: # pragma: no cover, should never happen! logger.warning("datatable, unknown object type: %s", self.object_type) # Empty response return json.dumps({ # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": 0, "recordsFiltered": 0, "data": [] }) # Update table inner properties with the object class defined properties object_class = object_class[0] self.id_property = '_id' if hasattr(object_class, 'id_property'): self.id_property = object_class.id_property self.name_property = 'name' if hasattr(object_class, 'name_property'): self.name_property = object_class.name_property self.status_property = 'status' if hasattr(object_class, 'status_property'): self.status_property = object_class.status_property logger.debug("datatable, object type: '%s' and properties: %s / %s / %s", object_class, self.id_property, self.name_property, self.status_property) # Change item content... rows = [] # Total number of filtered records self.records_filtered = self.records_total for item in items: bo_object = object_class(item) if not bo_object.ui_visible: logger.debug("Not UI visible object: %s", bo_object) continue logger.info("table data object: %s", bo_object) logger.debug("table data object: %s", bo_object) # This is an awful hack that allows to update the objects filtered for a table. # Two main interests: # - update the backend because some massive modifications are necessary for testing # - prepare a massive update feature in the Web UI :) # ----- # if self.is_templated and self.templates and self.object_type == 'service': # logger.warning("service template: %s for host: %s", # bo_object.name, bo_object['host']) # if bo_object['host'].name.startswith('fdj'): # logger.info("To be updated...") # data = { # "check_freshness": True, # "freshness_threshold": 86400, # "passive_checks_enabled": True, # "active_checks_enabled": False # } # result = self.datamgr.update_object(element=bo_object, data=data) # if result is True: # logger.info("updated.") # else: # logger.error("update failed!") # ----- # Each item contains the total number of records matching the search filter self.records_filtered = item['_total'] row = {} row['DT_RowData'] = {} row['_id'] = bo_object.id for field in self.table_columns: logger.debug(" - field: %s", field) # Specific fields if field['data'] == self.name_property: # Create a link to navigate to the item page row[self.name_property] = bo_object.html_link # Store the item name in a specific field of the row. # The value will be retrieved by the table actions (ack, recheck, ...) row['DT_RowData'].update({"object_%s" % self.object_type: bo_object.name}) continue if field['data'] == self.status_property: # Replace the text status with the specific item HTML state row[self.status_property] = bo_object.get_html_state(text=None, title=bo_object.status) # Use the item status to specify the table row class # row['DT_RowClass'] = "table-row-%s" % (bo_object.status.lower()) continue if field['data'] in ['_overall_state_id', 'overall_state', 'overall_status']: # Get the item overall state from the data manager f_get_overall_state = getattr(self.datamgr, 'get_%s_overall_state' % self.object_type) if f_get_overall_state: (dummy, overall_status) = f_get_overall_state(bo_object) # Get element state configuration row[field['data']] = ElementState().get_html_state( self.object_type, bo_object, text=None, title=bo_object.overall_state_to_title[bo_object.overall_state], use_status=overall_status ) # Use the item overall state to specify the table row class row['DT_RowClass'] = "table-row-%s" % (overall_status) else: # pragma: no cover, should never happen! logger.warning("Missing get_overall_state method for: %s", self.object_type) row[field['data']] = 'XxX' continue if "business_impact" in field['data']: # Replace the BI count with the specific item HTML formatting row[field['data']] = Helper.get_html_business_impact(bo_object.business_impact) continue # Specific fields type if field['type'] == 'datetime' or field['format'] == 'datetime': # Replace the timestamp with the formatted date row[field['data']] = bo_object.get_date(bo_object[field['data']]) continue if field['type'] == 'boolean': # Replace the boolean vaue with the specific item HTML formatting row[field['data']] = Helper.get_on_off(bo_object[field['data']]) continue if field['type'] == 'list': # Replace the list with the specific list HTML formatting if hasattr(bo_object, field['data']): row[field['data']] = Helper.get_html_item_list( bo_object.id, field['data'], getattr(bo_object, field['data']), title=field['title'] ) else: row[field['data']] = 'Unknown' continue if field['type'] == 'dict': # Replace the dictionary with the specific dict HTML formatting row[field['data']] = Helper.get_html_item_list( bo_object.id, field['data'], getattr(bo_object, field['data']), title=field['title'] ) continue if field['type'] == 'objectid': if isinstance(bo_object[field['data']], BackendElement): row[field['data']] = bo_object[field['data']].get_html_link( prefix=request.params.get('links') ) # row['DT_RowData'].update({ # "object_%s" % field['data']: bo_object[field['data']].name # }) else: logger.warning("Table field is supposed to be an object: %s, %s = %s", bo_object.name, field['data'], getattr(bo_object, field['data'])) row[field['data']] = getattr(bo_object, field['data']) if row[field['data']] == field['resource']: row[field['data']] = '...' continue # For any non-specific fields, send the field value to the table row[field['data']] = getattr(bo_object, field['data'], 'unset') logger.debug(" -> field: %s", field) logger.debug("table data row: %s", row) # logger.debug("Table row: %s", row) rows.append(row) logger.debug("filtered records: %d out of total: %d", self.records_filtered, self.records_total) # Send response return json.dumps({ "draw": int(float(params.get('draw', '0'))), "recordsTotal": self.records_total, "recordsFiltered": self.records_filtered, "data": rows })
def get_map_elements(self, hosts): # pylint:disable=no-self-use, too-many-locals """Get hosts valid for a map: :param hosts: list of hosts to search in :return: tuple with a list of positioned hosts and a list of not yet positioned hosts """ user = request.environ['beaker.session']['current_user'] datamgr = request.app.datamgr # Get elements from the data manager logger.info("worldmap, searching valid hosts...") default_lat = float(self.plugin_parameters['default_latitude']) default_lng = float(self.plugin_parameters['default_longitude']) positioned_hosts = [] for host in hosts: map_host = {} logger.debug("worldmap, found host '%s'", host.name) map_host['positioned'] = True if 'type' not in host.position or host.position['type'] != 'Point': # logger.warning("worldmap, host '%s', invalid position: %s", # host.name, host.position) # continue logger.warning("worldmap, host '%s' has an invalid position", host.name) continue else: logger.debug("worldmap, host '%s' located: %s", host.name, host.position) map_host['lat'] = host['position']['coordinates'][0] map_host['lng'] = host['position']['coordinates'][1] logger.debug("worldmap, host '%s' position: %s, %s", host.name, map_host['lat'], map_host['lng']) if map_host['lat'] == default_lat and map_host[ 'lng'] == default_lng: logger.debug("worldmap, host '%s' is not yet positioned", host.name) map_host['positioned'] = False for attr in [ 'id', 'name', 'alias', 'business_impact', 'tags', 'position', 'tags', 'notes', 'notes_url', 'action_url', 'overall_state', 'overall_status', 'state_id', 'state_type', 'acknowledged', 'downtimed', 'last_check', 'output', 'long_output' ]: map_host[attr] = host[attr] host_iw = self.plugin_parameters['host_info_content'] host_iw = host_iw.replace("\n", '') host_iw = host_iw.replace("\r", '') host_iw = host_iw.replace("##id##", map_host['id']) host_iw = host_iw.replace("##name##", map_host['name']) host_iw = host_iw.replace("##state##", map_host['overall_status']) host_iw = host_iw.replace("##bi##", str(map_host['business_impact'])) host_iw = host_iw.replace("##url##", host.get_html_link()) host_iw = host_iw.replace( "##html_bi##", Helper.get_html_business_impact(host.business_impact, icon=True, text=False)) host_iw = host_iw.replace( "##html_state##", host.get_html_state(text=None, use_status=host.overall_status)) if user.is_power(): host_iw = host_iw.replace( "##html_actions##", Helper.get_html_commands_buttons( host, _('<span class="fa fa-bolt"></span>'))) else: host_iw = host_iw.replace("##html_actions##", "") # Get host services # todo: using a projection with selected fields may help to improve more? search = {'sort': '-_overall_state_id,name', 'where': {}} if self.plugin_parameters.get('services_excluded'): search['where'].update({ 'name': { "$regex": "^((?!%s).)*$" % self.plugin_parameters['services_excluded'] } }) if self.plugin_parameters.get('services_included'): search['where'].update({ 'name': { "$regex": self.plugin_parameters['services_included'] } }) if self.plugin_parameters.get('services_overall_state'): allowed_states = self.plugin_parameters.get( 'services_overall_state').split(',') allowed_states = [int(value) for value in allowed_states] # {'_overall_state_id': {'$in': [0, 3], '$nin': [4]}} search['where'].update( {'_overall_state_id': { "$in": allowed_states }}) logger.info("worldmap, search services: %s", search) services = datamgr.get_host_services(host, search=search, embedded=False) services_iw = "" for service in services: svc_iw = self.plugin_parameters['service_info_content'] svc_iw = svc_iw.replace("\n", '') svc_iw = svc_iw.replace("\r", '') svc_iw = svc_iw.replace("##id##", service['id']) svc_iw = svc_iw.replace("##name##", service['name']) svc_iw = svc_iw.replace("##state##", service['overall_status']) svc_iw = svc_iw.replace("##bi##", str(service['business_impact'])) svc_iw = svc_iw.replace("##url##", service.get_html_link()) svc_iw = svc_iw.replace( "##html_bi##", Helper.get_html_business_impact(service.business_impact, icon=True, text=False)) svc_iw = svc_iw.replace( "##html_state##", service.get_html_state(text=None, use_status=service.overall_status)) if user.is_power(): svc_iw = svc_iw.replace( "##html_actions##", Helper.get_html_commands_buttons( service, _('<span class="fa fa-bolt"></span>'))) else: svc_iw = svc_iw.replace("##html_actions##", "") services_iw += svc_iw logger.debug("worldmap, host '%s' services: %s", host.name, services) map_host.update({'services': services}) host_iw = host_iw.replace("##services##", services_iw) map_host.update({'content': host_iw}) positioned_hosts.append(map_host) return positioned_hosts
def table_data(self, plugin_table): # Because there are many locals needed :) # pylint: disable=too-many-locals """Return elements data in json format as of Datatables SSP protocol More info: https://datatables.net/manual/server-side Example URL:: POST /? draw=1& columns[0][data]=alias& columns[0][name]=& columns[0][searchable]=true& columns[0][orderable]=true& columns[0][search][value]=& columns[0][search][regex]=false& ... order[0][column]=0& order[0][dir]=asc& start=0& length=10& search[value]=& search[regex]=false& Request parameters are Json formatted Request Parameters: - object_type: object type managed by the datatable - links: url prefix to be used by the links in the table - embedded: true / false whether the table is embedded by an external application **Note**: those three first parameters are not datatable specific parameters :) - draw, index parameter to be returned in the response Pagination: - start / length, for pagination Searching: - search (value or regexp) search[value]: Global search value. To be applied to all columns which are searchable search[regex]: true if search[value] is a regex Sorting: - order[i][column] / order[i][dir] index of the columns to order and sort direction (asc/desc) Columns: - columns[i][data]: Column's data source, as defined by columns.data. - columns[i][name]: Column's name, as defined by columns.name. - columns[i][searchable]: Flag to indicate if this column is searchable (true). - columns[i][orderable]: Flag to indicate if this column is orderable (true). - columns[i][search][value]: Search value to apply to this specific column. - columns[i][search][regex]: Flag to indicate if the search term for this column is a regex. Response data: - draw - recordsTotal: total records, before filtering (i.e. total number of records in the database) - recordsFiltered: Total records, after filtering (i.e. total number of records after filtering has been applied - not just the number of records being returned for this page of data). - data: The data to be displayed in the table. an array of data source objects, one for each row, which will be used by DataTables. - error (optional): Error message if an error occurs Not included if there is no error. """ # Manage request parameters ... logger.info("request data for table: %s, templates: %s", request.forms.get('object_type'), self.templates) # Because of specific datatables parameters name (eg. columns[0] ...) # ... some parameters have been json.stringify on client side ! params = {} for key in list(request.params.keys()): if key in ['columns', 'order', 'search']: params[key] = json.loads(request.params.get(key)) else: params[key] = request.params.get(key) # params now contains 'valid' query parameters as we should have found them ... logger.debug("table request parameters: %s", params) parameters = {} # Manage page number ... # start is the first requested row and we must transform to a page count ... first_row = int(params.get('start', '0')) # length is the number of requested rows rows_count = int(params.get('length', '25')) parameters['page'] = (first_row // rows_count) + 1 parameters['max_results'] = rows_count logger.debug("get %d rows from row #%d -> page: %d", rows_count, first_row, parameters['page']) # Columns ordering # order:[{"column":2,"dir":"desc"}] if 'order' in params and 'columns' in params and params['order']: sorted_columns = [] for order in params['order']: idx = int(order['column']) if params['columns'][idx] and params['columns'][idx]['data']: logger.debug("sort by column %d (%s), order: %s ", idx, params['columns'][idx]['data'], order['dir']) if order['dir'] == 'desc': sorted_columns.append('-' + params['columns'][idx]['data']) else: sorted_columns.append(params['columns'][idx]['data']) if sorted_columns: parameters['sort'] = ','.join(sorted_columns) logger.info("backend order request parameters: %s", parameters) # Individual column search parameter s_columns = [] if 'columns' in params and params['columns']: for column in params['columns']: if 'searchable' not in column or 'search' not in column: # pragma: no cover continue if 'value' not in column[ 'search'] or not column['search']['value']: continue logger.debug("search column '%s' for '%s'", column['data'], column['search']['value']) for field in self.table_columns: if field['data'] != column['data']: continue # Some specific types... if field['type'] == 'boolean': s_columns.append({ column['data']: column['search']['value'] == 'true' }) elif field['type'] == 'integer': s_columns.append( {column['data']: int(column['search']['value'])}) elif field['format'] == 'select': values = column['search']['value'].split(',') if len(values) > 1: s_columns.append({column['data']: {"$in": values}}) else: s_columns.append({column['data']: values[0]}) # ... the other fields :) else: # Do not care about 'smart' and 'caseInsensitive' boolean parameters ... if column['search']['regex']: s_columns.append({ column['data']: { "$regex": ".*" + column['search']['value'] + ".*" } }) else: s_columns.append( {column['data']: column['search']['value']}) break logger.info("backend search individual columns parameters: %s", s_columns) # Global search parameter # search:{"value":"test","regex":false} s_global = {} # pylint: disable=too-many-nested-blocks # Will be too complex else ... if 'search' in params and 'columns' in params and params['search']: # params['search'] contains something like: {u'regex': False, u'value': u'name:pi1'} # global regex is always ignored ... in favor of the column declared regex logger.info("global search requested: %s ", params['search']) if 'value' in params['search'] and params['search']['value']: # There is something to search for... logger.debug("search requested, value: %s ", params['search']['value']) # New strategy: decode search patterns... search = Helper.decode_search(params['search']['value'], plugin_table) logger.info("decoded search pattern: %s", search) # Old strategy: search for the value in all the searchable columns... # if not search: # logger.info("applying datatable search pattern...") # for column in params['columns']: # if not column['searchable']: # continue # logger.debug("search global '%s' for '%s'", # column['data'], params['search']['value']) # if 'regex' in params['search']: # if params['search']['regex']: # s_global.update( # {column['data']: { # "$regex": ".*" + params['search']['value'] + ".*"}}) # else: # s_global.update({column['data']: params['search']['value']}) s_global = search logger.info("backend search global parameters: %s", s_global) # Specific hack to filter the log check results that are not dated! if self.object_type == 'logcheckresult': s_columns.append({"last_check": {"$ne": 0}}) if s_columns and s_global: parameters['where'] = {"$and": [{"$and": s_columns}, s_global]} elif s_columns: parameters['where'] = {"$and": s_columns} elif s_global: parameters['where'] = s_global # Embed linked resources / manage templated resources parameters['embedded'] = {} for field in self.embedded: parameters['embedded'].update({field: 1}) logger.debug("backend embedded parameters: %s", parameters['embedded']) # Count total elements excluding templates if necessary if self.is_templated: if self.ui_visibility: self.records_total = self.datamgr.my_backend.count( self.object_type, params={ 'where': { '_is_template': self.templates, 'webui_visible': True } }) else: self.records_total = self.datamgr.my_backend.count( self.object_type, params={'where': { '_is_template': self.templates }}) if 'where' in parameters: parameters['where'].update({'_is_template': self.templates}) else: parameters['where'] = {'_is_template': self.templates} else: if self.ui_visibility: self.records_total = self.datamgr.my_backend.count( self.object_type, params={'where': { 'webui_visible': True }}) else: self.records_total = self.datamgr.my_backend.count( self.object_type) if self.ui_visibility: if 'where' in parameters: parameters['where'].update({'webui_visible': True}) else: parameters['where'] = {'webui_visible': True} # Request objects from the backend ... logger.info("table data get parameters: %s", parameters) items = self.datamgr.my_backend.get(self.object_type, params=parameters) logger.info("table data got %d items", len(items)) if not items: logger.info("No backend elements match search criteria: %s", parameters) # Empty response return json.dumps({ # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": 0, "recordsFiltered": 0, "data": [] }) # Create an object ... object_class = [ kc for kc in self.datamgr.known_classes if kc.get_type() == self.object_type ] if not object_class: # pragma: no cover, should never happen! logger.warning("datatable, unknown object type: %s", self.object_type) # Empty response return json.dumps({ # draw is the request number ... "draw": int(params.get('draw', '0')), "recordsTotal": 0, "recordsFiltered": 0, "data": [] }) # Update table inner properties with the object class defined properties object_class = object_class[0] self.id_property = '_id' if hasattr(object_class, 'id_property'): self.id_property = object_class.id_property self.name_property = 'name' if hasattr(object_class, 'name_property'): self.name_property = object_class.name_property self.status_property = 'status' if hasattr(object_class, 'status_property'): self.status_property = object_class.status_property logger.debug( "datatable, object type: '%s' and properties: %s / %s / %s", object_class, self.id_property, self.name_property, self.status_property) # Change item content... rows = [] # Total number of filtered records self.records_filtered = self.records_total for item in items: bo_object = object_class(item) if not bo_object.ui_visible: logger.debug("Not UI visible object: %s", bo_object) continue logger.info("table data object: %s", bo_object) logger.debug("table data object: %s", bo_object) # This is an awful hack that allows to update the objects filtered for a table. # Two main interests: # - update the backend because some massive modifications are necessary for testing # - prepare a massive update feature in the Web UI :) # ----- # if self.is_templated and self.templates and self.object_type == 'service': # logger.warning("service template: %s for host: %s", # bo_object.name, bo_object['host']) # if bo_object['host'].name.startswith('fdj'): # logger.info("To be updated...") # data = { # "check_freshness": True, # "freshness_threshold": 86400, # "passive_checks_enabled": True, # "active_checks_enabled": False # } # result = self.datamgr.update_object(element=bo_object, data=data) # if result is True: # logger.info("updated.") # else: # logger.error("update failed!") # ----- # Each item contains the total number of records matching the search filter self.records_filtered = item['_total'] row = {} row['DT_RowData'] = {} row['_id'] = bo_object.id for field in self.table_columns: logger.debug(" - field: %s", field) # Specific fields if field['data'] == self.name_property: # Create a link to navigate to the item page row[self.name_property] = bo_object.html_link # Store the item name in a specific field of the row. # The value will be retrieved by the table actions (ack, recheck, ...) row['DT_RowData'].update( {"object_%s" % self.object_type: bo_object.name}) continue if field['data'] == self.status_property: # Replace the text status with the specific item HTML state row[self.status_property] = bo_object.get_html_state( text=None, title=bo_object.status) # Use the item status to specify the table row class # row['DT_RowClass'] = "table-row-%s" % (bo_object.status.lower()) continue if field['data'] in [ '_overall_state_id', 'overall_state', 'overall_status' ]: # Get the item overall state from the data manager f_get_overall_state = getattr( self.datamgr, 'get_%s_overall_state' % self.object_type) if f_get_overall_state: (dummy, overall_status) = f_get_overall_state(bo_object) # Get element state configuration row[field['data']] = ElementState().get_html_state( self.object_type, bo_object, text=None, title=bo_object.overall_state_to_title[ bo_object.overall_state], use_status=overall_status) # Use the item overall state to specify the table row class row['DT_RowClass'] = "table-row-%s" % (overall_status) else: # pragma: no cover, should never happen! logger.warning( "Missing get_overall_state method for: %s", self.object_type) row[field['data']] = 'XxX' continue if "business_impact" in field['data']: # Replace the BI count with the specific item HTML formatting row[field['data']] = Helper.get_html_business_impact( bo_object.business_impact) continue # Specific fields type if field['type'] == 'datetime' or field['format'] == 'datetime': # Replace the timestamp with the formatted date row[field['data']] = bo_object.get_date( bo_object[field['data']]) continue if field['type'] == 'boolean': # Replace the boolean vaue with the specific item HTML formatting row[field['data']] = Helper.get_on_off( bo_object[field['data']]) continue if field['type'] == 'list': # Replace the list with the specific list HTML formatting if hasattr(bo_object, field['data']): row[field['data']] = Helper.get_html_item_list( bo_object.id, field['data'], getattr(bo_object, field['data']), title=field['title']) else: row[field['data']] = 'Unknown' continue if field['type'] == 'dict': # Replace the dictionary with the specific dict HTML formatting row[field['data']] = Helper.get_html_item_list( bo_object.id, field['data'], getattr(bo_object, field['data']), title=field['title']) continue if field['type'] == 'objectid': if isinstance(bo_object[field['data']], BackendElement): row[field['data']] = bo_object[ field['data']].get_html_link( prefix=request.params.get('links')) # row['DT_RowData'].update({ # "object_%s" % field['data']: bo_object[field['data']].name # }) else: logger.warning( "Table field is supposed to be an object: %s, %s = %s", bo_object.name, field['data'], getattr(bo_object, field['data'])) row[field['data']] = getattr(bo_object, field['data']) if row[field['data']] == field['resource']: row[field['data']] = '...' continue # For any non-specific fields, send the field value to the table row[field['data']] = getattr(bo_object, field['data'], 'unset') logger.debug(" -> field: %s", field) logger.debug("table data row: %s", row) # logger.debug("Table row: %s", row) rows.append(row) logger.debug("filtered records: %d out of total: %d", self.records_filtered, self.records_total) # Send response return json.dumps({ "draw": int(float(params.get('draw', '0'))), "recordsTotal": self.records_total, "recordsFiltered": self.records_filtered, "data": rows })