Mini Shell

Direktori : /opt/imh-python/lib/python3.9/site-packages/ngxconf/
Upload File :
Current File : //opt/imh-python/lib/python3.9/site-packages/ngxconf/control.py

# vim: set ts=4 sw=4 expandtab syntax=python:
"""

ngxconf.control
Process Control

Copyright (c) 2018-2020 InMotion Hosting, Inc.
http://www.inmotionhosting.com/

@author J. Hipps <jacobh@inmotionhosting.com>

"""

import re
import sys
import os
import time
import subprocess
import logging
import logging.handlers
import json
from glob import glob
from argparse import ArgumentParser, Action
from signal import SIGHUP, SIGUSR1, SIGUSR2

import yaml
from yaml import CLoader

from ngxconf import builder
from ngxconf.util import gconf, cancel_cp_pending_tasks
from ngxconf import __version__, __date__, gconf_defaults

__all__ = ['check_nginx', 'reload_nginx', 'rebuild_phpfpm', 'cp_rebuild_httpd_conf',
           'rebuild_phpfpm_list', 'reload_phpfpm', 'restart_phpfpm']

logger = logging.getLogger('ngxconf')


def check_nginx(nginx_path="/sbin/nginx", failfile="/var/run/nginx.fail"):
    """
    Perform an Nginx configuration check (`nginx -t`)
    """
    logger.info("Validating Nginx configuration...")
    try:
        ngxtest = subprocess.Popen([nginx_path, '-t'], stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='UTF-8')
        serr = ngxtest.communicate()[1]
        retval = ngxtest.returncode
    except Exception as e:
        logger.error("Failed to execute Nginx configuration test: %s", str(e))
        return False

    if retval != 0:
        logger.error("Nginx config validation failed (return code %d):\n%s", retval, serr)
        try:
            with open(failfile, 'w') as f:
                f.write(serr)
            logger.warning("Triggered failfile: %s", failfile)
        except Exception as e:
            logger.error("Failed to write failfile: %s", str(e))
        return False
    else:
        # Ensure failfile does not exist
        logger.info("Nginx config validated successfully")
        try:
            os.unlink(failfile)
        except:
            pass
    return True

def reload_nginx(pidfile="/var/run/nginx.pid"):
    """
    Reloads the Nginx master process
    """
    logger.info("Triggering Nginx config reload...")
    try:
        with open(pidfile, 'r') as f:
            ngxpid = int(f.read().strip())
    except Exception as e:
        logger.error("Failed to open %s; could not determine Nginx PID: %s", pidfile, str(e))
        return False

    try:
        os.kill(ngxpid, SIGHUP)
        logger.info("Sent SIGHUP to Nginx master process (%d)", ngxpid)
        return True
    except Exception as e:
        logger.error("Failed to send SIGHUP signal to Nginx master (%d): %s", ngxpid, str(e))
        return False

def rebuild_phpfpm(script_path="/scripts/php_fpm_config"):
    """
    Full rebuild of PHP-FPM configuration via (modified) cPanel utility
    """
    cancel_cp_pending_tasks('rebuild_fpm')

    # Perform full rebuild
    logger.info("Triggering full PHP-FPM config rebuild...")
    try:
        fprel = subprocess.Popen([script_path, '--rebuild'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        fprel.wait()
        fprel.communicate()
        retval = fprel.returncode
    except Exception as e:
        logger.error("Failed to execute %s: %s", script_path, str(e))
        return False

    if retval == 0:
        logger.info("PHP-FPM config rebuilt")
    else:
        logger.warning("PHP-FPM builder exited uncleanly (%d)", retval)

    return True

def reload_phpfpm():
    """
    Reload all PHP-FPM masters gracefully
    """
    fpms_reloaded = 0
    for fmaster in glob('/opt/cpanel/*/root/usr/var/run/php-fpm/php-fpm.pid'):
        try:
            with open(fmaster, 'r') as f:
                fpid = int(f.read().strip())
        except:
            logger.error("Failed to read PID file from %s", fmaster)
            continue

        try:
            tphp = re.search('(ea-php[0-9]{2})', fmaster, re.I).group(1)
        except:
            tphp = 'ea-php'

        try:
            os.kill(fpid, SIGUSR2)
            logger.info("Sent SIGUSR2 to PHP-FPM master process for %s (%d)", tphp, fpid)
            fpms_reloaded += 1
        except Exception as e:
            logger.error("Failed to reload PHP-FPM master for %s (%d): %s", tphp, fpid, str(e))
            continue

    if fpms_reloaded == 0:
        logger.warning("No FPM master PID files detected. PHP-FPM masters were NOT reloaded!")
        return False
    else:
        logger.debug("%d FPM masters were reloaded OK", fpms_reloaded)
    return True

def restart_phpfpm():
    """
    Terminate and restart all PHP-FPM masters
    """
    try:
        fprel = subprocess.Popen(['/scripts/restartsrv_apache_php_fpm'],
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        fprel.wait()
        fprel.communicate()
        retval = fprel.returncode
    except Exception as e:
        logger.error("Failed to restart PHP-FPM: %s", str(e))
        return False

    if retval == 0:
        logger.info("PHP-FPM restarted successfully")
    else:
        logger.warning("PHP-FPM restart returned non-zero exit code (%d)", retval)

    return True

def cp_update_userdata_cache(user=None, force=False):
    """
    Update cPanel userdata cache
    If @user is specified, only that user is updated
    """
    opts = []
    if user: opts += [user]
    if force: opts += ['--force']

    try:
        udc = subprocess.Popen(['/scripts/updateuserdatacache'] + opts,
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        udc.wait()
        udc.communicate()
        retval = udc.returncode
    except Exception as e:
        logger.error("Failed to execute /scripts/updateuserdatacache: %s", str(e))
        return False

    if retval == 0:
        logger.debug("Userdata cache updated")
        return True
    else:
        logger.warning("Failed to update userdata cache; script returned non-zero exit code (%d)", retval)
        return False

def cp_rebuild_httpd_conf(reload=False):
    """
    Update cPanel HTTPd configuration, optionally reloading
    """
    logger.debug("Queuing rebuildhttpdconf...")
    try:
        udc = subprocess.Popen(['/usr/local/cpanel/bin/servers_queue', 'queue', 'build_apache_conf'],
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        udc.wait()
        udc.communicate()
        retval = udc.returncode
    except Exception as e:
        logger.error("Failed to queue rebuildhttpdconf: %s", str(e))
        return False

    if retval == 0:
        logger.debug("rebuildhttpdconf queued successfully")
    else:
        logger.warning("Failed to queue rebuildhttpdconf; script returned non-zero exit code (%d)", retval)
        return False

    if reload is True:
        logger.debug("Queuing apache_restart restart...")
        try:
            udc = subprocess.Popen(['/usr/local/cpanel/bin/servers_queue', 'queue', 'apache_restart'],
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            udc.wait()
            udc.communicate()
            retval = udc.returncode
        except Exception as e:
            logger.error("Failed to queue apache_restart : %s", str(e))
            return False

        if retval == 0:
            logger.debug("apache_restart queued successfully")
        else:
            logger.warning("Failed to queue apache_restart; script returned non-zero exit code (%d)", retval)
            return False

    return True

Zerion Mini Shell 1.0