nginx-amplify-agent/amplify/ext/phpfpm/collectors/master/meta.py

127 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
from amplify.agent.common.context import context
from amplify.agent.data.eventd import INFO
from amplify.agent.collectors.abstract import AbstractMetaCollector
from amplify.agent.common.util import subp, host
from amplify.ext.phpfpm.util.ps import LS_CMD, LS_CMD_FREEBSD, LS_PARSER
from amplify.ext.phpfpm.util.version import VERSION_PARSER
__author__ = "Grant Hulegaard"
__copyright__ = "Copyright (C) Nginx, Inc. All rights reserved."
__license__ = ""
__maintainer__ = "Grant Hulegaard"
__email__ = "grant.hulegaard@nginx.com"
class PHPFPMMetaCollector(AbstractMetaCollector):
"""
Meta collector. Collects meta data about master
"""
short_name = 'phpfpm_meta'
def __init__(self, **kwargs):
super(PHPFPMMetaCollector, self).__init__(**kwargs)
self._bin_path = None # cache for bin_path discovery
self._version = None # cache for version discovery
self._version_line = None # "" "" ""
self.register(
self.bin_path,
self.version
)
@property
def default_meta(self):
meta = {
'type': self.object.type,
'root_uuid': context.uuid,
'local_id': self.object.local_id,
'name': self.object.name,
'display_name': self.object.display_name,
'cmd': self.object.cmd,
'conf_path': self.object.conf_path,
'workers': len(self.object.workers),
'bin_path': None,
'version': None,
'version_line': None,
}
if not self.in_container:
meta['pid'] = self.object.pid
return meta
def bin_path(self):
"""
Compute the bin_path as part of meta collection to be more tolerant of
users that utilize `pm.ondemand`. bin_path is also not required for
our regular running logic so it can safely be moved down a level (to
this collector that runs on a regular async basis).
This used to live in manager._find_all() but it is impossible to cache
the value there.
"""
# only compute if bin_path hasn't been found before
if self._bin_path is None:
all_pids = [self.object.pid] + self.object.workers
last_exception = None
for pid in all_pids:
ls_cmd_template = LS_CMD_FREEBSD if host.linux_name() == 'freebsd' else LS_CMD
ls_cmd = ls_cmd_template % pid
try:
ls, _ = subp.call(ls_cmd)
context.log.debug('ls "%s" output: %s' % (ls_cmd, ls))
except Exception as e:
last_exception = e
else:
try:
self._bin_path = LS_PARSER(ls[0])
except Exception as e:
exc_name = e.__class__.__name__
context.log.debug(
'failed to parse ls result "%s" due to %s' %
(ls[0], exc_name)
)
context.log.debug('additional info:', exc_info=True)
last_exception = None # clear last exception for ls
break
# if we never succeeded...log error
if last_exception:
exc_name = last_exception.__class__.__name__
# this is being kept as an error because it has
# implications for meta collection success/failure
context.log.debug(
'failed to find php-fpm bin path, last attempt: '
'"%s" failed due to %s' %
(ls_cmd, exc_name)
)
context.log.debug('additional info:', exc_info=True)
# If there is a root_object defined, send an event to the cloud
if context.objects.root_object:
context.objects.root_object.eventd.event(
level=INFO,
message='php-fpm bin not found'
)
self.meta['bin_path'] = self._bin_path
def version(self):
# only compute if version hasn't been found before and we have found a
# bin_path
if self._version is None and self._bin_path is not None:
version, raw_line = VERSION_PARSER(self._bin_path)
self._version, self._version_line = version, raw_line
self.meta['version'] = self._version
self.meta['version_line'] = self._version_line