def get_usergroup_members(self, group_id): """ Get the usergroup users list """ datamgr = request.app.datamgr usergroup = datamgr.get_usergroup(group_id) if not usergroup: usergroup = datamgr.get_usergroup(search={ 'max_results': 1, 'where': { 'name': group_id } }) if not usergroup: return self.webui.response_invalid_parameters( _('Element does not exist: %s') % group_id) items = [] if not isinstance(usergroup.members, str): # Get element state configuration items_states = ElementState() for member in usergroup.members: logger.debug("Group member: %s", member) cfg_state = items_states.get_icon_state('user', member.status) items.append({ 'id': member.id, 'type': 'user', '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), 'url': member.get_html_link() }) response.status = 200 response.content_type = 'application/json' return json.dumps(items)
def get_date(self, _date, fmt=None, duration=False): """Format the provided `_date` as a string according to the specified format. If no date format is specified, it uses the one defined in the ElementState object that is the date format defined in the application configuration. If duration is True, the date is displayed as a pretty date: 1 day 12 minutes ago ... """ if _date == self.__class__._default_date: return _('Never dated!') if duration: return Helper.print_duration(_date, duration_only=False, x_elts=0) item_state = ElementState() if not fmt: if item_state.date_format: fmt = item_state.date_format # Make timestamp to datetime _date = datetime.utcfromtimestamp(_date) # Tell the datetime object that it's in UTC time zone since # datetime objects are 'naive' by default _date = _date.replace(tzinfo=item_state.tz_from) # Convert to required time zone _date = _date.astimezone(item_state.tz_to) if fmt: return _date.strftime(fmt) return _date.isoformat(' ')
def get_html_state(self, extra='', icon=True, text='', title='', disabled=False, object_type=None, object_item=None, size='', use_status=None): # pylint: disable=too-many-arguments """Uses the ElementState singleton to display HTML state for an item""" if self.type.startswith( 'check.result') and self.logcheckresult != 'logcheckresult': return ElementState().get_html_state('logcheckresult', self.logcheckresult, extra, icon, text, title, disabled) return super(History, self).get_html_state(object_type=self.get_type(), object_item=self, extra=extra, icon=icon, text=text, title=title, disabled=disabled, size=size)
def get_group_members(self, group_id): """ Get the servicegroup services list """ datamgr = request.app.datamgr servicegroup = datamgr.get_servicegroup(group_id) if not servicegroup: servicegroup = datamgr.get_servicegroup( search={'max_results': 1, 'where': {'name': group_id}} ) if not servicegroup: return self.webui.response_invalid_parameters(_('Element does not exist: %s') % group_id) items = [] if not isinstance(servicegroup.members, str): # Get element state configuration items_states = ElementState() for member in servicegroup.members: logger.debug("Group member: %s", member) cfg_state = items_states.get_icon_state('service', member.status) items.append({ 'id': member.id, 'type': 'service', 'name': "%s/%s" % (member.host.name, member.name), 'alias': "%s/%s" % (member.host.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), 'url': member.get_html_link() }) response.status = 200 response.content_type = 'application/json' return json.dumps(items)
def test_items_states(self): """ Items - states """ items_states = ElementState() assert items_states.object_types_states assert items_states.default_states assert items_states.states print("Objects types and states", items_states.object_types_states) print("Default states", items_states.default_states) print("Items states", items_states.states) for s in self.config: print(s) s = s.split('.') if s[0] not in ['items', 'bottle'] and len(s) > 1: assert s[1] not in items_states.object_types_states assert s[1] not in items_states.default_states assert s[1] not in items_states.states else: if s[0] not in ['items']: continue print(s) if s[1] == 'item': assert s[1] not in items_states.object_types_states assert s[1] not in items_states.states if len(s) > 2: assert s[2] in items_states.default_states else: assert s[1] not in items_states.default_states if s[1] in ['content', 'back', 'front', 'badge']: assert s[1] not in items_states.object_types_states assert s[1] not in items_states.states continue assert s[1] in items_states.object_types_states assert s[1] in items_states.states if len(s) > 2: assert s[2] in items_states.object_types_states[s[1]] assert s[2] in items_states.states[s[1]] print(s[1], items_states.states[s[1]])
def get_html_state(self, extra='', icon=True, text='', title='', disabled=False, object_type=None, object_item=None, size='', use_status=None): # pylint: disable=too-many-arguments """Uses the ElementState singleton to display HTML state for an item""" if not object_type: object_type = self.object_type if not object_item: object_item = self if not self.is_template: return ElementState().get_html_state(object_type, object_item, extra, icon, text, title, disabled, size, use_status) return self.get_html_link(title=title)
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_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 test_03_html_states(self): print("---") items_states = ElementState() assert items_states.object_types_states assert items_states.default_states assert items_states.states # Objects known states save_object_type = 'user' for object_type in items_states.object_types_states: print("Html for: ", object_type) for state in items_states.get_icon_states(object_type): if state == 'state_view': continue elt = BackendElement({'_id': '0', 'status': state}) print("Html for:", object_type, ", object:", elt) assert items_states.get_html_state(object_type, elt) print("Html : ", items_states.get_html_state(object_type, elt)) # Unknown states print("States for: fake") print(items_states.get_icon_states('fake')) assert not items_states.get_icon_states('fake') print("Html for:", save_object_type, ", state: fake") print("Unknown state") elt = BackendElement({'_id': '0', 'status': 'fake'}) print(items_states.get_html_state(save_object_type, elt)) assert items_states.get_html_state(save_object_type, elt) == 'n/a - status: fake' print("Html for: fake, state: unknown") print("Unknown object type") elt = BackendElement({'_id': '0', 'status': 'unknown'}) # Unknown object_type provides a default user html state ... item_state = items_states.get_html_state('fake', elt) print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="fake"><span class="fa-stack" title="User default text"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>User default text</span></div>''' % elt.id) # Bad parameters print("No icon/text") item_state = items_states.get_html_state(save_object_type, elt, icon=False, text='') print(item_state) self.assertEqual(item_state, 'n/a - icon/text') print("Default icon/text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="User default text"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>User default text</span></div>''' % elt.id) # Other parameters print("Default icon/text - disabled") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='', disabled=True) print(item_state) self.assertEqual( item_state, '''<div class="item-state text-muted " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="User default text"><i class="fa fa-circle fa-stack-2x text-muted"></i><i class="fa fa-user fa-stack-1x "></i></span><span>User default text</span></div>''' % elt.id) print("Default icon/text - title and default text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, title='Test title') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="Test title"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>User default text</span></div>''' % elt.id) print("Default icon/text - title without text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text=None, title='Test title') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="Test title"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span></span></div>''' % elt.id) print("Default icon/text - not title and default text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='Test') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="User default text"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>Test</span></div>''' % elt.id) print("Default icon/text - not title and text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='Test text') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" title="User default text"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>Test text</span></div>''' % elt.id) print("Default icon/text - extra") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='', extra='test') print(item_state) self.assertEqual( item_state, '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user"><span class="fa-stack" style="opacity: 0.7" title="User default texttest"><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x "></i></span><span>User default texttest</span></div>''' % elt.id)
def test_02_items_states(self): print("---") items_states = ElementState() assert items_states.object_types_states assert items_states.default_states assert items_states.states print("Objects types and states", items_states.object_types_states) print("Default states", items_states.default_states) print("Items states", items_states.states) assert items_states.get_objects_types() print("All objects types : ", items_states.get_objects_types()) assert items_states.get_icon_states() print("All objects : ", items_states.get_icon_states()) assert items_states.get_default_states() print("Default states : ", items_states.get_default_states()) # Objects known states for object_type in items_states.object_types_states: assert items_states.get_icon_states(object_type) print(object_type, ", all states: ", items_states.get_icon_states(object_type)) for state in items_states.get_icon_states(object_type): assert items_states.get_icon_state(object_type, state) print(object_type, ", state: ", state, ": ", items_states.get_icon_state(object_type, state)) assert not items_states.get_icon_state(None, None) # Default states are in all objects types for state in items_states.get_default_states(): print("Default state: ", state) for object_type in items_states.object_types_states: assert items_states.get_icon_states(object_type)
def test_html_states(self): """ Items - HTML states """ self.maxDiff = None items_states = ElementState() assert items_states.object_types_states assert items_states.default_states assert items_states.states # Objects known states save_object_type = 'user' for object_type in items_states.object_types_states: print("Html for: ", object_type) for state in items_states.get_icon_states(object_type): if state == 'state_view': continue elt = BackendElement({ '_id': '0', 'status': state }) print("Html for:", object_type, ", object:", elt) assert items_states.get_html_state(object_type, elt) print("Html : ", items_states.get_html_state(object_type, elt)) # Unknown states print("States for: fake") print(items_states.get_icon_states('fake')) assert not items_states.get_icon_states('fake') print("Html for:", save_object_type, ", state: fake") print("Unknown state") elt = BackendElement({ '_id': '0', 'status': 'fake' }) print(items_states.get_html_state(save_object_type, elt)) assert items_states.get_html_state(save_object_type, elt) == 'n/a - status: fake' print("Html for: fake, state: unknown") print("Unknown object type") elt = BackendElement({ '_id': '0', 'status': 'unknown' }) # Unknown object_type provides a default user html state ... item_state = items_states.get_html_state('fake', elt) print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="fake" data-item-state="" title=""><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id # Bad parameters print("No icon/text") item_state = items_states.get_html_state(save_object_type, elt, icon=False, text='') print(item_state) assert item_state == 'n/a - icon/text' print("Default icon/text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title=""><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id # Other parameters print("Default icon/text - disabled") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='', disabled=True) print(item_state) assert item_state == \ '''<div class="item-state text-muted " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title=""><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x text-muted"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id print("Default icon/text - title and default text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, title='Test title') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title="Test title"><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id print("Default icon/text - title without text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text=None, title='Test title') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title="Test title"><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id print("Default icon/text - not title and default text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='Test') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title=""><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span>Test</span></div>''' % elt.id print("Default icon/text - not title and text") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='Test text') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title=""><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span>Test text</span></div>''' % elt.id print("Default icon/text - extra") item_state = items_states.get_html_state(save_object_type, elt, icon=True, text='', extra='test') print(item_state) assert item_state == \ '''<div class="item-state item_user " style="display: inline; font-size:0.9em;" data-item-id="%s" data-item-name="anonymous" data-item-type="user" data-item-state="" title="testtest"><span class="fa-stack " ><i class="fa fa-circle fa-stack-2x item_user"></i><i class="fa fa-user fa-stack-1x fa-inverse"></i></span><span></span></div>''' % elt.id
def test_items_states_2(self): """ Items - states (2) """ items_states = ElementState() assert items_states.object_types_states assert items_states.default_states assert items_states.states print("Objects types and states", items_states.object_types_states) print("Default states", items_states.default_states) print("Items states", items_states.states) assert items_states.get_objects_types() print("All objects types : ", items_states.get_objects_types()) assert items_states.get_icon_states() print("All objects : ", items_states.get_icon_states()) assert items_states.get_default_states() print("Default states : ", items_states.get_default_states()) # Objects known states for object_type in items_states.object_types_states: assert items_states.get_icon_states(object_type) print(object_type, ", all states: ", items_states.get_icon_states(object_type)) for state in items_states.get_icon_states(object_type): assert items_states.get_icon_state(object_type, state) print(object_type, ", state: ", state, ": ", items_states.get_icon_state( object_type, state)) assert not items_states.get_icon_state(None, None) # Default states are in all objects types for state in items_states.get_default_states(): print("Default state: ", state) for object_type in items_states.object_types_states: assert items_states.get_icon_states(object_type)
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 })