def test_ps_master_parser(self): ps, _ = subp.call(PS_CMD) assert_that(ps, not_none()) parsed_lines = [PS_PARSER(line) for line in ps] assert_that(parsed_lines, not_none()) assert_that(parsed_lines, has_length(6)) master_pid, master_ppid, master_command = parsed_lines[0] parsed_master = MASTER_PARSER(master_command) assert_that(parsed_master, not_none()) assert_that(parsed_master, equal_to('/etc/php5/fpm/php-fpm.conf'))
def _find_all(ps=None): """ Tries to find a master process :param ps: List of Strings...used for debugging our parsing logic... should be None most of the time :return: List of Dicts phpfpm object definitions """ # get ps info try: # set ps output to passed param or call subp ps, _ = (ps, None) if ps is not None else subp.call(PS_CMD) context.log.debug('ps php-fpm output: %s' % ps) except Exception as e: # log error exception_name = e.__class__.__name__ context.log.debug( 'failed to find running php-fpm via "%s" due to %s' % (PS_CMD, exception_name)) context.log.debug('additional info:', exc_info=True) # If there is a root_object defined, log an event to send to the # cloud. if context.objects.root_object: context.objects.root_object.eventd.event( level=INFO, message='no php-fpm found') # break processing returning a fault-tolerant empty list return [] if not any('master process' in line for line in ps): context.log.info('no php-fpm masters found') # break processing returning a fault-tolerant empty list return [] # collect all info about processes masters = {} try: for line in ps: parsed = PS_PARSER(line) # if not parsed - go to the next line if parsed is None: continue pid, ppid, cmd = parsed # unpack values # match master process if 'master process' in cmd: # if ppid isn't 1, then the master process must have been # started with a launcher if ppid != 1: out, err = subp.call('ps o command %d' % ppid) # take the second line because the first is a header parent_command = out[1] context.log.debug( 'launching php-fpm with "%s" is not currently ' 'supported' % parent_command) continue try: conf_path = MASTER_PARSER(cmd) except: context.log.error('failed to find conf_path for %s' % cmd) context.log.debug('additional info:', exc_info=True) else: # calculate local_id local_id = hashlib.sha256( '%s_%s' % (cmd, conf_path)).hexdigest() if pid not in masters: masters[pid] = {'workers': []} masters[pid].update({ 'cmd': cmd.strip(), 'conf_path': conf_path, 'pid': pid, 'local_id': local_id }) # match pool process elif 'pool' in cmd: if ppid in masters: masters[ppid]['workers'].append(pid) else: masters[ppid] = dict(workers=[pid]) except Exception as e: # log error exception_name = e.__class__.__name__ context.log.error('failed to parse ps results due to %s' % exception_name) context.log.debug('additional info:', exc_info=True) # format results results = [] for payload in masters.itervalues(): # only add payloads that have all the keys if 'cmd' in payload and \ 'conf_path' in payload and \ 'pid' in payload and \ 'local_id' in payload and \ 'workers' in payload: results.append(payload) else: context.log.debug( 'phpfpm master "_find_all()" found an incomplete entity %s' % payload) return results