#!/usr/bin/env python
# -*- mode:python; coding:utf-8; -*-
# author: Dmitriy Kasyanov <dkasyanov@cloudlinux.com>
import getopt
import glob
import logging
import os
import sys
import traceback
import ConfigParser
try:
import rpm
except:
class rpm:
@staticmethod
def labelCompare(version1, version2):
for i in range(0, len(version1)):
if version1[i] < version2[i]:
return -1
return 0
# Minimal version with MultiPHP support for alt-php
MIN_CPANEL_VERSION = '11.66.0.11'
SCL_PREFIX_PATH = '/etc/scl/prefixes'
CONFIG_PATH = '/opt/alt/alt-php-config/alt-php.cfg'
def configure_logging(verbose):
"""
Logging configuration function.
@type verbose: bool
@param verbose: Enable additional debug output if True, display only errors
otherwise.
"""
if verbose:
level = logging.DEBUG
else:
level = logging.ERROR
handler = logging.StreamHandler()
handler.setLevel(level)
log_format = "%(levelname)-8s: %(message)s"
formatter = logging.Formatter(log_format, "%H:%M:%S %d.%m.%y")
handler.setFormatter(formatter)
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(level)
return logger
def get_cpanel_version():
"""
Returns cPanel version if cPanel installed or None othervise.
@rtype: str or None
@return: String with cPanel version or None if cPanel not installed.
"""
if os.path.exists('/usr/local/cpanel/version'):
with open('/usr/local/cpanel/version', 'r') as fd:
version = fd.read()
return version
return None
def find_interpreter_versions():
"""
Returns list of installed alt-php versions and their base directories.
@rtype: list
@return: List of version (e.g. 44, 55) and base directory tuples.
"""
int_versions = []
base_path_regex = "/opt/alt/php[0-9][0-9]"
for int_dir in glob.glob(base_path_regex):
int_versions.append((int_dir[-2:], int_dir))
int_versions.sort()
return int_versions
def delete_prefix(prefix_path):
"""
Remove prefix file
@type prefix_path: str
@param prefix_path: Path to the prefix file, e.g. /etc/scl/prefix/alt-php70
@rtype: bool
@return: True if file was removed sucessfully, False otherwise
"""
try:
if os.path.exists(prefix_path):
os.unlink(prefix_path)
return True
except OSError, e:
logging.error(u"Couldn't remove prefix %s:\n%s" % (prefix_path, e))
return False
def create_prefix(prefix_path, prefix_content):
"""
Creates prefix with path to alt-php
@type prefix_path: str
@param prefix_path: Path to the prefix file, e.g. /etc/scl/prefix/alt-php70
@type prefix_content: str
@param prefix_content: SCL path, e.g. /opt/cloudlinux
@rtype: bool
@return: True if file was created sucessfully, False otherwise
"""
try:
with open(prefix_path, 'w') as fd:
fd.write(prefix_content)
except IOError, e:
logging.error(u"Couldn't open file %s:\n%s" % (prefix_path, e))
return False
return True
def reconfigure(config, int_version):
"""
@type config:
@param config:
@type int_version: str
@param int_version: Interpreter version (44, 55, 72, etc.)
@type int_path: str
@param int_path: Interpreter directory on the disk (/opt/alt/php51, etc.)
@rtype: bool
@return: True if reconfiguration was successful, False otherwise
"""
cp_version = get_cpanel_version()
prefix_name = "alt-php%s" % int_version
prefix_path = os.path.join(SCL_PREFIX_PATH, prefix_name)
prefix_content = "/opt/cloudlinux\n"
alt_php_enable_file = "/opt/cloudlinux/alt-php%s/enable" % int_version
if cp_version and rpm.labelCompare(
('1', cp_version, '0'), ('1', MIN_CPANEL_VERSION, '0')) == -1:
status = delete_prefix(prefix_path)
else:
try:
int_enabled = config.getboolean("MultiPHP Manager", prefix_name)
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError), e:
int_enabled = True
logging.error("Could not parse alt-php.cfg:\n %s" % e)
if int_enabled and os.path.exists(alt_php_enable_file):
status = create_prefix(prefix_path, prefix_content)
else:
status = delete_prefix(prefix_path)
return status
def check_alt_path_exists(int_path, int_name, int_ver):
"""
Check if alt-php path exist
----------
@type int_path: str or unicode
@param int_path: Interpreter directory on the disk (/opt/alt/php51, etc.)
@type int_name: str or unicode
@param int_name: Interpreter name (php, python)
@type int_ver: str or unicode
@apram int_ver: Interpreter version (44, 55, 72, etc.)
@rtype: bool
@return: True if interpreter path exists, False otherwise
"""
if not os.path.isdir(int_path):
print >> sys.stderr, u"unknown %s version %s" % (int_name, int_ver)
return False
return True
def main(sys_args):
try:
opts, args = getopt.getopt(sys_args, "p:v", ["php=", "verbose"])
except getopt.GetoptError, e:
print >> sys.stderr, \
u"cannot parse command line arguments: %s" % unicode(e)
return 1
verbose = False
int_versions = []
int_name = "php"
for opt, arg in opts:
if opt in ("-p", "--php"):
int_name = "php"
int_path = "/opt/alt/php%s" % arg
if check_alt_path_exists(int_path, int_name, arg):
int_versions.append((arg, int_path))
else:
return 1
if opt in ("-v", "--verbose"):
verbose = True
log = configure_logging(verbose)
config = ConfigParser.SafeConfigParser()
config.read(CONFIG_PATH)
try:
if not int_versions:
int_versions = find_interpreter_versions()
for int_ver, int_dir in int_versions:
reconfigure(config, int_ver)
return 0
except Exception, e:
log.error(u"cannot reconfigure alt-%s for SCL: %s. "
u"Traceback:\n%s" % (int_name, unicode(e),
traceback.format_exc()))
return 1
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))