Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WiP: Alignak specific stuff #681

Open
wants to merge 31 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
35cb117
Update test configuration
mohierf Dec 16, 2018
1eab371
Manage Alignak arbiter in the main module - get status thread
mohierf Dec 16, 2018
b397a21
Display Alignak parameters - schedulers configuration
mohierf Dec 16, 2018
f4c4115
Alignak MongoDB logs
mohierf Dec 16, 2018
a594e7c
Alignak system menu with the live state and the events log
mohierf Dec 16, 2018
fe47d22
Alignak statistics - first version
mohierf Dec 17, 2018
ddcfa28
Closes #676 - Contacts list with icon
mohierf Dec 13, 2018
eb8ca94
Fix hostgroups filtering behaviour
mohierf Dec 18, 2018
9b0dc47
Revert some of 1435bdb about comment tab
Dec 18, 2018
445c31d
Closes #696 - fix and improve broken parameters view
mohierf Dec 21, 2018
7aeabc9
Helper functions to render notes and actions
mohierf Dec 19, 2018
cfcd48d
Closes #677 - render notes and actions in the element view
mohierf Dec 20, 2018
0ebc860
Closes #677 - render notes and actions in the problems view
mohierf Dec 20, 2018
c8f7c77
Fix a CSS media query for width around 992px
mohierf Jan 2, 2019
c20d924
Revert "Closes #677 - render notes and actions in the problems view"
Jan 2, 2019
a1bf880
Revert "Closes #677 - render notes and actions in the element view"
Jan 2, 2019
80e58c5
Revert "Helper functions to render notes and actions"
Jan 2, 2019
205edf7
Debug notes_url display in cv_hosts
Jan 2, 2019
0a614a6
Closes #677 - render notes and actions in the element view
mohierf Dec 20, 2018
a6081ca
Helper functions to render notes and actions
mohierf Dec 19, 2018
2d197ff
Closes #699 - enhance plain text search engine
mohierf Dec 21, 2018
8aadced
Improve hovering title (Aka) for host name if host has a display_name
mohierf Dec 28, 2018
e1fbefa
Load shinken-action.js only once!
mohierf Dec 30, 2018
fdcd2eb
Improve Alignak parameters view
mohierf Dec 31, 2018
799b25e
Improve host custom view
mohierf Dec 31, 2018
eae5408
Clean element view and update test configuration
mohierf Dec 31, 2018
292e22b
Alert if user and BIs are not consistent (log + user preference message)
mohierf Dec 18, 2018
aedbfda
Manage BI filter in the search query parameter
mohierf Dec 19, 2018
9e1c187
BI cleaning - review comments
mohierf Dec 31, 2018
48c3e0f
Add a duration check criteria: last_check
mohierf Jan 1, 2019
6c4a73e
Clean the anonymous user mode and the currently view
mohierf Jan 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions etc/alignak.d/alignak-module-webui.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ python_name=alignak_webui
;log_level=INFO
# Set log_color=1 to have a (colored) log on the console
;log_console=0
# Declare the log file for the Shinken Web UI log (default is /var/log/alignak/shinken-webui.log)
;log_file=/var/log/alignak/shinken-webui.log
# Declare the log file for the Shinken Web UI log (default is /var/log/alignak/alignak-webui.log)
; If the configured and/or default log file is not allowed, the UI will log to /tmp/alignak-webui.log
;log_file=/var/log/alignak/alignak-webui.log

# Export module metrics to a statsd server.
# By default at localhost:8125 (UDP) with the alignak prefix
Expand All @@ -26,6 +27,18 @@ python_name=alignak_webui
# Default is not enabled
;statsd_enabled=0

## Alignak configuration
# Define the Alignak arbiter API endppont
;alignak_endpoint = http://127.0.0.1:7770

# The webUI will get the Alignak livestate every alignak_check_period seconds
;alignak_check_period = 10

# The WebUI will store internally an events log queue limited to alignak_events_count items
# If ALIGNAK_EVENTS_LOG_COUNT environment variable is set it will take precedence
;alignak_events_count = 1000


## Modules for WebUI
## User authentication:
# - auth-cfg-password (internal) : Use the password set in Shinken contact for auth.
Expand Down Expand Up @@ -80,8 +93,39 @@ python_name=alignak_webui
;username=
;password=

# Logs collection from a MongoDB database
# ---
# Logs collection name
# -- For Shinken mongo-logs module logs
;logs_collection=logs
# -- For Alignak logstash parser
logs_collection=alignak_events
# -- For Alignak backend module
;logs_collection=history

# Configure the date format for date range searching
# -- For Shinken mongo-logs module logs (default configuration)
;plugin.logs.date_format=timestamp
# -- For Alignak logstash parser, usual datetime
plugin.logs.date_format=datetime
# -- For Alignak backend module, usual datetime
;plugin.logs.date_format=datetime

# Configure the name of the collected and displayed fields
# -- For Shinken mongo-logs module logs (default configuration)
;plugin.logs.time_field=times
;plugin.logs.other_fields=message
;plugin.logs.types='INFO', 'WARNING', 'ERROR'

# -- For Alignak logstash parser
plugin.logs.time_field=@timestamp
plugin.logs.other_fields=alignak.event,alignak.host_name,alignak.service,alignak.state,alignak.state_type,alignak.message
plugin.logs.types=

# -- For Alignak backend module
;plugin.logs.time_field=_created
;plugin.logs.other_fields=type,host_name,service_name,user_name,message
;plugin.logs.types=

# Hosts availability collection name
;hav_collection=availability
Expand Down
110 changes: 55 additions & 55 deletions module/datamanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@
from shinken.objects.command import Command, Commands
from shinken.misc.sorter import worse_first, last_state_change_earlier

# Search patterns like: isnot:0 isnot:ack isnot:"downtime fred" name "vm fred"
SEARCH_QUERY_PATTERNS = r'''
# 1/ Search a key:value pattern.
(?P<key>\w+): # Key consists of only a word followed by a colon
(?P<quote2>["']?) # Optional quote character.
(?P<value>.*?) # Value is a non greedy match
(?P=quote2) # Closing quote equals the first.
($|\s) # Entry ends with whitespace or end of string
| # OR
# 2/ Search a single string quoted or not
(?P<quote>["']?) # Optional quote character.
(?P<name>.*?) # Name is a non greedy match
(?P=quote) # Closing quote equals the opening one.
($|\s) # Entry ends with whitespace or end of string
'''


class WebUIDataManager(DataManager):

Expand Down Expand Up @@ -363,31 +379,10 @@ def search_hosts_and_services(self, search, user, get_impacts=True, sorter=None,
items.extend(self._only_related_to(super(WebUIDataManager, self).get_hosts(), user))
items.extend(self._only_related_to(super(WebUIDataManager, self).get_services(), user))

# Filter items according to the logged-in user minimum business impact or the minimum business impact
business_impact = max(user.min_business_impact, self.problems_business_impact)
logger.debug("[WebUI - datamanager] business impact, filtering %d items >= %d (user: %d, ui: %d)",
len(items), business_impact, user.min_business_impact, self.problems_business_impact)
items = [i for i in items if i.business_impact >= business_impact]

logger.debug("[WebUI - datamanager] search_hosts_and_services, search for %s in %d items", search, len(items))

# Search patterns like: isnot:0 isnot:ack isnot:"downtime fred" name "vm fred"
regex = re.compile(
r'''
# 1/ Search a key:value pattern.
(?P<key>\w+): # Key consists of only a word followed by a colon
(?P<quote2>["']?) # Optional quote character.
(?P<value>.*?) # Value is a non greedy match
(?P=quote2) # Closing quote equals the first.
($|\s) # Entry ends with whitespace or end of string
| # OR
# 2/ Search a single string quoted or not
(?P<quote>["']?) # Optional quote character.
(?P<name>.*?) # Name is a non greedy match
(?P=quote) # Closing quote equals the opening one.
($|\s) # Entry ends with whitespace or end of string
''',
re.VERBOSE)
regex = re.compile(SEARCH_QUERY_PATTERNS, re.VERBOSE)

# Replace "NOT foo" by "^((?!foo).)*$" to ignore foo
search = re.sub(r'NOT ([^\ ]*)', r'^((?!\1).)*$', search)
Expand All @@ -409,21 +404,23 @@ def search_hosts_and_services(self, search, user, get_impacts=True, sorter=None,
# Case insensitive
pat = re.compile(s, re.IGNORECASE)
new_items = []
# Ordered search in all the items for: displa_name, alias, name and notes
for i in items:
if (pat.search(i.get_full_name())
or (i.__class__.my_type == 'host' and i.alias and pat.search(i.alias))):
if (pat.search(getattr(i, 'display_name', '')) or pat.search(getattr(i, 'alias', ''))
or pat.search(i.get_full_name()) or pat.search(getattr(i, 'notes', ''))):
new_items.append(i)
else:
for j in i.impacts + i.source_problems:
if (pat.search(j.get_full_name())
or (j.__class__.my_type == 'host' and j.alias and pat.search(j.alias))):
new_items.append(i)

# Nothing found in all the items
if not new_items:
for i in items:
# Search in the last check output
if pat.search(i.output):
new_items.append(i)
else:

if not new_items:
# Nothing found in the checks output
for i in items:
# Search in the impacts and source problems last check output
for j in i.impacts + i.source_problems:
if pat.search(j.output):
new_items.append(i)
Expand Down Expand Up @@ -478,34 +475,34 @@ def search_hosts_and_services(self, search, user, get_impacts=True, sorter=None,
if (t in ['hg', 'hgroup', 'hostgroup']) and s.lower() != 'all':
logger.debug("[WebUI - datamanager] searching for items in the hostgroup %s", s)
group = self.get_hostgroup(s)
if not group:
return []
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())

items = [i for i in items if i in group.members]
if group:
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())
# This filters items that are related with the hostgroup only
# if the item has an hostgroups property
items = [i for i in items if getattr(i, 'get_hostgroups') and
group.get_name() in [g.get_name() for g in i.get_hostgroups()]]

if (t in ['sg', 'sgroup', 'servicegroup']) and s.lower() != 'all':
logger.info("[WebUI - datamanager] searching for items in the servicegroup %s", s)
logger.debug("[WebUI - datamanager] searching for items in the servicegroup %s", s)
group = self.get_servicegroup(s)
if not group:
return []
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())

items = [i for i in items if i in group.members]
# items = [i for i in items if i.__class__.my_type == 'service'
if group:
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())
# Only the items that have a servicegroups property
items = [i for i in items if getattr(i, 'servicegroups') and
group.get_name() in [g.get_name() for g in i.servicegroups]]

# @mohierf: to be refactored!
if (t in ['cg', 'cgroup', 'contactgroup']) and s.lower() != 'all':
logger.info("[WebUI - datamanager] searching for items related with the contactgroup %s", s)
logger.debug("[WebUI - datamanager] searching for items related with the contactgroup %s", s)
group = self.get_contactgroup(s, user)
if not group:
return []
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())
if group:
logger.debug("[WebUI - datamanager] found the group: %s", group.get_name())

contacts = [c for c in self.get_contacts(user=user) if c in group.members]
items = list(set(itertools.chain(*[self._only_related_to(items,
self.rg.contacts.find_by_name(c))
for c in contacts])))
contacts = [c for c in self.get_contacts(user=user) if c in group.members]
logger.info("[WebUI - datamanager] contacts: %s", contacts)

items = list(set(itertools.chain(*[self._only_related_to(items,
self.rg.contacts.find_by_name(c))
for c in contacts])))

if t == 'realm':
r = self.get_realm(s)
Expand All @@ -514,10 +511,10 @@ def search_hosts_and_services(self, search, user, get_impacts=True, sorter=None,
items = [i for i in items if i.get_realm() == r]

if t == 'htag' and s.lower() != 'all':
items = [i for i in items if s in i.get_host_tags()]
items = [i for i in items if getattr(i, 'get_host_tags') and s in i.get_host_tags()]

if t == 'stag' and s.lower() != 'all':
items = [i for i in items if i.__class__.my_type == 'service' and s in i.get_service_tags()]
items = [i for i in items if getattr(i, 'get_service_tags') and s in i.get_service_tags()]

if t == 'ctag' and s.lower() != 'all':
contacts = [c for c in self.get_contacts(user=user) if s in c.tags]
Expand Down Expand Up @@ -546,9 +543,12 @@ def search_hosts_and_services(self, search, user, get_impacts=True, sorter=None,
except ValueError:
items = []

if t == 'duration':
if t in ['duration', 'last_check']:
seconds_per_unit = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800}
times = [(i, time.time() - int(i.last_state_change)) for i in items]
if t == 'duration':
times = [(i, time.time() - int(i.last_state_change)) for i in items]
else:
times = [(i, time.time() - int(i.last_chk)) for i in items]
try:
if s.startswith('>='):
s = int(s[2:-1]) * seconds_per_unit[s[-1].lower()]
Expand Down
Loading