diff --git a/install/scripts/config-services.php b/install/scripts/config-services.php new file mode 100755 index 00000000..1236fbf5 --- /dev/null +++ b/install/scripts/config-services.php @@ -0,0 +1,427 @@ +#!/usr/bin/php + (2018-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + */ + +// Check if we're in the CLI +if (@php_sapi_name() !== 'cli') { + die('This script will only work in the shell.'); +} + +require dirname(dirname(__DIR__)) . '/lib/classes/output/class.CmdLineHandler.php'; + +class ConfigServicesCmd extends CmdLineHandler +{ + + /** + * list of valid switches + * + * @var array + */ + public static $switches = array( + 'h' + ); + + /** + * list of valid parameters + * + * @var array + */ + public static $params = array( + 'create', + 'apply', + 'daemon', + 'list-daemons', + 'froxlor-dir', + 'help' + ); + + public static $action_class = 'Action'; + + public static function printHelp() + { + self::println(""); + self::println("Help / command line parameters:"); + self::println(""); + // commands + self::println("--create\t\tlets you create a services list configuration for the 'apply' command"); + self::println(""); + self::println("--apply\t\t\tconfigure your services by given configuration file. To create one run the --create command"); + self::println("\t\t\tExample: --apply=/path/to/my-config.json"); + self::println(""); + self::println("--list-daemons\t\tOutput the services that are going to be configured using a given config file. No services will be configured."); + self::println("\t\t\tExample: --apply=/path/to/my-config.json --list-daemons"); + self::println(""); + self::println("--daemon\t\tWhen running --apply you can specify a daemon. This will be the only service that gets configured"); + self::println("\t\t\tExample: --apply=/path/to/my-config.json --daemon=apache24"); + self::println(""); + self::println("--froxlor-dir\t\tpath to froxlor installation"); + self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/"); + self::println(""); + self::println("--help\t\t\tshow help screen (this)"); + self::println(""); + // switches + // self::println("-d\t\t\tenable debug output"); + self::println("-h\t\t\tsame as --help"); + self::println(""); + + die(); // end of execution + } +} + +class Action +{ + + private $_args = null; + + private $_name = null; + + private $_db = null; + + public function __construct($args) + { + $this->_args = $args; + $this->_validate(); + } + + public function getActionName() + { + return $this->_name; + } + + /** + * validates the parsed command line parameters + * + * @throws Exception + */ + private function _validate() + { + $this->_checkConfigParam(true); + $this->_parseConfig(); + + require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php'; + require FROXLOR_INSTALL_DIR . '/lib/functions.php'; + require FROXLOR_INSTALL_DIR . '/lib/classes/settings/class.Settings.php'; + require FROXLOR_INSTALL_DIR . '/lib/classes/config/class.ConfigParser.php'; + require FROXLOR_INSTALL_DIR . '/lib/classes/config/class.ConfigService.php'; + require FROXLOR_INSTALL_DIR . '/lib/classes/config/class.ConfigDaemon.php'; + + if (array_key_exists("create", $this->_args)) { + $this->_createConfig(); + } elseif (array_key_exists("apply", $this->_args)) { + $this->_applyConfig(); + } elseif (array_key_exists("list-daemons", $this->_args) || array_key_exists("daemon", $this->_args)) { + CmdLineHandler::printwarn("--list-daemons and --daemon only work together with --apply"); + } + } + + private function _createConfig() + { + $_daemons_config = array( + 'distro' => "" + ); + + $config_dir = FROXLOR_INSTALL_DIR . '/lib/configfiles/'; + // show list of available distro's + $distros = glob($config_dir . '*.xml'); + // tmp array + $distributions_select_data = array(); + // read in all the distros + foreach ($distros as $_distribution) { + // get configparser object + $dist = new ConfigParser($_distribution); + // get distro-info + $dist_display = $this->getCompleteDistroName($dist); + // store in tmp array + $distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution))); + } + + // sort by distribution name + ksort($distributions_select_data); + + // list all distributions + $mask = "|%-50.50s |%-50.50s |\n"; + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + printf($mask, 'dist', 'name'); + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + foreach ($distributions_select_data as $name => $filename) { + printf($mask, $filename, $name); + } + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + echo PHP_EOL; + + while (! in_array($_daemons_config['distro'], $distributions_select_data)) { + $_daemons_config['distro'] = CmdLineHandler::getInput("choose distribution", "stretch"); + } + + // go through all services and let user check whether to include it or not + $configfiles = new ConfigParser($config_dir . '/' . $_daemons_config['distro'] . ".xml"); + $services = $configfiles->getServices(); + + foreach ($services as $si => $service) { + echo PHP_EOL . "--- " . strtoupper($si) . " ---" . PHP_EOL . PHP_EOL; + $_daemons_config[$si] = ""; + + $daemons = $service->getDaemons(); + $mask = "|%-50.50s |%-50.50s |\n"; + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + printf($mask, 'value', 'name'); + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + $default_daemon = ""; + foreach ($daemons as $di => $dd) { + $title = $dd->title; + if ($dd->default) { + $default_daemon = $di; + $title = $title . " (default)"; + } + printf($mask, $di, $title); + } + printf($mask, "x", "No " . $si); + $daemons['x'] = 'x'; + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + echo PHP_EOL; + if ($si == 'system') { + $_daemons_config[$si] = array(); + // for the system/other services we need a multiple choice possibility + CmdLineHandler::println("Select every service you need. Enter empty value when done"); + $sysservice = ""; + do { + $sysservice = CmdLineHandler::getInput("choose service"); + if (! empty($sysservice)) { + $_daemons_config[$si][] = $sysservice; + } + } while (! empty($sysservice)); + } else { + // for all others -> only one value + while (! array_key_exists($_daemons_config[$si], $daemons)) { + $_daemons_config[$si] = CmdLineHandler::getInput("choose service", $default_daemon); + } + } + } + + echo PHP_EOL . PHP_EOL; + $daemons_config = json_encode($_daemons_config); + $output = CmdLineHandler::getInput("choose output-filename", "/tmp/froxlor-config-" . date('Ymd') . ".json"); + file_put_contents($output, $daemons_config); + CmdLineHandler::printsucc("Successfully generated service-configfile '" . $output . "'"); + } + + private function getCompleteDistroName($cparser) + { + // get distro-info + $dist_display = $cparser->distributionName; + if ($cparser->distributionCodename != '') { + $dist_display .= " " . $cparser->distributionCodename; + } + if ($cparser->distributionVersion != '') { + $dist_display .= " (" . $cparser->distributionVersion . ")"; + } + if ($cparser->deprecated) { + $dist_display .= " [deprecated]"; + } + return $dist_display; + } + + private function _applyConfig() + { + if (! is_file($this->_args["apply"])) { + throw new Exception("Given config file is not a file"); + } elseif (! file_exists($this->_args["apply"])) { + throw new Exception("Given config file cannot be found ('" . $this->_args["apply"] . "')"); + } elseif (! is_readable($this->_args["apply"])) { + throw new Exception("Given config file cannot be read ('" . $this->_args["apply"] . "')"); + } + + $config = file_get_contents($this->_args["apply"]); + $decoded_config = json_decode($config, true); + + if (array_key_exists("list-daemons", $this->_args)) { + $mask = "|%-50.50s |%-50.50s |\n"; + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + printf($mask, 'service', 'daemon'); + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + foreach ($decoded_config as $service => $daemon) { + if (is_array($daemon) && count($daemon) > 0) { + foreach ($daemon as $sysdaemon) { + printf($mask, $service, $sysdaemon); + } + } else { + if ($daemon == 'x') { + $daemon = '--- skipped ---'; + } + printf($mask, $service, $daemon); + } + } + printf($mask, str_repeat("-", 50), str_repeat("-", 50)); + echo PHP_EOL; + exit(); + } + + $only_daemon = null; + if (array_key_exists("daemon", $this->_args)) { + $only_daemon = $this->_args['daemon']; + } + + if (! empty($decoded_config)) { + $config_dir = FROXLOR_INSTALL_DIR . '/lib/configfiles/'; + $configfiles = new ConfigParser($config_dir . '/' . $decoded_config['distro'] . ".xml"); + $services = $configfiles->getServices(); + $replace_arr = $this->_getReplacerArray(); + + foreach ($services as $si => $service) { + echo PHP_EOL . "--- Configuring: " . strtoupper($si) . " ---" . PHP_EOL . PHP_EOL; + if (! isset($decoded_config[$si]) || $decoded_config[$si] == 'x') { + CmdLineHandler::printwarn("Skipping " . strtoupper($si) . " configuration as desired"); + continue; + } + $daemons = $service->getDaemons(); + foreach ($daemons as $di => $dd) { + // check for desired service + if (($si != 'system' && $decoded_config[$si] != $di) || (is_array($decoded_config[$si]) && ! in_array($di, $decoded_config[$si]))) { + continue; + } + CmdLineHandler::println("Configuring '" . $di . "'"); + + if (! empty($only_daemon) && $only_daemon != $di) { + CmdLineHandler::printwarn("Skipping " . $di . " configuration as desired"); + continue; + } + // run all cmds + $confarr = $dd->getConfig(); + foreach ($confarr as $idx => $action) { + switch ($action['type']) { + case "install": + CmdLineHandler::println("Installing required packages"); + passthru(strtr($action['content'], $replace_arr), $result); + if (strlen($result) > 1) { + echo $result; + } + break; + case "command": + exec(strtr($action['content'], $replace_arr)); + break; + case "file": + if (array_key_exists('content', $action)) { + CmdLineHandler::printwarn("Creating file '" . $action['name'] . "'"); + file_put_contents($action['name'], strtr($action['content'], $replace_arr)); + } elseif (array_key_exists('subcommands', $action)) { + foreach ($action['subcommands'] as $fileaction) { + if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") { + exec(strtr($fileaction['content'], $replace_arr)); + } elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") { + exec(strtr($fileaction['content'], $replace_arr)); + } elseif ($fileaction['type'] == 'file') { + CmdLineHandler::printwarn("Creating file '" . $fileaction['name'] . "'"); + file_put_contents($fileaction['name'], strtr($fileaction['content'], $replace_arr)); + } + } + } + break; + } + } + } + } + CmdLineHandler::printsucc("All services have been configured"); + } else { + CmdLineHandler::printerr("Unable to decode given JSON file"); + } + } + + private function _getReplacerArray() + { + $customer_tmpdir = '/tmp/'; + if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') { + $customer_tmpdir = Settings::Get('system.mod_fcgid_tmpdir'); + } elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.tmpdir') != '') { + $customer_tmpdir = Settings::Get('phpfpm.tmpdir'); + } + + // try to convert namserver hosts to ip's + $ns_ips = ""; + if (Settings::Get('system.nameservers') != '') { + $nameservers = explode(',', Settings::Get('system.nameservers')); + foreach ($nameservers as $nameserver) { + $nameserver = trim($nameserver); + $nameserver_ips = gethostbynamel($nameserver); + if (is_array($nameserver_ips) && count($nameserver_ips) > 0) { + $ns_ips .= implode(",", $nameserver_ips); + } + } + } + + Database::needSqlData(); + $sql = Database::getSqlData(); + + $replace_arr = array( + '' => $sql['user'], + '' => $sql['passwd'], + '' => $sql['db'], + '' => $sql['host'], + '' => isset($sql['socket']) ? $sql['socket'] : null, + '' => Settings::Get('system.hostname'), + '' => Settings::Get('system.ipaddress'), + '' => Settings::Get('system.nameservers'), + '' => $ns_ips, + '' => Settings::Get('system.axfrservers'), + '' => Settings::Get('system.vmail_homedir'), + '' => Settings::Get('system.vmail_uid'), + '' => Settings::Get('system.vmail_gid'), + '' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '', + '' => makeCorrectDir($customer_tmpdir), + '' => makeCorrectDir(FROXLOR_INSTALL_DIR), + '' => makeCorrectDir(Settings::Get('system.bindconf_directory')), + '' => Settings::Get('system.apachereload_command'), + '' => makeCorrectDir(Settings::Get('system.logfiles_directory')), + '' => makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')), + '' => Settings::Get('system.httpgroup') + ); + return $replace_arr; + } + + private function _parseConfig() + { + define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']); + if (! file_exists(FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php')) { + throw new Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?"); + } + if (! file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) { + throw new Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system."); + } + require FROXLOR_INSTALL_DIR . '/lib/classes/database/class.Database.php'; + } + + private function _checkConfigParam($needed = false) + { + if ($needed) { + if (! isset($this->_args["froxlor-dir"])) { + throw new Exception("No configuration given (missing --froxlor-dir parameter?)"); + } elseif (! is_dir($this->_args["froxlor-dir"])) { + throw new Exception("Given --froxlor-dir parameter is not a directory"); + } elseif (! file_exists($this->_args["froxlor-dir"])) { + throw new Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')"); + } elseif (! is_readable($this->_args["froxlor-dir"])) { + throw new Exception("Given froxlor direcotry cannot be read ('" . $this->_args["froxlor-dir"] . "')"); + } + } + } +} + +// give control to command line handler +try { + ConfigServicesCmd::processParameters($argc, $argv); +} catch (Exception $e) { + ConfigServicesCmd::printerr($e->getMessage()); +} diff --git a/install/scripts/switch-server-ip.php b/install/scripts/switch-server-ip.php old mode 100644 new mode 100755