예제 #1
0
    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'))
예제 #2
0
    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