????

Your IP : 18.191.237.131


Current Path : /usr/share/cagefs-plugins/
Upload File :
Current File : //usr/share/cagefs-plugins/install-cagefs-plugin.py

#!/opt/cloudlinux/venv/bin/python3 -bb
# -*- coding: utf-8 -*-

# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from future import standard_library
standard_library.install_aliases()
from builtins import *
import argparse
import grp
import os
import pwd
import shutil
import stat
import sys
import subprocess

import cldetectlib as detect
from copy_directory import CopyDirectory
from exec_command import exec_command, exec_command_null_input
from mysql_lib import delete_cagefs_module_plesk
from clcommon.utils import (
    delete_line_from_file,
    write_file_lines,
)
from clcommon.cpapi import admins, DIRECTADMIN_NAME, getCPName, NotSupported
from clcommon.utils import mod_makedirs
from clsudo import Clsudo


# cagefs imports
LIBDIR = '/usr/share/cagefs'
sys.path.append(LIBDIR)
import cagefsctl
import cagefslib
import cagefs_without_lve_lib
import cagefs_universal_hook_lib
from cagefslib import verCompare, add_syslog_socket, remove_syslog_socket
from cagefsreconfigure import litespeed_enableLVE_configure, litespeed_config_write, litespeed_lsphp5_path_change
from cagefsreconfigure import touch, add_mount_to_cagefs_mp, POSTGRES_CONF, POSTGRES_CL7_FOLDER, DEFAULT_POSTGRES_FOLDER


# This line is changed in %build section of securelve.spec
CAGEFS_VERSION = "7.6.18"
# This line is changed in %build section of securelve.spec
CAGEFS_RELEASE = "2.el6.cloudlinux"

SKELETON = '/usr/share/cagefs-skeleton'
SOURCE_PATH = "/usr/share/cagefs-plugins/"
ROOT_PLESK_DIR = "/usr/local/psa/admin/"
ROOT_CPANEL_DIR = "/usr/local/cpanel/whostmgr/docroot/"
ROOT_IWORX_DIR = "/usr/local/interworx/"
ROOT_ISPMGR_DIR = "/usr/local/ispmgr/"
ROOT_DA_DIR = "/usr/local/directadmin/plugins/"
NEED_PLUGIN = "/etc/cagefs/cagefs.plugin.disable"
CPANEL_CRON_PATH = '/etc/cron.d/cagefs_cron'
CPANEL_PHP_SESSIONS_CRON_PATH = '/etc/cron.d/cpanel_php_sessions_cron'
PLESK_CRON_PHP_CLEANER_HOURLY_PATH = '/etc/cron.hourly/clean_user_alt_php_sessions_plesk'
NEW_EXCLUDE_PATH = '/usr/share/cagefs/exclude.d'
EXCLUDE_USERS_CRON_FILE = '/etc/cron.d/exclude_users_cagefs_cron'
CREATE_NAMESPACES_CRON_FILE = '/etc/cron.d/create_namespaces_cagefs_cron'


def manage_cron_file():
    if verCompare(cp.version,'55.9999') < 0:
        create_cron_multiphp()
    else:
        if os.path.isfile(CPANEL_CRON_PATH):
            os.unlink(CPANEL_CRON_PATH)


def update_sudoers(user):
    def exit_with_error(message, status=1):
        sys.stderr.write("%s\n" % (str(message,)))
        sys.exit(status)
    try:
        from clsudo import (
                NoSuchUser,
                UnableToReadFile,
                UnableToWriteFile)
        sudo = Clsudo()
        sudo.add_cagefs_user(user)
    except ImportError:
        exit_with_error("Cannot import Clsudo. Check if python-cllib package installed")
    except (NoSuchUser, UnableToReadFile, UnableToWriteFile) as e:
        exit_with_error(e)


def create_cron_multiphp():
    """
    This func creates cron task which run every 10 minutes
    """
    if not os.path.exists(CPANEL_CRON_PATH):
        f = open(CPANEL_CRON_PATH,'w')
        f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_multiphp.cronlock /usr/share/cagefs/setup_multiphp_integration\n')
        f.close()


def create_cron_cpanel_sessions():
    """
    This func creates cron task which runs every 30 minutes
    to clean php sessions inside cagefs
    """
    if not os.path.exists(CPANEL_PHP_SESSIONS_CRON_PATH):
        f = open(CPANEL_PHP_SESSIONS_CRON_PATH, 'w')
        f.write('*/29 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cleanuserphpsessions.cronlock /usr/share/cagefs/clean_user_php_sessions\n')
        f.close()


def create_exclude_users_cron():
    """
    This func creates cron task which runs every 10 minutes to actualize CageFS exclude users file(s)
    """
    if not os.path.exists(EXCLUDE_USERS_CRON_FILE):
        f = open(EXCLUDE_USERS_CRON_FILE, 'w')
        f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cagefs_exclude_users.cronlock /usr/share/cagefs/exclude_users_cleaner.py\n')
        f.close()


def create_cron_namespaces():
    """
    This func creates cron task that runs every 10 minutes to create namespaces for new users
    """
    if not os.path.exists(CREATE_NAMESPACES_CRON_FILE):
        f = open(CREATE_NAMESPACES_CRON_FILE, 'w')
        f.write('*/10 * * * * root /usr/bin/flock -n /var/run/cloudlinux_cagefs_create_namespaces.cronlock /usr/sbin/cagefsctl --create-namespaces\n')
        f.close()


def shared_mounts_are_found():
    try:
        f = open('/proc/self/mountinfo', 'r')
        found = False
        for line in f:
            if line.find(' shared:') != -1:
                found = True
                break
        f.close()
        return found
    except IOError:
        return False


def fix_shared_mounts(force=False):
    """
    Change shared mounts to private and remount CageFS when shared mounts are found. see CAG-520 for details
    :param force: do not search for shared mounts, make changes unconditionally
    :type force: bool
    """
    if force or shared_mounts_are_found():
        exec_command('/usr/sbin/cagefsctl --unmount-really-all > /dev/null 2>&1')
        if not os.path.isfile('/opt/suphp/sbin/suphp'):
            exec_command('/bin/umount /opt/suphp/sbin > /dev/null 2>&1')
        exec_command('/bin/mount --make-rprivate / > /dev/null 2>&1')
        exec_command('/usr/sbin/cagefsctl --without-lock --remount-all > /dev/null 2>&1')


def install_plugin_web():
    if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0:
        cpdir = CopyDirectory(SOURCE_PATH+"plesk-cagefs", ROOT_PLESK_DIR)
        cpdir.process()
        register_cagefs_plugin()
    elif cp.name == "cPanel":
        cpdir = CopyDirectory(SOURCE_PATH+"cpanel-cagefs/usr/local/cpanel/whostmgr/docroot", ROOT_CPANEL_DIR)
        cpdir.process()
        if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"):
            os.chmod(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi", stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH)
        if verCompare(cp.version, '11.38.1') >= 0:
            if not os.path.isdir("/var/cpanel/apps"):
                mod_makedirs("/var/cpanel/apps", 0o755)
            if verCompare(cp.version, '63.9999') >= 0:
                exec_command("sed -i -e '/^#WHMADDON:cagefs:CageFS/d' "+ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi")
                if verCompare(cp.version, '65.9999') >= 0:
                    shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs-cpanel66.conf', "/var/cpanel/apps/cagefs.conf")
                else:
                    shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs-cpanel64.conf', "/var/cpanel/apps/cagefs.conf")
            else:
                shutil.copyfile(SOURCE_PATH + 'cpanel-cagefs/cagefs.conf', "/var/cpanel/apps/cagefs.conf")
            exec_command("chmod 600 /var/cpanel/apps/cagefs.conf")
            exec_command("/usr/local/cpanel/bin/register_appconfig /var/cpanel/apps/cagefs.conf")
            exec_command("/usr/local/cpanel/etc/init/startcpsrvd")
            manage_cron_file()
    elif cp.name == "InterWorx":
        cpdir = CopyDirectory(SOURCE_PATH+"interworx-cagefs/usr/local/interworx", ROOT_IWORX_DIR)
        cpdir.process()

    elif cp.name == "ISPManager":
        if verCompare(cp.version, "5") == -1:
            # ISP Manager 4
            m_path = "{0}ispmanager-cagefs/usr/local/ispmgr/".format(SOURCE_PATH)
            for name in ["addon", "etc", "skins/sirius"]:
                CopyDirectory("{0}{1}".format(m_path, name), "{0}{1}".format(ROOT_ISPMGR_DIR, name)).process()

            if verCompare(cp.version, "4.4.4") <= 0:
                # for <=4.4.4 version copy mobile skin. for other verions don`t copy
                CopyDirectory("{}skins/mobile".format(m_path), "{}skins/mobile".format(ROOT_ISPMGR_DIR)).process()
            exec_command("/usr/bin/killall ispmgr")

    elif cp.name == "DirectAdmin":
        cpdir = CopyDirectory(SOURCE_PATH+"directadmin-cagefs/usr/local/directadmin/plugins", ROOT_DA_DIR)
        cpdir.process()
        exec_command("chown -R diradmin:diradmin "+ROOT_DA_DIR+"cagefs")
        exec_command("chmod -R 755 "+ROOT_DA_DIR+"cagefs/admin")


def delete_plugin_web():
    # remove installed files
    if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0:
        delete_cagefs_module_plesk()
        if os.path.exists(ROOT_PLESK_DIR+"htdocs/images/modules/plesk-cagefs"):
            shutil.rmtree(ROOT_PLESK_DIR+"htdocs/images/modules/plesk-cagefs")
        if os.path.exists(ROOT_PLESK_DIR+"htdocs/modules/plesk-cagefs"):
            shutil.rmtree(ROOT_PLESK_DIR+"htdocs/modules/plesk-cagefs")
        if os.path.exists(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs"):
            shutil.rmtree(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs")
        if os.path.exists(ROOT_PLESK_DIR+"plib/templates/modules/plesk-cagefs"):
            shutil.rmtree(ROOT_PLESK_DIR+"plib/templates/modules/plesk-cagefs")
    elif cp.name == "cPanel":
        if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"):
            os.remove(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi")
        if os.path.exists(ROOT_CPANEL_DIR+"cgi/cageFS"):
            shutil.rmtree(ROOT_CPANEL_DIR+"cgi/cageFS")
        if os.path.exists(ROOT_CPANEL_DIR+"themes/x/icons/cagefs.gif"):
            os.remove(ROOT_CPANEL_DIR+"themes/x/icons/cagefs.gif")
        if os.path.exists(ROOT_CPANEL_DIR+"images/CageOnly32.png"):
            os.remove(ROOT_CPANEL_DIR+"images/CageOnly32.png")
        if os.path.exists(ROOT_CPANEL_DIR+"images/cagefs-32x32.png"):
            os.remove(ROOT_CPANEL_DIR+"images/cagefs-32x32.png")
        if verCompare(cp.version, '11.38.1') >= 0:
            if (os.path.exists("/var/cpanel/apps/cagefs.conf")):
                exec_command("/usr/local/cpanel/bin/unregister_appconfig /var/cpanel/apps/cagefs.conf")
                os.remove("/var/cpanel/apps/cagefs.conf")
                exec_command("/usr/local/cpanel/etc/init/startcpsrvd")
        if os.path.isfile(CPANEL_CRON_PATH):
            os.unlink(CPANEL_CRON_PATH)
        if os.path.isfile(CPANEL_PHP_SESSIONS_CRON_PATH):
            os.unlink(CPANEL_PHP_SESSIONS_CRON_PATH)
    elif cp.name == "InterWorx":
        if os.path.exists(ROOT_IWORX_DIR+"plugins/cagefs"):
            shutil.rmtree(ROOT_IWORX_DIR+"plugins/cagefs")
        if os.path.exists(ROOT_IWORX_DIR+"html/images/cagefs"):
            shutil.rmtree(ROOT_IWORX_DIR+"html/images/cagefs")
    elif cp.name == "ISPManager":
        if verCompare(cp.version, "5") == -1:
            # ISP Manager 4
            if os.path.exists(ROOT_ISPMGR_DIR+"addon/cagefs"):
                shutil.rmtree(ROOT_ISPMGR_DIR+"addon/cagefs")
            if (os.path.exists("/usr/local/ispmgr/addon/CageFS.php")):
                os.remove("/usr/local/ispmgr/addon/CageFS.php")
            if (os.path.exists("/usr/local/ispmgr/addon/CageFSUser.php")):
                os.remove("/usr/local/ispmgr/addon/CageFSUser.php")
            if (os.path.exists("/usr/local/ispmgr/addon/CageFSUser_get.php")):
                os.remove("/usr/local/ispmgr/addon/CageFSUser_get.php")
            if (os.path.exists("/usr/local/ispmgr/addon/CageFSBackup.php")):
                os.remove("/usr/local/ispmgr/addon/CageFSBackup.php")
            if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefsusers.xml")):
                os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefsusers.xml")
            if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefs.xml")):
                os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefs.xml")
            if (os.path.exists("/usr/local/ispmgr/etc/ispmgr_mod_cagefsbackup.xml")):
                os.remove("/usr/local/ispmgr/etc/ispmgr_mod_cagefsbackup.xml")
            if (os.path.exists("/usr/local/ispmgr/skins/mobile/mb-cagefs.png")):
                os.remove("/usr/local/ispmgr/skins/mobile/mb-cagefs.png")
            if (os.path.exists("/usr/local/ispmgr/skins/mobile/m-cagefs.png")):
                os.remove("/usr/local/ispmgr/skins/mobile/m-cagefs.png")
            if (os.path.exists("/usr/local/ispmgr/skins/mobile/t-CagefsStatus.png")):
                os.remove("/usr/local/ispmgr/skins/mobile/t-CagefsStatus.png")
            if (os.path.exists("/usr/local/ispmgr/skins/sirius/mb-cagefs.png")):
                os.remove("/usr/local/ispmgr/skins/sirius/mb-cagefs.png")
            if (os.path.exists("/usr/local/ispmgr/skins/sirius/m-cagefs.png")):
                os.remove("/usr/local/ispmgr/skins/sirius/m-cagefs.png")
            if (os.path.exists("/usr/local/ispmgr/skins/sirius/t-CagefsStatus.png")):
                os.remove("/usr/local/ispmgr/skins/sirius/t-CagefsStatus.png")
            # Clear ISP Manager's cache and restart it
            shutil.rmtree('/usr/local/ispmgr/var/.xmlcache/ispmgr', True)
            p = subprocess.Popen(['killall', 'ispmgr'], shell=False, stdin=open('/dev/null'),
                                                     stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
            p.wait()
    elif cp.name == "DirectAdmin":
        if os.path.exists(ROOT_DA_DIR+"cagefs"):
            shutil.rmtree(ROOT_DA_DIR+"cagefs")


def install_file(src, dst, perm=0o644):
    base_dir = os.path.dirname(dst)
    if not os.path.isdir(base_dir):
        mod_makedirs(base_dir, 0o755)
    if not os.path.isfile(dst):
        shutil.copyfile(src, dst)
    os.chmod(dst, perm)


def install_native_conf(path):
    install_file(SOURCE_PATH + path, "/etc/cl.selector/native.conf")


def add_read_only_mounts_to_cagefs_mp():
    MOUNTS = cagefsctl.READ_ONLY_MOUNTS
    if os.path.isfile('/etc/cagefs/cagefs.mp'):
        cagefsctl.check_mp_file()
        mp_file = cagefslib.read_file('/etc/cagefs/cagefs.mp')
        comment_added = False
        comment = '# Please add exclamation sign at the beginning of the line if you want to mount path read-only, like below.\n'
        mp_changed = False
        for path in MOUNTS:
            line = '!' + path + '\n'
            if (line not in mp_file) and os.path.isdir(path):
                if (not comment_added) and (comment not in mp_file):
                    mp_file.append(comment)
                    comment_added = True
                mp_file.append(line)
                mp_changed = True
        if mp_changed:
            cagefslib.write_file('/etc/cagefs/cagefs.mp', mp_file)
            touch('/usr/share/cagefs/need.remount')


def switch_php_ini_symlinks_for_users():
    pw = pwd.getpwall()
    for line in pw:
        prefix = str(line.pw_uid)[-2:]
        user = line.pw_name
        path = '/var/cagefs/' + prefix + '/' + user + '/etc/cl.selector/php.ini'
        if os.path.islink(path):
            try:
                linkto = os.readlink(path)
                if linkto == '/usr/selector/php.ini':
                    os.unlink(path)
                    os.symlink('/usr/selector.etc/php.ini', path)
            except OSError as e:
                print('Error:', str(e), file=sys.stderr)


def move_php_ini_to_selector_etc(force = False):
    old_ini_path = '/usr/selector/php.ini'
    new_ini_path = '/usr/selector.etc/php.ini'
    if force or os.path.isfile(SKELETON + old_ini_path):
        new_dir_path = SKELETON + os.path.dirname(new_ini_path)
        if not os.path.isdir(new_dir_path):
            mod_makedirs(new_dir_path, 0o755)
        if os.path.isfile(SKELETON + old_ini_path) and (not os.path.isfile(SKELETON + new_ini_path)):
            exec_command('/bin/cp -p ' + SKELETON + old_ini_path + ' ' + SKELETON + new_ini_path)
        if os.path.isfile(SKELETON + new_ini_path):
            switch_php_ini_symlinks_for_users()
            try:
                os.unlink(SKELETON + old_ini_path)
            except OSError:
                pass


def add_usr_local_easy_mount():
    add_mount_to_cagefs_mp('/usr/local/easy', read_only=True)


def delete_mount_from_cagefs_mp(line):
    path = '/etc/cagefs/cagefs.mp'
    if os.path.isfile(path):
        if delete_line_from_file(path, line):
            touch('/usr/share/cagefs/need.remount')


def setup_ea_php_sessions():
    delete_mount_from_cagefs_mp('/var/cpanel/php/sessions')
    cagefsctl.add_mounts_for_ea_php_sessions()


def detect_min_uid():
    """
    Return UID_MIN setting from /etc/login.defs file as string
    """
    min_uid = None
    try:
        f = open('/etc/login.defs', 'r')
        for line in f:
            if line.startswith('UID_MIN'):
                a = line.split()
                if a and a[0] == 'UID_MIN':
                    min_uid = a[1]
        f.close()
    except (OSError, IOError) as e:
        print('Error while reading UID_MIN from /etc/login.defs file', str(e))
    return min_uid


def set_min_uid(default=500):
    """
    Set min_uid value for CageFS
    """
    if not os.path.isfile('/etc/cagefs/cagefs.min.uid'):
        min_uid = detect_min_uid()
        if min_uid:
            exec_command("/usr/sbin/cagefsctl --set-min-uid="+min_uid)
        else:
            exec_command("/usr/sbin/cagefsctl --set-min-uid="+str(default))


def sync_control_panel_admins():
    """
    Process control panel admins:
      - Add all admins to sudoers
      - Add all admins to /etc/cagefs/exclude/*.admins, which proceesed by hooks
      - Remove 'admin' from /etc/cagefs/exclude/directadminusers
    :return: None
    """
    if getCPName() == DIRECTADMIN_NAME:
        admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "directadmin.admins")
    else:
        admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "panel.admins")
    admin_lines_for_write = list()
    try:
        list_panel_admins = admins()
    except NotSupported:
        # this is ok, just control panel
        # does not implement our API
        return

    for admin_name in list_panel_admins:
        admin_lines_for_write.append(admin_name + '\n')
        Clsudo.add_cagefs_user(admin_name)
    if not admin_lines_for_write:
        # nothing to write, just exit
        return
    write_file_lines(admins_list_file, admin_lines_for_write, 'w')
    os.chmod(admins_list_file, 0o0600)
    # We need to remove 'admin' from /etc/cagefs/exclude/directadminusers because
    # CAG-940 cleaner does not remove it (manually added)
    if getCPName() == DIRECTADMIN_NAME:
        admins_list_file = os.path.join(cagefsctl.EXCLUDE_PATH, "directadminusers")
        delete_line_from_file(admins_list_file, "admin")


def install_plugin():
    """
    Install cagefs plugin on panel
    """
    move_php_ini_to_selector_etc()
    # Add check CageFS exclude users cron
    create_exclude_users_cron()

    # Check for disable etcfs
    if (not os.path.exists("/etc/cagefs/etc.safe/disable.etcfs")):
        if (not os.path.exists("/etc/cagefs/etc.safe")):
            mod_makedirs("/etc/cagefs/etc.safe", 0o751)
        touch("/etc/cagefs/etc.safe/disable.etcfs")
        if (os.path.exists("/usr/share/cagefs-skeleton/bin")):
            exec_command("/usr/sbin/cagefsctl --update-etc")
            touch('/usr/share/cagefs/etc.update.done')
            # execution of "cagefsctl --remount-all" is needed
            touch('/usr/share/cagefs/need.remount')
    # add mail directory if it isn't exists
    if (not os.path.exists("/etc/mail")):
        mod_makedirs("/etc/mail", 0o755)

    # LU-640: check if license file is inside CageFS and mount it into CageFS when needed
    if os.path.exists(SKELETON+'/bin') and os.path.exists(cagefsctl.LICENSE_TIMESTAMP_FILE) and \
            not os.path.exists(SKELETON+'/var/lve/lveinfo.ver.cagefs/lveinfo.ver'):
        touch('/usr/share/cagefs/need.remount')

    add_read_only_mounts_to_cagefs_mp()
    add_mount_to_cagefs_mp('/var/run/nscd', read_only=False)

    # CAG-797: mount NodeJS selector config directory into CageFS
    nodejs_selector_conf_dir = cagefsctl.SELECTOR_CONF_DIR_TEMPLATE.format('nodejs')
    if not os.path.isdir(nodejs_selector_conf_dir):
        mod_makedirs(nodejs_selector_conf_dir, 0o755)
    add_mount_to_cagefs_mp(nodejs_selector_conf_dir, read_only=True)

    # CAG-828: Add python-selector.json to cagefs
    python_selector_conf_dir = cagefsctl.SELECTOR_CONF_DIR_TEMPLATE.format('python')
    if not os.path.isdir(python_selector_conf_dir):
        mod_makedirs(python_selector_conf_dir, 0o755)
    add_mount_to_cagefs_mp(python_selector_conf_dir, read_only=True)

    # CAG-826: fix cagefsctl --enter vulnerability
    delete_mount_from_cagefs_mp('@/root,700')

    # CAG-1007: remove LiteSpeed dir /tmp/lshttpd
    delete_mount_from_cagefs_mp('/tmp/lshttpd')

    # CAG-936: remove unneeded mount point for awstats
    delete_mount_from_cagefs_mp('!/usr/local/awstats/wwwroot/cgi-bin')

    if os.path.isfile(cagefsctl.DEV_SHM_OPTIONS):
        # CAG-954: remove /dev/shm mount from cagefs.mp when isolation of /dev/shm is enabled
        delete_mount_from_cagefs_mp('/dev/shm')
    else:
        # CAG-954: add /dev/shm mount to cagefs.mp when isolation of /dev/shm is disabled
        add_mount_to_cagefs_mp('/dev/shm')

    if os.path.isdir(POSTGRES_CL7_FOLDER) and os.path.isdir(DEFAULT_POSTGRES_FOLDER) and not os.path.isfile(POSTGRES_CONF):
        # if /var/run/postgresql exists and /etc/sysconfig/postgres does not,
        # than we assume, that we are on CL7
        # in such case, /var/run/postgres directory should be empty (not needed),
        # and we try to remove it
        try:
            os.rmdir(DEFAULT_POSTGRES_FOLDER)
            removed = True
        except OSError:
            removed = False
        if removed:
            delete_mount_from_cagefs_mp(DEFAULT_POSTGRES_FOLDER)

    # install cagefs cronjob
    if os.path.isdir("/etc/cron.d") and (not os.path.exists("/etc/cron.d/cp-cagefs-cron")):
        shutil.copyfile(SOURCE_PATH+"plesk-cagefs-cron", "/etc/cron.d/cp-cagefs-cron")
    if os.path.exists("/etc/cron.daily/cagefs.cron"):
        os.remove("/etc/cron.daily/cagefs.cron")

    #install web-face only
    if not os.path.exists(NEED_PLUGIN):
        install_plugin_web()

    # install only. rewrite all existing file
    if cp.name == "Plesk" and verCompare(cp.version, "10") >= 0:
        # remove pam_lve and pam_sulve from /etc/pam.d/su on Plesk
        exec_command("/bin/sed -i '/pam_lve.so/d' /etc/pam.d/su")
        exec_command("/bin/sed -i '/pam_sulve.so/d' /etc/pam.d/su")
        update_sudoers('psaadm')
        if not os.path.exists(NEW_EXCLUDE_PATH):
            mod_makedirs(NEW_EXCLUDE_PATH, 0o750)
        shutil.copyfile(SOURCE_PATH+"plesk-cagefs/pleskuserlist", os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist"))
        os.chmod(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist"), 0o600)
        install_native_conf("plesk-cagefs/plesk.native.conf")
        set_min_uid(10000)
        touch('/etc/cagefs/enable.duplicate.uids')
        # Install alt-php sessions clean cron job
        source = '/usr/share/cagefs/clean_user_alt_php_sessions_plesk'
        print("%s --> %s" % (source, PLESK_CRON_PHP_CLEANER_HOURLY_PATH))
        exec_command("/bin/cp -f %s %s" % (source, PLESK_CRON_PHP_CLEANER_HOURLY_PATH))
    elif cp.name == "cPanel":
        add_usr_local_easy_mount()
        add_mount_to_cagefs_mp('/usr/local/cpanel/var', read_only=False)
        for path in cagefsctl.READ_ONLY_MOUNTS:
            add_mount_to_cagefs_mp(path, read_only=True)
        setup_ea_php_sessions()
        # create symlink /usr/share/cagefs-skeleton/usr/local/cpanel/bin/jailshell -> /bin/bash
        if os.path.exists('/usr/share/cagefs-skeleton/bin/bash'):
            exec_command('ln -fs /bin/bash /usr/share/cagefs-skeleton/usr/local/cpanel/bin/jailshell')

        # update perl modules that are needed for cagefs plugin
        exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller YAML::Syck &> /dev/null &')
        exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller Template::Constants &> /dev/null &')
        exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller XML::Simple &> /dev/null &')
        exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller XML::LibXML &> /dev/null &')
        exec_command_null_input('/usr/bin/nohup /scripts/perlinstaller IO::Scalar &> /dev/null &')

        # install hooks for CPanel
        exec_command("/usr/share/cagefs/cpanel/cpanel-delete-cagefs")
        exec_command("/usr/share/cagefs/cpanel/cpanel-hooks-cagefs")

        # install rearrange-acc hook. works only for 11.54+
        exec_command("/usr/share/cagefs/cpanel/cpanel_hooks_manage.py -i")

        print("Rebuilding Apache's suexec...")
        exec_command("/usr/sbin/cpanel-compile-suexec.sh 500")
        print("Rebuilding suphp...")
        exec_command("/usr/sbin/cpanel-compile-suphp.sh 1")
        if not os.path.exists(NEW_EXCLUDE_PATH):
            mod_makedirs(NEW_EXCLUDE_PATH, 0o750)
        shutil.copyfile(SOURCE_PATH+"cpanel-cagefs/cpaneluserlist", os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist"))
        os.chmod(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist"), 0o600)
        install_native_conf("cpanel-cagefs/cpanel.native.conf")
        install_file(SOURCE_PATH + 'cpanel-cagefs/exclude_mounts.conf', '/etc/container/exclude_mounts.conf')
        set_min_uid()
        if os.path.exists(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi"):
            os.chmod(ROOT_CPANEL_DIR+"cgi/addon_cagefs.cgi", stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH)
        # clean system from old and not used hooks
        if os.path.exists("/usr/share/cagefs-plugins/hooks/cpanel/delete-unused-hooks.sh"):
            exec_command("/usr/share/cagefs-plugins/hooks/cpanel/delete-unused-hooks.sh")

        if os.path.exists("/usr/share/cagefs-plugins/hooks/jail_shell_disable.sh"):
            exec_command("/usr/share/cagefs-plugins/hooks/jail_shell_disable.sh")

        # add cpanel-specific cron jobs
        # cron task to clean user-specified php-sessions
        create_cron_cpanel_sessions()

        cagefs_universal_hook_lib.install_multiphp_universal_hook()
        cagefs_universal_hook_lib.install_passenger_universal_hook()
        # install yum universal hook for environments without LVE
        # to process a new ea-php fpm and native php-fpm packages
        if cagefslib.is_running_without_lve():
            cagefs_universal_hook_lib.install_without_lve_universal_hooks()

    elif cp.name == "InterWorx":
        update_sudoers('iworx')
        if not os.path.exists(NEW_EXCLUDE_PATH):
            mod_makedirs(NEW_EXCLUDE_PATH, 0o750)
        shutil.copyfile(SOURCE_PATH+"interworx-cagefs/iworxuserslist", os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist"))
        os.chmod(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist"), 0o600)
        install_native_conf("interworx-cagefs/iworx.native.conf")
        set_min_uid()
        if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suexec"):
            if (not os.path.exists("/usr/sbin/suexec.bak")) and os.path.exists("/usr/sbin/suexec"):
                shutil.copyfile("/usr/sbin/suexec", "/usr/sbin/suexec.bak")
            shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suexec", "/usr/sbin/suexec")
            try:
                gr = grp.getgrnam('apache')
                os.chown('/usr/sbin/suexec', 0, gr.gr_gid)
            except KeyError:
                pass
            os.chmod('/usr/sbin/suexec', 0o4510)
        if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suphp"):
            if (not os.path.exists("/usr/sbin/suphp.bak")) and os.path.exists("/usr/sbin/suphp"):
                shutil.copyfile("/usr/sbin/suphp", "/usr/sbin/suphp.bak")
            shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suphp", "/usr/sbin/suphp")
            os.chown('/usr/sbin/suphp', 0, 0)
            os.chmod('/usr/sbin/suphp', 0o4755)

    elif cp.name == "ISPManager":
        # ISP Manager 4
        if not os.path.isfile('/etc/cagefs/cagefs.base.home.dirs'):
            exec_command('echo "^/var/www/" > /etc/cagefs/cagefs.base.home.dirs')
            touch('/usr/share/cagefs/need.remount')
        if os.path.isdir('/var/www/php-bin'):
            exec_command('/bin/chmod o-r /var/www/php-bin')
            add_mount_to_cagefs_mp('/var/www/php-bin')
        set_min_uid()
        # Clear ISP Manager's cache and restart it
        shutil.rmtree('/usr/local/ispmgr/var/.xmlcache/ispmgr', True)
        exec_command("/usr/bin/killall ispmgr")
        install_native_conf("ispmanager-cagefs/ispmanager.native.conf")

    elif cp.name == "DirectAdmin":
        add_mount_to_cagefs_mp('/var/www/html')
        set_min_uid()
        if not os.path.exists(NEW_EXCLUDE_PATH):
            mod_makedirs(NEW_EXCLUDE_PATH, 0o0750)
        if not os.path.exists(cagefsctl.EXCLUDE_PATH):
            mod_makedirs(cagefsctl.EXCLUDE_PATH, 0o0751)
        shutil.copyfile(SOURCE_PATH+"directadmin-cagefs/directadminusers", os.path.join(NEW_EXCLUDE_PATH,
                                                                                        "directadminusers"))
        # Add all DA admins to sudoers and /etc/cagefs/exclude/directadmin.admins
        sync_control_panel_admins()
        install_native_conf("directadmin-cagefs/directadmin.native.conf")
        # CAG-916: set cagefs=yes in options.conf when installing CageFS on DirectAdmin server
        subprocess.run('/usr/local/directadmin/custombuild/build set cagefs yes', shell=True, executable='/bin/bash')
    else:
        if cp.name == "Unknown" and cagefslib.is_running_without_lve():
            # Namespace creation cronjob should only run on no-panel systems in environments without LVE
            create_cron_namespaces()
        print("Panel name: "+cp.name+" version: "+cp.version)
        if not os.path.exists(cagefsctl.EXCLUDE_PATH):
            mod_makedirs(cagefsctl.EXCLUDE_PATH, 0o751)
        sync_control_panel_admins()
        set_min_uid()


def delete_plugin():
    """
    Remove cagefs plugin from system
    """
    #delete web-face
    delete_plugin_web()

    # Remove cagefs cronjob
    if os.path.exists("/etc/cron.d/cp-cagefs-cron"):
        os.remove("/etc/cron.d/cp-cagefs-cron")
    if os.path.exists("/etc/cron.daily/cagefs.cron"):
        os.remove("/etc/cron.daily/cagefs.cron")
    # Remove alt-php sessions cleaner cron
    if os.path.exists(PLESK_CRON_PHP_CLEANER_HOURLY_PATH):
        os.remove(PLESK_CRON_PHP_CLEANER_HOURLY_PATH)
    # Remove exclude users check cron
    if os.path.exists(EXCLUDE_USERS_CRON_FILE):
        os.remove(EXCLUDE_USERS_CRON_FILE)
    # Remove namespace creation cron
    if os.path.exists(CREATE_NAMESPACES_CRON_FILE):
        os.remove(CREATE_NAMESPACES_CRON_FILE)

    # remove installed files
    #in CAG-248 securelinks support was removed, but uninstall script should still delete old files
    if cp.name == "Plesk" and verCompare(cp.version, "10") >= 0:
        if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist")):
            os.remove(os.path.join(NEW_EXCLUDE_PATH, "pleskuserlist"))
        if os.path.exists("/etc/cagefs/securelinks/plesk.htaccess"):
            os.remove("/etc/cagefs/securelinks/plesk.htaccess")

    elif cp.name == "cPanel":
        exec_command("/usr/share/cagefs/cpanel/cpanel-delete-cagefs")

        # remove rearrange-acc hook. hook works only for 11.54+
        exec_command("/usr/share/cagefs/cpanel/cpanel_hooks_manage.py -d")

        print("Rebuilding Apache's suexec...")
        exec_command("/usr/sbin/cpanel-compile-suexec.sh 500 restore")
        print("Rebuilding suphp...")
        exec_command("/usr/sbin/cpanel-compile-suphp.sh 1 restore")
        if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist")):
            os.remove(os.path.join(NEW_EXCLUDE_PATH, "cpaneluserlist"))
        if os.path.exists("/etc/cagefs/securelinks/cpanel.htaccess"):
            os.remove("/etc/cagefs/securelinks/cpanel.htaccess")

        cagefs_universal_hook_lib.remove_multiphp_universal_hook()
        cagefs_universal_hook_lib.remove_passenger_universal_hook()
        if cagefslib.is_running_without_lve():
            cagefs_universal_hook_lib.remove_without_lve_universal_hooks()

    elif cp.name == "InterWorx":
        if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist")):
            os.remove(os.path.join(NEW_EXCLUDE_PATH, "iworxuserslist"))
        if os.path.exists("/usr/sbin/suexec.bak"):
            shutil.copyfile("/usr/sbin/suexec.bak", "/usr/sbin/suexec")
        if os.path.exists("/usr/sbin/suphp.bak"):
            shutil.copyfile("/usr/sbin/suphp.bak", "/usr/sbin/suphp")
        if os.path.exists("/etc/cagefs/securelinks/interworx.htaccess"):
            os.remove("/etc/cagefs/securelinks/interworx.htaccess")

    elif cp.name == "ISPManager":
        if verCompare(cp.version, "5") == -1:
            # ISP Manager 4
            exec_command("/usr/bin/killall ispmgr")
            if os.path.exists("/etc/cagefs/securelinks/ispmanager.htaccess"):
                os.remove("/etc/cagefs/securelinks/ispmanager.htaccess")

    elif cp.name == "DirectAdmin":
        if os.path.exists(os.path.join(NEW_EXCLUDE_PATH, "directadminusers")):
            os.remove(os.path.join(NEW_EXCLUDE_PATH, "directadminusers"))
        if os.path.exists("/etc/cagefs/securelinks/directadmin.htaccess"):
            os.remove("/etc/cagefs/securelinks/directadmin.htaccess")
    else:
        print("Current panel unsupported. Panel name: "+cp.name+" version: "+cp.version)
    litespeed_enableLVE_configure(force_value = 0)
    litespeed_lsphp5_path_change(lsphp5_path = '$SERVER_ROOT/fcgi-bin/lsphp5')
    litespeed_config_write()
    if cagefslib.is_running_without_lve():
        cagefs_without_lve_lib.restore_httpd_php_fpm_services()


def cp_supported():
    if cp.name == "Plesk" and verCompare (cp.version, "10") >= 0:
        return True
    if cp.name in ("cPanel", "InterWorx", "ISPManager", "DirectAdmin"):
        return True
    return False


def cron_update():
    """
    Periodically update cagefs
    """
    lockname = '/var/run/cloudlinux_update_cagefs.cronlock'
    lockfile = cagefsctl.acquire_lock(lockname, wait=False, quiet=True)

    try:
        if os.path.exists('/etc/cagefs/users.disabled') or os.path.exists('/etc/cagefs/users.enabled'):
            exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --update --do-not-ask --silent > /dev/null 2>&1")
            exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --skip-php-reload --setup-cl-selector > /dev/null 2>&1")
            if os.path.isfile('/usr/share/cagefs/need.remount'):
                exec_command("/usr/sbin/cagefsctl --remount-all > /dev/null 2>&1")
            exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --clean-var-cagefs > /dev/null 2>&1")
            exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --clean-config-dirs > /dev/null 2>&1")
            exec_command("/usr/bin/ionice -c 3 /usr/sbin/cagefsctl --tmpwatch > /dev/null 2>&1")
    finally:
        cagefsctl.unlock(lockfile, lockname)


def call_httpdtrigger():
    if cp.name == "InterWorx":
        if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suexec"):
            if (not os.path.exists("/usr/sbin/suexec.bak")) and os.path.exists("/usr/sbin/suexec"):
                shutil.copyfile("/usr/sbin/suexec", "/usr/sbin/suexec.bak")
            shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suexec", "/usr/sbin/suexec")
            try:
                gr = grp.getgrnam('apache')
                os.chown('/usr/sbin/suexec', 0, gr.gr_gid)
            except KeyError:
                pass
            os.chmod('/usr/sbin/suexec', 0o4510)


def call_suphptrigger():
    if cp.name == "InterWorx":
        if os.path.exists("/usr/share/cagefs-plugins/binary/inetrworx/suphp"):
            if (not os.path.exists("/usr/sbin/suphp.bak")) and os.path.exists("/usr/sbin/suphp"):
                shutil.copyfile("/usr/sbin/suphp", "/usr/sbin/suphp.bak")
            shutil.copyfile("/usr/share/cagefs-plugins/binary/inetrworx/suphp", "/usr/sbin/suphp")
            os.chown('/usr/sbin/suphp', 0, 0)
            os.chmod('/usr/sbin/suphp', 0o4755)


def toggle_plugin():
    if os.path.exists(NEED_PLUGIN):
        install_plugin_web()
        os.remove(NEED_PLUGIN)
    else:
        delete_plugin_web()
        touch(NEED_PLUGIN)


class ControlPanel(object):
    name = ''
    varsion = ''

    def __init__(self, name, version):
        self.name = name
        self.version = version


def build_parser():
    """
    Build argument parser and parse input arguments
    """
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--install", help="install CageFS plugin",
                                            action="store_true")
    parser.add_argument("--install-plesk-wrapper", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("-d", "--delete", help="delete CageFS plugin",
                                            action="store_true")
    parser.add_argument("--uninstall", help="do actions while uninstalling CageFS",
                                            action="store_true")
    parser.add_argument("-c", "--cronupdate", help="cagefsctl --update",
                                            action="store_true")
    parser.add_argument("-r", "--httpdtrigger", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("-t", "--suphptrigger", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("-p", "--toggle-plugin", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("-n", "--manage-multiphp-cron-file", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("--add-usr-local-easy-mount", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("--setup-ea-php-sessions", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("--fix-shared-mounts", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("--force-fix-shared-mounts", help=argparse.SUPPRESS,
                                            action="store_true")
    parser.add_argument("--fix-services-without-lve", help=argparse.SUPPRESS,
                        action="store_true")

    help_text = ("add /usr/share/cagefs-skeleton/dev/log to syslog config and"
                             " restart syslog")
    parser.add_argument("--add-syslog-socket", action="store_true",
                                            help=help_text)

    help_text = ("remove /usr/share/cagefs-skeleton/dev/log from syslog config"
                             " and restart syslog")
    parser.add_argument("--remove-syslog-socket", action="store_true",
                                            help=help_text)
    return parser


def register_cagefs_plugin():
    fd = open(ROOT_PLESK_DIR+"plib/modules/plesk-cagefs/meta.xml", 'w')
    text = """<?xml version="1.0" encoding="utf-8"?>
<module>
<id>plesk-cagefs</id>
<name>CageFS</name>
<description>CageFS</description>
<url>http://cloudlinux.com/</url>
<version>{version}</version>
<release>{release}</release>
<vendor>Cloud Linux</vendor>
<icon>/images/modules/plesk-cagefs/addon_CloudLinux_logo.png</icon>
</module>"""
    release_number = CAGEFS_RELEASE.split('.')[0]
    fd.write(text.format(version=CAGEFS_VERSION, release=release_number))
    fd.close()
    exec_command('/usr/local/psa/bin/extension --register plesk-cagefs')


def uninstall_cagefs():
    """
    This function is executed while uninstall (not upgrade) of cagefs package
    """
    if cp.name == "DirectAdmin":
        # CAG-916: set cagefs=no in options.conf when uninstalling CageFS on DirectAdmin server
        subprocess.run('/usr/local/directadmin/custombuild/build set cagefs no', shell=True, executable='/bin/bash')


def fix_services_without_lve():
    """
    Reconfigure httpd and ea-php-fpm services to work in environment without LVE
    """
    if cagefslib.is_running_without_lve():
        cagefs_without_lve_lib.fix_httpd_php_fpm_services()


def main(argv):
    """
    Script run function
    """
    parser = build_parser()
    if len(argv) == 0:
        parser.print_help()
        sys.exit(2)

    args = parser.parse_args(argv)

    if args.install:
        install_plugin()
    if args.install_plesk_wrapper:
        cagefslib.install_plesk_wrapper()
    if args.delete:
        delete_plugin()
    if args.uninstall:
        uninstall_cagefs()
    if args.cronupdate:
        cron_update()
    if args.httpdtrigger:
        call_httpdtrigger()
    if args.suphptrigger:
        call_suphptrigger()
    if args.toggle_plugin:
        toggle_plugin()
    if args.add_syslog_socket:
        add_syslog_socket()
    if args.remove_syslog_socket:
        remove_syslog_socket()
    if args.manage_multiphp_cron_file:
        manage_cron_file()
    if args.add_usr_local_easy_mount:
        add_usr_local_easy_mount()
    if args.setup_ea_php_sessions:
        setup_ea_php_sessions()
    if args.fix_shared_mounts or args.force_fix_shared_mounts:
        fix_shared_mounts(args.force_fix_shared_mounts)
    if args.fix_services_without_lve:
        fix_services_without_lve()


if "__main__" == __name__:
    detect.getCP()
    cp = ControlPanel(detect.CP_NAME, detect.CP_VERSION)
    main(sys.argv[1:])