Mini Shell
#!/opt/alt/python37/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
import sys
import getopt
import os
import clcommon
import traceback
from builtins import map
from .clselect import ClSelect
from .clextselect import ClExtSelect, depend_modules_dict
from .cluserselect import ClUserSelect
from .cluserextselect import ClUserExtSelect
from .cluseroptselect import ClUserOptSelect
from .clselectprint import clprint
from clcommon import ClPwd
from clcommon.sysctl import SysCtlConf, SYSCTL_CL_CONF_FILE
from clcommon.utils import run_command, ExternalProgramFailed
from .utils import in_cagefs, make_symlink
from .clselectexcept import ClSelectExcept, BaseClSelectException
import simplejson as json
import shutil
# This is the oldest version with all bad things
API_0 = 0
# This version replaces hardcoded interpreter name in utility output with more
# generic key names that will be correctly understood by cloudlinux-selector
API_1 = 1
# Path to cagefs command
CAGEFSCTL_COMMAND = '/usr/sbin/cagefsctl'
def usage():
print(' -v | --version : Specify alternative version')
print(' -u | --user : Username')
print(' -l | --list : List alternatives for interpreter')
print(' -G | --list-extensions : List global set of extensions for alternative')
print(' -S | --summary : List summary of alternatives')
print(' -s | --user-summary : List user summary of alternatives')
print(' -C | --current : Show currently selected alternative')
print(' -c | --user-current : Show currently selected alternative for a user')
print(' -B | --set-current : Set alternative as global default')
print(' -b | --set-user-current : Set alternative as user default')
print(' -Y | --enable-alternative : Enable alternative globally')
print(' -N | --disable-alternative : Disable alternative globally')
print(' -E | --enable-extensions : Enable comma-separated list of extensions globally for a version')
print(' -D | --disable-extensions : Disable comma-separated list of extensions globally for a version')
print(' -R | --replace-extensions : Replace extensions with comma-separated list of extensions ')
print(' for a version globally')
print(' -e | --enable-user-extensions : Enable comma-separated list of extensions for a user')
print(' -d | --disable-user-extensions : Disable comma-separated list of extensions for a user')
print(' -r | --replace-user-extensions : Replace user extensions with comma-separated list of extensions')
print(' -t | --reset-user-extensions : Replace user extensions with version default extensions')
print(' -g | --list-user-extensions : List enabled extensions for a user. With key --all shows all extensions')
print(' -a | --all : Show all extensions')
print(' -p | --print-summary : If specified along with setting an alternative prints user summary')
print(' -V | --show-native-version : Shows native version while showing summary or selected version')
print(' -L | --list-users : List users who use a specified alternative')
print(' -T | --change-to-version : Changes to a specified version all users who have a certain version')
print(' -k | --add-options : Add comma-separated list options for a user')
print(' -m | --replace-options : Replace user options with comma-separated list of options')
print(' -x | --delete-options : Delete comma-separated list options for a user')
print(' -Q | --base64 : Expects data as comma-separated base64-encoded string')
print(' -q | --quiet : Suppress errors messages for wrong input')
print(' -P | --print-options : Prints user options. By default prints as plain text')
print(' --print-options-safe : Prints user options. By default prints as plain text (safe strings)')
print(' --apply-symlinks-rules : Recreate symlinks to php extensions for all users ')
print(' based on /etc/cl.selector/symlinks.rules file')
print(' --exclude-pid-list : Specify list of PIDs of processes that should not be signaled by SIGHUP')
print(' -j | --json : Print data as JSON')
print(' -w | --csv : Print data as CSV')
print(' -W | --perl : Print data as perl structure')
print(' --api-version : Integer, representing specific api version to use. ')
print(' Defaults to {}'.format(API_0))
print(' -z | --reset-options : Deletes all user custom options. Range can be narrowed with user ')
print(' or version options')
print(' --update-backup : write settings to backup')
print(' --apply-global-php-ini : use with 0, 1 or 2 arguments from the list: error_log, date.timezone')
print(' without arguments applies all global php options including two above')
print(' --setup-without-cagefs : setup PHP Selector without CageFS')
print(' --revert-to-cagefs : revert to default setup of PHP Selector (with CageFS)')
print(' --for-all-users : applies specified action for all users in CageFS. ')
print(' Available only for enable/disable user extensions')
def print_error_and_exit(message, prefix=None):
"""
Prints to stderr
@param message: string
"""
fmt = "%s\n"
if prefix:
fmt = "%s:%s\n" % (prefix, '%s')
sys.stderr.write(fmt % message)
sys.exit(1)
def check_args_presence():
"""
Checks presence of command line arguments
and exits with usage info if missing
"""
if len(sys.argv) == 1:
print_error_and_exit(
"Command line arguments expected. "
"For help use '-h' or '--help' options")
def get_name_modifier(version):
"""
"""
BASE_ALT_DIR = '/opt/alt/php'
ver = version.replace('.','')
name_modifier_file = BASE_ALT_DIR + ver + '/name_modifier'
name_modifier = ''
if os.path.isfile(name_modifier_file):
try:
name_modifier = open(name_modifier_file,'r').readline().strip()
except (OSError, IOError):
return ''
return name_modifier
def letter_to_status(letter):
if letter == '-':
return 'disabled'
elif letter == 'e':
return 'enabled'
def format_summary(data, format='text', api_version=API_0):
if api_version == API_0:
available_versions_key = 'PHPConfiguration'
default_version_key = 'defaultPHPversion'
else:
available_versions_key = 'available_versions'
default_version_key = 'default_version'
states = ['e', 'd', 's']
text_lines = []
json_dict = {
available_versions_key: [],
}
for alt in data:
row_length = len(alt[1])
fmt = ' '.join(['%s'] * (row_length+1))
row_data = [alt[0]]
row_data.extend(list(map(
(lambda i: ((alt[1][i] and states[i]) or '-')),
range(row_length)))) # pylint: disable=range-builtin-not-iterating
name_modifier = get_name_modifier(alt[0])
if name_modifier != "":
fmt = ' '.join(['%s'] * (row_length+2))
row_data.append(name_modifier)
if format == 'text':
text_lines.append(fmt % tuple(row_data))
if 'd' in row_data:
json_dict[default_version_key] = row_data[0]
json_dict[available_versions_key].append({
'version': row_data[0],
'status': letter_to_status(row_data[1]),
'name_modifier': name_modifier,
})
if format == 'json':
return json.dumps(json_dict)
elif format == 'text':
return '\n'.join(text_lines)
def print_summary(data, format='text', api_version=API_0):
"""
Prints alternatives summary
"""
data = format_summary(data, format, api_version)
print(data)
def check_params(config, param_list):
"""
Check that config has param_list and this params not None
"""
for param in param_list:
if param not in config or config[param] == None:
print_error_and_exit("Error: %s must be specified" % param)
def ext_letter_to_status(letter):
if letter == '~':
return 'build-in'
elif letter == '+':
return 'enabled'
else:
return 'disabled'
def fill_descriptions(tmp_list):
descr_file = '/etc/cl.selector/phpextdesc.txt'
with open(descr_file) as f:
desct_content = f.readlines()
full_desct_dict = {}
for line in desct_content:
line_parts = line.split('=')
full_desct_dict[line_parts[0]] = line_parts[1].strip()
for item in tmp_list:
try:
item['description'] = full_desct_dict[item['name']]
except KeyError: # skip extention without description
pass
return tmp_list
def print_json_status_ok():
result_dict = {'status': 'ok'}
print(json.dumps(result_dict))
def get_cpanel_user():
"""
Return user (name of cpanel account) for PHP Selector without CageFS feature
"""
if os.path.isfile(ClSelect.USER_CONF):
with open(ClSelect.USER_CONF, 'r') as f:
return f.read().strip()
pwd = ClPwd()
for user in pwd.get_user_dict():
if os.path.exists('/var/cpanel/users/'+user):
return user
return None
def set_cpanel_user(user):
"""
Set user (name of cpanel account) for PHP Selector without CageFS feature
"""
with open(ClSelect.USER_CONF, 'w') as f:
f.write(user)
os.chmod(ClSelect.USER_CONF, 0o644)
def switch_linksafe(enable=False):
new_conf = '/etc/sysctl.d/cloudlinux-linksafe.conf'
if os.path.isfile(new_conf):
conf = new_conf
else:
conf = SYSCTL_CL_CONF_FILE
sysctl_cfg = SysCtlConf(config_file=conf)
sysctl_cfg.set('fs.protected_symlinks_create', str(int(enable)))
sysctl_cfg.set('fs.protected_hardlinks_create', str(int(enable)))
if os.system('sysctl --system &>/dev/null') != 0:
print('Error while executing: sysctl --system')
sys.exit(1)
def modify_search_path_in_bashrc(user, homedir, obj=None, add=True):
"""
Add path to PATH variable in ~/.bashrc
:param user: name of user
:type user: string
:param homedir: path to home directory
:type homedir: string
:param obj: instance of ClUserSelect class
:type obj: instance of ClUserSelect class
:param add: add path to .bashrc when True, remove otherwise
:type obj: bool
"""
if obj is None:
obj = ClUserSelect('php')
cur_user = obj._change_uid(user)
bashrc = homedir + '/.bashrc'
line = 'PATH=$HOME/'+ClUserSelect.SELECTOR2_DIR+':$HOME/.cl.selector:$PATH'
with open(bashrc, 'r') as f:
found = line+'\n' in f
if add:
if not found:
with open(bashrc, 'a') as f:
f.write('\n'+line+'\n')
else:
if found:
clcommon.utils.delete_line_from_file(bashrc, line)
obj._restore_uid(cur_user)
def restore_settings_from_backup(user, homedir, uid, alt_dirs, obj=None):
"""
Restore (apply) settings for PHP Selector from backup
:param user: name of user
:type user: string
:param homedir: path to user's home directory
:type homedir: string
:param uid: user's uid
:type uid: int
:param alt_dirs: list of alt-php directories like ['php51', 'php52']
:type alt_dirs: list
:param obj: instance of ClUserSelect class
:type obj: ClUserSelect object
"""
def cleanup():
# Delete unneeded files
shutil.rmtree(os.path.join('/var/cagefs', str(uid)[-2:]), True)
shutil.rmtree('/usr/share/cagefs/etc', True)
shutil.rmtree('/usr/share/cagefs/etc.new', True)
if obj is None:
obj = ClUserSelect('php')
base_dest_path = homedir + '/.cl.selector'
cleanup()
# Generate alt_php.ini for all versions using cagefsctl
if os.system('/usr/sbin/cagefsctl --silent --force-update-etc '+user) != 0:
sys.exit(1)
cur_user = obj._change_uid(user)
# Copy generated alt_php.ini files to new location in user's home directory
base_src_path = os.path.join('/var/cagefs', str(uid)[-2:], user, 'etc', 'cl.php.d')
for alt_dir in alt_dirs:
src_path = base_src_path + '/alt-' + alt_dir + '/alt_php.ini'
dest_path = base_dest_path + '/alt_' + alt_dir + '.ini'
shutil.copy(src_path, dest_path)
# Select php version from backup (or default when backup does not exist)
obj.set_version_from_backup(user)
shutil.rmtree(homedir+'/.cagefs', True)
obj._restore_uid(cur_user)
cleanup()
def disable_cagefs_service():
if os.path.isfile('/usr/bin/systemctl'):
os.system('/usr/bin/systemctl disable cagefs')
os.system('/usr/bin/systemctl stop cagefs')
os.system('/usr/bin/systemctl mask cagefs')
else:
os.system('/sbin/service cagefs stop &> /dev/null')
os.system('/sbin/chkconfig cagefs off')
def enable_cagefs_service():
if os.path.isfile('/usr/bin/systemctl'):
os.system('/usr/bin/systemctl unmask cagefs')
os.system('/usr/bin/systemctl enable cagefs')
os.system('/usr/bin/systemctl start cagefs')
else:
os.system('/sbin/chkconfig cagefs on')
os.system('/sbin/service cagefs start &> /dev/null')
def setup_without_cagefs(args):
"""
Setup PHP Selector without CageFS
"""
sys.path.append('/usr/share/cagefs')
try:
import cagefslib
except ImportError:
print('Error: CageFS is not installed')
sys.exit(1)
# alt-php versions are installed ?
alt_dirs = cagefslib.get_alt_dirs()
if not alt_dirs:
print('alt-php not found')
sys.exit(1)
# detect cpanel user
if args:
user = args[0]
set_cpanel_user(user)
else:
user = get_cpanel_user()
if not user:
print('Error: failed to detect cpanel account. Please specify name of an account as argument:')
print('selectorctl --setup-without-cagefs USER')
sys.exit(1)
if not os.path.exists(ClSelect.USER_CONF):
set_cpanel_user(user)
# disable linksafe protection
switch_linksafe()
import pwd
pw = pwd.getpwnam(user)
homedir = pw.pw_dir
# create symlinks to user's alt_php.ini files
for alt_dir in alt_dirs:
alt_path = '/opt/alt/' + alt_dir + '/link/conf/alt_php.ini'
user_path = homedir + '/.cl.selector/alt_' + alt_dir + '.ini'
make_symlink(user_path, alt_path)
obj = ClUserSelect('php')
restore_settings_from_backup(user, homedir, pw.pw_uid, alt_dirs, obj)
obj.create_selector_symlinks(user)
modify_search_path_in_bashrc(user, homedir, obj)
disable_cagefs_service()
# kill user's processes in LVE
os.system('/usr/sbin/lvectl destroy '+str(pw.pw_uid)+' &>/dev/null; /usr/sbin/lvectl apply '+str(pw.pw_uid)+' &>/dev/null')
def revert_to_cagefs():
"""
Revert to default PHP Selector setup with CageFS
"""
if not os.path.exists(ClSelect.USER_CONF):
print('PHP Selector is in default mode already ("with CageFS" mode)')
sys.exit(1)
sys.path.append('/usr/share/cagefs')
try:
import cagefslib
except ImportError:
print('Error: CageFS is not installed')
sys.exit(1)
# alt-php versions are installed ?
alt_dirs = cagefslib.get_alt_dirs()
if not alt_dirs:
print('alt-php not found')
sys.exit(1)
switch_linksafe(enable=True)
# delete symlinks to user's alt_php.ini files
for alt_dir in alt_dirs:
alt_path = '/opt/alt/' + alt_dir + '/link/conf/alt_php.ini'
if os.path.islink(alt_path):
os.unlink(alt_path)
user = get_cpanel_user()
if not user:
print('Error: failed to detect user')
sys.exit(1)
import pwd
pw = pwd.getpwnam(user)
homedir = pw.pw_dir
obj = ClUserSelect('php')
modify_search_path_in_bashrc(user, homedir, obj, add=False)
# Generate alt_php.ini for all versions using cagefsctl
os.system('/usr/sbin/cagefsctl --silent --force-update-etc '+user)
enable_cagefs_service()
# remove config file (file-switch) for "without CageFS" mode
os.unlink(ClSelect.USER_CONF)
# kill user's processes in LVE
os.system('/usr/sbin/lvectl destroy '+str(pw.pw_uid)+' &>/dev/null; /usr/sbin/lvectl apply '+str(pw.pw_uid)+' &>/dev/null')
def apply_global_php_ini(args):
"""
Apply "global" php.ini settings to all alt-php versions
:param args: list of command line parameters (names of php.ini options)
:type args: list
"""
sys.path.append('/usr/share/cagefs')
try:
import cagefslib
import cagefsreconfigure
except ImportError:
print('Error: CageFS is not installed')
sys.exit(1)
# alt-php versions are installed ?
if cagefslib.get_alt_versions():
cagefsreconfigure.replace_alt_settings(options=args)
def _check_depencies_and_print_message(print_format, print_message):
if len(depend_modules_dict):
# Warning - blocked modules present
modules_list = list()
for module_name, dep_module in depend_modules_dict.items():
modules_list.append(" '%s' is required for '%s'" % (module_name, dep_module))
clprint.print_diag(print_format, {'status': 'WARN',
'message': print_message + ','.join(modules_list)})
def get_extensions(interpreter, version, fmt='text'):
ext_list = ClExtSelect(interpreter).list_extensions(version)
return parse_extensions(ext_list, version, fmt)
def parse_extensions(ext_list, version, fmt):
json_list = []
for ext in ext_list:
action = '~'
if ext[1] is True:
action = '+'
elif ext[1] is False:
action = '-'
if fmt == 'text':
json_list.append((action, ext[0]))
else:
json_list.append({'name': ext[0], 'description': '', 'state': ext_letter_to_status(action)})
json_list = fill_descriptions(json_list)
if fmt == 'json':
result_dict = {'version': version, 'extensions': json_list}
return result_dict
return json_list
def get_cagefs_users():
"""
Return list of users that are in CageFS
If CageFS is not installed or initialized
throws exception and prints it
:return:
"""
not_installed_msg = 'No such file or directory'
not_initialized_msg = 'CageFS is not initialized'
try:
users = run_command([CAGEFSCTL_COMMAND, '--list-enabled']).strip()
if users == '':
return []
return users.split('\n')[1:] # First element shows number of users
except ExternalProgramFailed as e:
if not_installed_msg in str(e):
print_error_and_exit('ERROR: CageFS not installed.')
elif not_initialized_msg in str(e):
print_error_and_exit('Error: CageFS is not initialized. '
'Use "/usr/sbin/cagefsctl --init" to initialize CageFS')
print_error_and_exit(e)
def main():
config = {}
config['interpreter'] = 'php'
config['version'] = None
config['show-all'] = False
config['print-summary'] = False
config['show-native-version'] = False
config['decoder'] = 'plain'
config['quiet'] = False
config['format'] = 'text'
config['api-version'] = API_0
actions = {}
exclude_pid_list = []
check_args_presence()
if in_cagefs():
print('selectorctl does not work in CageFS for PHP interpreter')
sys.exit(1)
try:
opts, args = getopt.getopt(
sys.argv[1:],
'hi:lSsCcB:Y:N:E:D:R:v:Gu:b:ge:d:r:atpVLT:k:m:x:QqPjwWz',
['help',
'setup-without-cagefs',
'revert-to-cagefs',
'interpreter=',
'list',
'summary',
'user-summary',
'current',
'user-current',
'set-current=',
'enable-alternative=',
'disable-alternative=',
'enable-extensions=',
'disable-extensions=',
'replace-extensions=',
'version=',
'list-extensions',
'user=',
'set-user-current=',
'list-user-extensions',
'enable-user-extensions=',
'disable-user-extensions=',
'replace-user-extensions=',
'all',
'reset-user-extensions',
'print-summary',
'show-native-version',
'list-users',
'change-to-version=',
'add-options=',
'replace-options=',
'delete-options=',
'base64',
'apply-symlinks-rules',
'quiet',
'print-options',
'print-options-safe',
'json',
'csv',
'perl',
'api-version=',
'reset-options',
'update-backup',
'apply-global-php-ini',
'exclude-pid-list=',
'for-all-users'
])
except getopt.GetoptError:
usage()
sys.exit(1)
for o, a in opts:
if o in ['-h', '--help']:
usage()
sys.exit(0)
elif o in ['--exclude-pid-list']:
for pid in a.split(','):
try:
exclude_pid_list.append(int(pid))
except ValueError:
continue
elif o in ['--apply-symlinks-rules']:
actions['apply-symlinks-rules'] = True
elif o in ['--setup-without-cagefs']:
setup_without_cagefs(args)
sys.exit(0)
elif o in ['--revert-to-cagefs']:
revert_to_cagefs()
sys.exit(0)
elif o in ("--apply-global-php-ini",):
apply_global_php_ini(args)
sys.exit(0)
elif o in ['-l', '--list']:
actions['list-alternatives'] = True
elif o in ['-S', '--summary']:
actions['show-summary'] = True
elif o in ['-s', '--user-summary']:
actions['show-user-summary'] = True
elif o in ['-C', '--current']:
actions['show-current'] = True
elif o in ['-c', '--user-current']:
actions['show-user-current'] = True
elif o in ['-a', '--all']:
config['show-all'] = True
elif o in ['-v', '--version']:
config['version'] = a
elif o in ['-u', '--user']:
config['user'] = a
clpwd = ClPwd()
if ClSelect.work_without_cagefs():
uid = clpwd.get_uid(a)
else:
users = a.split(',')
user_list = list()
try:
if len(users) == 1:
uid = clpwd.get_uid(a)
if os.geteuid() == 0:
for user in clpwd.get_names(uid):
ClUserSelect().cagefs_copy_etc(user)
else:
for user in users:
if user not in user_list:
user_list += clpwd.get_names(clpwd.get_uid(user))
config['user'] = ','.join(user_list)
except ClPwd.NoSuchUserException as e:
sys.stderr.write(str(e)+'\n')
sys.exit(1)
elif o in ['-B', '--set-current']:
actions['set-current'] = a
elif o in ['-b', '--set-user-current']:
actions['set-user-current'] = a
elif o in ['-Y', '--enable-alternative']:
actions['enable-alternative'] = a
elif o in ['-N', '--disable-alternative']:
actions['disable-alternative'] = a
elif o in ['-G', '--list-extensions']:
actions['list-extensions'] = True
elif o in ['-g', '--list-user-extensions']:
actions['list-user-extensions'] = True
elif o in ['-E', '--enable-extensions']:
actions['enable-extensions'] = a
elif o in ['-D', '--disable-extensions']:
actions['disable-extensions'] = a
elif o in ['-R', '--replace-extensions']:
actions['replace-extensions'] = a
elif o in ['-e', '--enable-user-extensions']:
actions['enable-user-extensions'] = a
elif o in ['-d', '--disable-user-extensions']:
actions['disable-user-extensions'] = a
elif o in ['-r', '--replace-user-extensions']:
actions['replace-user-extensions'] = a
elif o in ['-t', '--reset-user-extensions']:
actions['reset-user-extensions'] = True
elif o in ['-p', '--print-summary']:
config['print-summary'] = True
elif o in ['-V', '--show-native-version']:
config['show-native-version'] = True
elif o in ['-L', '--list-users']:
actions['list-users'] = True
elif o in ['-T', '--change-to-version']:
actions['change-to-version'] = a
elif o in ['-k', '--add-options']:
actions['add-options'] = a
elif o in ['-m', '--replace-options']:
actions['replace-options'] = a
elif o in ['-x', '--delete-options']:
actions['delete-options'] = a
elif o in ['-Q', '--base64']:
config['decoder'] = 'base64'
elif o in ['-q', '--quiet']:
config['quiet'] = True
elif o in ['-P', '--print-options']:
actions['print-options'] = True
elif o in ['--print-options-safe']:
actions['print-options-safe'] = True
elif o in ['-j', '--json']:
config['format'] = 'json'
elif o in ['-w', '--csv']:
config['format'] = 'csv'
elif o in ['--api-version']:
config['api-version'] = int(a)
elif o in ['-W', '--perl']:
config['format'] = 'perl'
elif o in ['-z', '--reset-options']:
actions['reset-options'] = True
elif o in ['--update-backup']:
actions['update-backup'] = True
elif o in ['--for-all-users']:
if 'user' in config:
print_error_and_exit("--for-all-users and --user options are mutually"
" exclusive options and cannot be used simultaneously."
"\nUse --for-all-user OR --user instead.")
users = get_cagefs_users()
if not users:
print_error_and_exit("No changes were made: there are no users with cagefs enabled ")
clpwd = ClPwd()
user_list = list()
for user in users:
if user not in user_list:
user_list += clpwd.get_names(clpwd.get_uid(user))
config['user'] = ','.join(user_list)
if len(actions) != 1:
if len(actions) == 0 and config['show-native-version']:
try:
print(ClSelect(config['interpreter']).get_native_version()[0])
except TypeError:
pass
else:
print_error_and_exit("Wrong set of options", 'ERROR')
try:
# check if we are able to do anything before actually parsing options
# this two exceptions check for native version inside
# this is done because selectorctl is called in alt-php spec in cycle
# and we should avoid printing lot of messages there
if 'set-user-current' not in actions and \
'show-user-current' not in actions:
ClSelect().check_requirements()
if 'list-alternatives' in actions:
if config["format"] != "json":
for alt in ClSelect(config['interpreter']).list_alternatives():
print("%s\t%s\t%s" % (alt))
else:
alternatives_dict = {'status': 'ok', 'data': []}
for alt in ClSelect(config['interpreter']).list_alternatives():
alternatives_dict['data'].append({'short': alt[0], 'full': alt[1], 'path': alt[2]})
print(json.dumps(alternatives_dict))
elif 'show-summary' in actions:
data = ClSelect(config['interpreter']).get_summary(
config['show-native-version'])
print_summary(data, config['format'], config['api-version'])
elif 'show-current' in actions:
print("%s\t%s\t%s" % ClSelect(config['interpreter']).get_version(
config['show-native-version']))
elif 'set-current' in actions:
ClSelect(config['interpreter']).set_version(actions['set-current'])
if config['format'] == 'json':
print_json_status_ok()
elif 'enable-alternative' in actions:
ClSelect(config['interpreter']).enable_version(actions['enable-alternative'])
if config['format'] == 'json':
print_json_status_ok()
elif 'disable-alternative' in actions:
ClSelect(config['interpreter']).disable_version(actions['disable-alternative'])
if config['format'] == 'json':
print_json_status_ok()
elif 'list-extensions' in actions:
check_params(config, ('interpreter','version'))
ext_list = get_extensions(config['interpreter'], config['version'], config['format'])
if config['format'] == 'text':
for item in ext_list:
print("%s %s" % item)
elif config['format'] == 'json':
print(json.dumps(ext_list))
elif 'enable-extensions' in actions:
check_params(config, ('interpreter', 'version'))
ClExtSelect(config['interpreter']).enable_extensions(
config['version'],
list(map((lambda i: i.strip()), actions['enable-extensions'].split(','))))
elif 'disable-extensions' in actions:
check_params(config, ('interpreter', 'version'))
ClExtSelect(config['interpreter']).disable_extensions(
config['version'],
list(map((lambda i: i.strip()), actions['disable-extensions'].split(','))))
if len(depend_modules_dict):
# Warning - blocked modules present
_check_depencies_and_print_message(config['format'], 'Modules left by dependencies:')
elif 'replace-extensions' in actions:
check_params(config, ('interpreter', 'version'))
ClExtSelect(config['interpreter']).replace_extensions(
config['version'],
list(map((lambda i: i.strip()), actions['replace-extensions'].split(','))))
if len(depend_modules_dict):
# Warning - blocked modules present
_check_depencies_and_print_message(config['format'], 'Modules left/added by dependencies:')
elif config['format'] == 'json':
print_json_status_ok()
elif 'show-user-summary' in actions:
check_params(config, ('interpreter', 'user'))
data = ClUserSelect(config['interpreter'], exclude_pid_list).get_summary(
config['user'],
config['show-native-version'])
print_summary(data)
elif 'show-user-current' in actions:
check_params(config, ('interpreter', 'user'))
print("%s\t%s\t%s" % ClUserSelect(
config['interpreter'], exclude_pid_list).get_version(
config['user'],
config['show-native-version']))
elif 'apply-symlinks-rules' in actions:
check_params(config, ('interpreter',))
ClUserSelect(config['interpreter'], exclude_pid_list).apply_symlinks_rules()
elif 'set-user-current' in actions:
check_params(config, ('interpreter', 'user'))
# hack for alt-php spec where we read and re-apply
# php version for each user in system
# in order not to bump deps, we just silently
# ignore version set requests for 'native'
# (which should be set for all users on server
# because web ui does not work)
try:
ClSelect().check_requirements()
except ClSelectExcept.NativeNotInstalled:
if actions['set-user-current'] != 'native':
raise
exit(0)
# we intentionally use first user cause set_version has workaround for multiple same uid users
# LVEMAN-1670
user = clpwd.get_names(uid)[0]
c = ClUserSelect(config['interpreter'], exclude_pid_list)
data = c.set_version(user, actions['set-user-current'],
config['print-summary'], config['show-native-version'])
c.clean_crui_images(clpwd.get_names(uid))
if config['print-summary']:
print_summary(data)
elif 'list-user-extensions' in actions:
check_params(config, ('interpreter', 'user'))
if config['show-all']:
for ext in ClUserExtSelect(config['interpreter'], exclude_pid_list).list_all_extensions(
config['user'],
config['version']):
action = '-'
if ext[1]:
action = '+'
print("%s %s" % (action, ext[0]))
else:
for ext in ClUserExtSelect(config['interpreter'], exclude_pid_list).list_enabled_extensions(
config['user'],
config['version']):
print(ext[0])
elif 'enable-user-extensions' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
users = config['user'].split(',')
for user in users:
c = ClUserExtSelect(config['interpreter'], exclude_pid_list)
c.enable_extensions(
user=user,
version=config['version'],
ext_list=list(map((lambda i: i.strip()), actions['enable-user-extensions'].split(','))),
check_ext=True)
c.clean_crui_images(users)
elif 'disable-user-extensions' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
users = config['user'].split(',')
for user in users:
c = ClUserExtSelect(config['interpreter'], exclude_pid_list)
c.disable_extensions(
user,
config['version'],
list(map((lambda i: i.strip()), actions['disable-user-extensions'].split(','))))
c.clean_crui_images(users)
elif 'replace-user-extensions' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
user = clpwd.get_names(uid)[0]
c = ClUserExtSelect(config['interpreter'], exclude_pid_list)
c.replace_extensions(
user,
config['version'],
list(map((lambda i: i.strip()), actions['replace-user-extensions'].split(','))))
c.clean_crui_images(clpwd.get_names(uid))
elif 'reset-user-extensions' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
user = clpwd.get_names(uid)[0]
c = ClUserExtSelect(config['interpreter'], exclude_pid_list)
extensions = c.reset_extensions(user, config['version'])
c.clean_crui_images(clpwd.get_names(uid))
print(','.join(extensions))
elif 'list-users' in actions:
check_params(config, ('interpreter', 'version'))
users = ClUserSelect(config['interpreter'], exclude_pid_list).list_users(
config['version'])
print(','.join(users))
elif 'change-to-version' in actions:
check_params(config, ('interpreter', 'version'))
ClUserSelect(config['interpreter'], exclude_pid_list).change_to_version(
actions['change-to-version'],
config['version'])
elif 'add-options' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
user = clpwd.get_names(uid)[0]
c = ClUserOptSelect(config['interpreter'], exclude_pid_list)
c.insert_options(
user,
config['version'],
actions['add-options'],
config['decoder'],
True,
config['quiet'])
c.clean_crui_images(clpwd.get_names(uid))
if config['format'] == 'json':
clprint.print_data(config['format'], {})
elif 'replace-options' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
user = clpwd.get_names(uid)[0]
c = ClUserOptSelect(config['interpreter'], exclude_pid_list)
c.insert_options(
user,
config['version'],
actions['replace-options'],
config['decoder'],
False,
config['quiet'])
c.clean_crui_images(clpwd.get_names(uid))
if config['format'] == 'json':
clprint.print_data(config['format'], {})
elif 'delete-options' in actions:
check_params(config, ('interpreter', 'version', 'user'))
ClSelect.check_multiphp_system_default_version()
user = clpwd.get_names(uid)[0]
c = ClUserOptSelect(config['interpreter'], exclude_pid_list)
c.delete_options(
user,
config['version'],
actions['delete-options'],
config['decoder'],
config['quiet'])
c.clean_crui_images(clpwd.get_names(uid))
if config['format'] == 'json':
clprint.print_data(config['format'], {})
elif 'reset-options' in actions:
user = None
version = None
if 'user' in config:
user = config['user'].split(',')
if config['version']:
version = config['version'].split(',')
c = ClUserOptSelect(config['interpreter'], exclude_pid_list)
c.reset_options(user, version)
c.clean_crui_images(user)
if config['format'] == 'json':
clprint.print_data(config['format'], {})
elif 'print-options' in actions:
check_params(config, ('interpreter', 'user'))
clprint.print_data(config['format'],
ClUserOptSelect(config['interpreter'], exclude_pid_list).get_options(
config['user'],
config['version']))
elif 'print-options-safe' in actions:
check_params(config, ('interpreter', 'user'))
clprint.print_data(
config['format'],
ClUserOptSelect(config['interpreter'], exclude_pid_list).get_options(
config['user'],
config['version']
),
escape=True
)
elif 'update-backup' in actions:
clpwd = ClPwd()
for user in clpwd.get_user_dict().keys():
try:
ClUserSelect()._check_user_in_cagefs(user)
ClUserSelect()._backup_settings(user)
ClUserOptSelect().backup_php_options(user)
except ClSelectExcept.NotCageFSUser:
pass #SKIP user with disabled cagefs
except ClSelectExcept.UnableToSaveData as e:
if not config['quiet']:
clprint.print_diag(
config['format'],
{'status': 'ERROR', 'message': str(e)})
pass #SKIP user with errors
except ClSelectExcept.NativeNotInstalled as e:
clprint.print_diag(config['format'], {
'status': 'WARNING',
'message': str(e),
'details': e.details,
'context': e.context
})
sys.exit(1)
except BaseClSelectException as e:
clprint.print_diag(config['format'], {
'status': 'ERROR',
'message': str(e),
'details': e.details,
'context': e.context
})
sys.exit(1)
except (KeyError, UnboundLocalError):
print_error_and_exit("Incomplete or incorrect set of arguments")
except Exception as e:
msg = traceback.format_exc()
clprint.print_diag(
config['format'],
{'status': 'ERROR', 'message': msg})
if __name__ == '__main__':
main()
Zerion Mini Shell 1.0