def __init__(self, configs, hosts, services, contacts, hostgroups, servicegroups, contactgroups, timeperiods, commands, schedulers, pollers, reactionners, brokers, dbconn, pnp_path, return_queue, counters): # Runtime data form the global Thrift object print "ThriftQuery.__init__()" self.configs = configs self.hosts = hosts self.services = services self.contacts = contacts self.hostgroups = hostgroups self.servicegroups = servicegroups self.contactgroups = contactgroups self.timeperiods = timeperiods self.commands = commands self.schedulers = schedulers self.pollers = pollers self.reactionners = reactionners self.brokers = brokers self.dbconn = dbconn self.pnp_path = pnp_path self.return_queue = return_queue self.counters = counters # Private attributes for this specific request self.response = ThriftResponse(responseheader = 'off', outputformat = 'csv', keepalive = 'off', columnheaders = 'undef', separators = ThriftResponse.separators) self.table = None self.columns = [] self.filtercolumns = [] self.prefiltercolumns = [] self.stats_group_by = [] self.stats_columns = [] self.aliases = [] self.limit = None self.extcmd = False self.out_map = self.copy_out_map_hooks() # Initialize the stacks which are needed for the Filter: and Stats: # filter- and count-operations self.filter_stack = LiveStatusStack() self.sql_filter_stack = LiveStatusStack() self.sql_filter_stack.type = 'sql' self.stats_filter_stack = LiveStatusStack() self.stats_postprocess_stack = LiveStatusStack() self.stats_request = False # When was this query launched? self.tic = time.time() # Clients can also send their local time with the request self.client_localtime = self.tic
class ThriftQuery(Hooker): my_type = 'query' def __init__(self, configs, hosts, services, contacts, hostgroups, servicegroups, contactgroups, timeperiods, commands, schedulers, pollers, reactionners, brokers, dbconn, pnp_path, return_queue, counters): # Runtime data form the global Thrift object print "ThriftQuery.__init__()" self.configs = configs self.hosts = hosts self.services = services self.contacts = contacts self.hostgroups = hostgroups self.servicegroups = servicegroups self.contactgroups = contactgroups self.timeperiods = timeperiods self.commands = commands self.schedulers = schedulers self.pollers = pollers self.reactionners = reactionners self.brokers = brokers self.dbconn = dbconn self.pnp_path = pnp_path self.return_queue = return_queue self.counters = counters # Private attributes for this specific request self.response = ThriftResponse(responseheader = 'off', outputformat = 'csv', keepalive = 'off', columnheaders = 'undef', separators = ThriftResponse.separators) self.table = None self.columns = [] self.filtercolumns = [] self.prefiltercolumns = [] self.stats_group_by = [] self.stats_columns = [] self.aliases = [] self.limit = None self.extcmd = False self.out_map = self.copy_out_map_hooks() # Initialize the stacks which are needed for the Filter: and Stats: # filter- and count-operations self.filter_stack = LiveStatusStack() self.sql_filter_stack = LiveStatusStack() self.sql_filter_stack.type = 'sql' self.stats_filter_stack = LiveStatusStack() self.stats_postprocess_stack = LiveStatusStack() self.stats_request = False # When was this query launched? self.tic = time.time() # Clients can also send their local time with the request self.client_localtime = self.tic def find_converter(self, attribute): """Return a function that converts textual numbers in the request to the correct data type""" out_map = LSout_map[self.out_map_name] if attribute in out_map and 'type' in out_map[attribute]: if out_map[attribute]['type'] == 'int': return int elif out_map[attribute]['type'] == 'float': return float return None def set_default_out_map_name(self): """Translate the table name to the corresponding out_map key.""" try: self.out_map_name = { 'hosts' : 'Host', 'services' : 'Service', 'hostgroups' : 'Hostgroup', 'servicegroups' : 'Servicegroup', 'contacts' : 'Contact', 'contactgroups' : 'Contactgroup', 'comments' : 'Comment', 'downtimes' : 'Downtime', 'commands' : 'Command', 'timeperiods' : 'Timeperiod', 'hostsbygroup' : 'Hostsbygroup', 'servicesbygroup' : 'Servicesbygroup', 'servicesbyhostgroup' : 'Servicesbyhostgroup', 'status' : 'Config', 'log' : 'Logline', 'schedulers' : 'SchedulerLink', 'pollers' : 'PollerLink', 'reactionners' : 'ReactionnerLink', 'brokers' : 'BrokerLink', 'problems' : 'Problem', 'columns' : 'Config', # just a dummy }[self.table] except: self.out_map_name = 'hosts' def copy_out_map_hooks(self): """Update the hooks for some out_map entries. Thrift columns which have a fulldepythonize postprocessor need an updated argument list. The third argument needs to be the request object. (When the out_map is first supplied with hooks, the third argument is the Thrift object.) """ new_map = {} for objtype in LSout_map: new_map[objtype] = {} for attribute in LSout_map[objtype]: new_map[objtype][attribute] = {} entry = LSout_map[objtype][attribute] if 'hooktype' in entry: if 'prop' not in entry or entry['prop'] is None: prop = attribute else: prop = entry['prop'] if 'default' in entry: default = entry['default'] else: if entry['type'] == 'int' or entry['type'] == 'float': default = 0 else: default = '' func = entry['fulldepythonize'] new_map[objtype][attribute]['hook'] = self.make_hook('get_prop_full_depythonize', prop, default, func, None) else: new_map[objtype][attribute]['hook'] = entry['hook'] return new_map def __str__(self): output = "ThriftRequest:\n" for attr in ["table", "columns", "filtercolumns", "prefiltercolumns", "aliases", "stats_group_by", "stats_request"]: output += "request %s: %s\n" % (attr, getattr(self, attr)) return output def split_command(self, line, splits=1): """Create a list from the words of a line""" return line.split(' ', splits) def split_option(self, line, splits=1): """Like split_commands, but converts numbers to int data type""" #x = [int(i) if i.isdigit() else i for i in [token.strip() for token in re.split(r"[\s]+", line, splits)]] x = map (lambda i: (i.isdigit() and int(i)) or i, [token.strip() for token in re.split(r"[\s]+", line, splits)]) return x def split_option_with_columns(self, line): """Split a line in a command and a list of words""" cmd, columns = self.split_option(line) return cmd, [self.strip_table_from_column(c) for c in re.compile(r'\s+').split(columns)] def strip_table_from_column(self, column): """Cut off the table name, because it is possible to say service_state instead of state""" bygroupmatch = re.compile('(\w+)by.*group').search(self.table) if bygroupmatch: return re.sub(re.sub('s$', '', bygroupmatch.group(1)) + '_', '', column, 1) else: return re.sub(re.sub('s$', '', self.table) + '_', '', column, 1) def launch_query(self): """ Prepare the request object's filter stacks """ print "launch_query" # A minimal integrity check if not self.table: return [] # Make columns unique self.filtercolumns = list(set(self.filtercolumns)) self.prefiltercolumns = list(set(self.prefiltercolumns)) self.stats_columns = list(set(self.stats_columns)) if self.stats_request: if len(self.columns) > 0: # StatsGroupBy is deprecated. Columns: can be used instead self.stats_group_by = self.columns elif len(self.stats_group_by) > 0: self.columns = self.stats_group_by + self.stats_columns #if len(self.stats_columns) > 0 and len(self.columns) == 0: if len(self.stats_columns) > 0: self.columns = self.stats_columns + self.columns # Make one big filter where the single filters are anded self.filter_stack.and_elements(self.filter_stack.qsize()) try: # Remember the number of stats filters. We need these numbers as columns later. # But we need to ask now, because get_live_data() will empty the stack num_stats_filters = self.stats_filter_stack.qsize() if self.table == 'log': self.sql_filter_stack.and_elements(self.sql_filter_stack.qsize()) result = self.get_live_data_log() else: # If the pnpgraph_present column is involved, then check # with each request if the pnp perfdata path exists if 'pnpgraph_present' in self.columns + self.filtercolumns + self.prefiltercolumns and self.pnp_path and os.access(self.pnp_path, os.R_OK): self.pnp_path_readable = True else: self.pnp_path_readable = False # Apply the filters on the broker's host/service/etc elements result = self.get_live_data() if self.stats_request: self.columns = range(num_stats_filters) if self.stats_group_by: self.columns = tuple(list(self.stats_group_by) + list(self.columns)) if len(self.aliases) == 0: #If there were Stats: staments without "as", show no column headers at all self.response.columnheaders = 'off' else: self.response.columnheaders = 'on' except Exception, e: import traceback print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" print e traceback.print_exc(32) print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" result = [] return result