From 8676df1eff1bacdc53977a9d69cedb20204d92b9 Mon Sep 17 00:00:00 2001 From: tcrivat Date: Tue, 19 Jul 2016 00:02:44 +0200 Subject: [PATCH] php: improvements in handling PHP server configuration - frontend: added the option to enable or disable the debug mode - frontend: optimized the number of calls to the 'get_configuration()' function of the manager when rendering the php page: 1 single call instead of 6 (8 when autoscaling is enabled) - frontend and manager: updated the default values for the configuration parameters to match the ones in PHP v 5.6 - frontend: more sensible available values for parameters (I don't think a 4 GB post size is achievable) - frontend: fixed indentation in PhpPage.php - manager: the initial PHP configuration contains the default values (if not, when PHP is updated, a discrepancy may appear between the default values in the ConPaaS and the ones in PHP, leading to an unwanted effect in which changing a value from the web frontend will also change other values) - cps-tools: shortened the 'get_configuration' command to 'get_config' - cps-tools: human readable output for the 'get_configuration' command - uploading code using git: more informative message from the git push hook (prints the code version id of the code just pushed) --- conpaas-frontend/www/js/hosting.js | 3 +- .../www/lib/service/php/__init__.php | 1 - .../www/lib/ui/page/hosting/PhpPage.php | 582 +++++++++--------- conpaas-services/src/conpaas/core/manager.py | 2 +- .../services/webservers/manager/config.py | 16 +- cps-tools/src/cps_tools/php.py | 20 +- 6 files changed, 325 insertions(+), 299 deletions(-) diff --git a/conpaas-frontend/www/js/hosting.js b/conpaas-frontend/www/js/hosting.js index d6f427f9..4eb7ab85 100644 --- a/conpaas-frontend/www/js/hosting.js +++ b/conpaas-frontend/www/js/hosting.js @@ -69,7 +69,7 @@ conpaas.ui = (function (this_module) { $('.deployactions').toggleClass('invisible'); }); // configuration handlers - $('#conf-maxexec, #conf-memlim, #conf-uploadmaxsize, #conf-postmaxsize').change(function() { + $('#conf-maxexec, #conf-memlim, #conf-uploadmaxsize, #conf-postmaxsize, #conf-debugmode').change(function() { $('#saveconf').removeAttr('disabled'); }); $('#conf-disablefunctions').focus(function() { @@ -230,6 +230,7 @@ conpaas.ui = (function (this_module) { upload_max_filesize: $('#conf-uploadmaxsize').val(), post_max_size: $('#conf-postmaxsize').val(), disable_functions: $('#conf-disablefunctions').val(), + display_errors: $('#conf-debugmode').val(), }}; $(event.target).attr('disabled', 'disabled'); page.updateConfiguration(params, function () { diff --git a/conpaas-frontend/www/lib/service/php/__init__.php b/conpaas-frontend/www/lib/service/php/__init__.php index abedb67f..32c581e6 100644 --- a/conpaas-frontend/www/lib/service/php/__init__.php +++ b/conpaas-frontend/www/lib/service/php/__init__.php @@ -21,7 +21,6 @@ public function __construct($data, $manager) { } } - public function getConfiguration() { if (!$this->isReachable()) { return null; diff --git a/conpaas-frontend/www/lib/ui/page/hosting/PhpPage.php b/conpaas-frontend/www/lib/ui/page/hosting/PhpPage.php index b2afbb33..2754774b 100644 --- a/conpaas-frontend/www/lib/ui/page/hosting/PhpPage.php +++ b/conpaas-frontend/www/lib/ui/page/hosting/PhpPage.php @@ -5,310 +5,328 @@ class PhpPage extends HostingPage { - private function renderSettingsRow($description, $input) { - return - '' - .''.$description.'' - .''.$input.'' - .''; - } + private function renderSettingsRow($description, $input) { + return + '' + .''.$description.'' + .''.$input.'' + .''; + } - private function renderSwVersionInput() { - return - ''; - } + private function renderSwVersionInput() { + return + ''; + } - private function getCurrentExecLimit() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->max_execution_time)) { - // default value - return 30; - } - return intval($conf->phpconf->max_execution_time); - } + private function getCurrentExecLimit($conf) { + if ($conf === null || !isset($conf->phpconf->max_execution_time)) { + // default value + return 30; + } + return intval($conf->phpconf->max_execution_time); + } - public function renderExecTimeOptions() { - static $options = array(30, 60, 120, 180, 240, 300); - $selected = $this->getCurrentExecLimit(); - $html = ''; - return $html; - } + public function renderExecTimeOptions($conf) { + static $options = array(30, 60, 120, 180, 240, 300); + $selected = $this->getCurrentExecLimit($conf); + $html = ''; + return $html; + } - private function getCurrentMemLimit() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->memory_limit)) { - // default value - return '128M'; - } - return $conf->phpconf->memory_limit; - } + private function getCurrentMemLimit($conf) { + if ($conf === null || !isset($conf->phpconf->memory_limit)) { + // default value + return '128M'; + } + return $conf->phpconf->memory_limit; + } - public function renderMemLimitOptions() { - static $options = array('64M', '128M', '256M'); - $selected = $this->getCurrentMemLimit(); - $html = ''; - return $html; - } + public function renderMemLimitOptions($conf) { + static $options = array('64M', '128M', '256M', '512M'); + $selected = $this->getCurrentMemLimit($conf); + $html = ''; + return $html; + } - private function getCurrentUploadMaxSize() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->upload_max_filesize)) { - // default value - return '2M'; - } - return $conf->phpconf->upload_max_filesize; - } + private function getCurrentUploadMaxSize($conf) { + if ($conf === null || !isset($conf->phpconf->upload_max_filesize)) { + // default value + return '2M'; + } + return $conf->phpconf->upload_max_filesize; + } - public function renderUploadMaxSizeOptions() { - static $options = array('2M', '16M', '256M', '1024M', '4096M'); - $selected = $this->getCurrentUploadMaxSize(); - $html = ''; - return $html; - } + public function renderUploadMaxSizeOptions($conf) { + static $options = array('2M', '8M', '16M', '32M', '64M', '128M'); + $selected = $this->getCurrentUploadMaxSize($conf); + $html = ''; + return $html; + } - private function getCurrentPostMaxSize() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->post_max_size)) { - // default value - return '4M'; - } - return $conf->phpconf->post_max_size; - } + private function getCurrentPostMaxSize($conf) { + if ($conf === null || !isset($conf->phpconf->post_max_size)) { + // default value + return '8M'; + } + return $conf->phpconf->post_max_size; + } - public function renderPostMaxSizeOptions() { - static $options = array('4M', '20M', '300M', '1200M', '4192M'); - $selected = $this->getCurrentPostMaxSize(); - $html = ''; - return $html; - } + public function renderPostMaxSizeOptions($conf) { + static $options = array('2M', '8M', '16M', '32M', '64M', '128M'); + $selected = $this->getCurrentPostMaxSize($conf); + $html = ''; + return $html; + } - private function getCurrentDisableFunctions() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->disable_functions)) { - // default value - return 'disk_free_space, diskfreespace, dl, exec, fsockopen, highlight_file, ini_alter, ini_restore, mail, openlog, parse_ini_file, passthru, phpinfo, popen, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, set_time_limit, shell_exec, show_source, symlink, system'; - } - return $conf->phpconf->disable_functions; - } + private function getCurrentDisableFunctions($conf) { + if ($conf === null || !isset($conf->phpconf->disable_functions)) { + // default value + return 'pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority'; + } + return $conf->phpconf->disable_functions; + } - public function renderDisableFunctionsField() { - $value = $this->getCurrentDisableFunctions(); + public function renderDisableFunctionsField($conf) { + $value = $this->getCurrentDisableFunctions($conf); $html = ''; return $html; } - - private function getCurrentCooldownTime() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->cool_down)) { - // default value - return '10'; - } - return $conf->phpconf->cool_down; - } - - public function renderCooldownTimeOptions() { - static $options = array('5','10','15'); - $selected = $this->getCurrentCooldownTime(); - $html = ''; - return $html; - } - - private function getCurrentResponseTime() { - $conf = $this->service->getConfiguration(); - if ($conf === null || !isset($conf->phpconf->response_time)) { - // default value - return '700'; - } - return $conf->phpconf->response_time; - } - - public function renderResponseTimeField() { - $value = $this->getCurrentResponseTime(); + + private function getDebugModeStatus($conf) { + if ($conf === null || !isset($conf->phpconf->display_errors)) { + // default value + return 'Off'; + } + return $conf->phpconf->display_errors; + } + + public function renderDebugModeOptions($conf) { + static $options = array('On', 'Off'); + $selected = $this->getDebugModeStatus($conf); + $html = ''; + return $html; + } + + private function getCurrentCooldownTime($conf) { + if ($conf === null || !isset($conf->phpconf->cool_down)) { + // default value + return '10'; + } + return $conf->phpconf->cool_down; + } + + public function renderCooldownTimeOptions($conf) { + static $options = array('5','10','15'); + $selected = $this->getCurrentCooldownTime($conf); + $html = ''; + return $html; + } + + private function getCurrentResponseTime($conf) { + if ($conf === null || !isset($conf->phpconf->response_time)) { + // default value + return '700'; + } + return $conf->phpconf->response_time; + } + + public function renderResponseTimeField($conf) { + $value = $this->getCurrentResponseTime($conf); $html = ' milliseconds'; return $html; } - public function renderAutoscalingStatus() { - if ($this->service->isAutoscalingON()) { - return ''; - - } - return ''; - } - - public function renderAutoscalingSlider() { - return ''; - } - - public function renderAutoscalingSettingsSection() { - return - '
' - .'
' - .'
Autoscaling settings
' - .'
'.$this->renderAutoscalingStatus() - .'
' - .'
' - .'' - .$this->renderSettingsRow('Maximum acceptable response time', - $this->renderResponseTimeField()) - .$this->renderSettingsRow('Cool down time', - $this->renderCooldownTimeOptions()) - .$this->renderSettingsRow('Autoscaling aggressiveness', - $this->renderAutoscalingSlider()) - .'
' - .'
'; - } - - public function renderSettingsSection() { - return - '
' - .'
' - .'
Settings
' - .'
' - .'
' - .'' - //.$this->renderSettingsRow('Software Version', - // $this->renderSwVersionInput()) - .$this->renderSettingsRow('Maximum script execution time', - $this->renderExecTimeOptions()) - .$this->renderSettingsRow('Memory limit', - $this->renderMemLimitOptions()) - .$this->renderSettingsRow('Maximum allowed size for uploaded files', - $this->renderUploadMaxSizeOptions()) - .$this->renderSettingsRow('Maximum size of POST data', - $this->renderPostMaxSizeOptions()) - .$this->renderSettingsRow('Disabled PHP functions', - $this->renderDisableFunctionsField()) - .'' - .'' - .'' - .'
' - .'' - .'' - .'
' - .'
'; - } + public function renderAutoscalingStatus() { + if ($this->service->isAutoscalingON()) { + return ''; + + } + return ''; + } + + public function renderAutoscalingSlider() { + return ''; + } + + public function renderAutoscalingSettingsSection($conf) { + return + '
' + .'
' + .'
Autoscaling settings
' + .'
'.$this->renderAutoscalingStatus() + .'
' + .'
' + .'' + .$this->renderSettingsRow('Maximum acceptable response time', + $this->renderResponseTimeField($conf)) + .$this->renderSettingsRow('Cool down time', + $this->renderCooldownTimeOptions($conf)) + .$this->renderSettingsRow('Autoscaling aggressiveness', + $this->renderAutoscalingSlider()) + .'
' + .'
'; + } + + public function renderSettingsSection($conf) { + return + '
' + .'
' + .'
Settings
' + .'
' + .'
' + .'' + //.$this->renderSettingsRow('Software Version', + // $this->renderSwVersionInput()) + .$this->renderSettingsRow('Maximum script execution time', + $this->renderExecTimeOptions($conf)) + .$this->renderSettingsRow('Memory limit', + $this->renderMemLimitOptions($conf)) + .$this->renderSettingsRow('Maximum allowed size for uploaded files', + $this->renderUploadMaxSizeOptions($conf)) + .$this->renderSettingsRow('Maximum size of POST data', + $this->renderPostMaxSizeOptions($conf)) + .$this->renderSettingsRow('Disabled PHP functions', + $this->renderDisableFunctionsField($conf)) + .$this->renderSettingsRow('Debug mode', + $this->renderDebugModeOptions($conf)) + .'' + .'' + .'' + .'
' + .'' + .'' + .'
' + .'
'; + } - private function renderCdsForm() { - if ($this->service->isCdnEnabled()) { - return - 'Content delivery is ON using ' - .''.$this->service->getCds()->getName().'. ' - .'You should be able to get the following variables into your application:' - .'
' - .'' - .'$_SERVER[\'CDN_URL_PREFIX\']' - .'' - .'' - .'$_SERVER[\'GEOIP_COUNTRY_CODE\']' - .'' - .'
'; - } - $cdsServices = $this->service->getAvailableCds($this->getUID()); - $options = ''; - $subscribeButton = InputButton('subscribe')->setId('cds_subscribe'); - if (count($cdsServices) > 0) { - foreach ($cdsServices as $cds) { - $options .= ''; - } - } else { - $options = ''; - $subscribeButton->setDisabled(true); - } - // we cannot subscribe to a CDS if we are not running, because we don't - // have an origin address yet - if (!$this->service->isRunning()) { - $subscribeButton - ->setDisabled(true) - ->setTitle('the service must be running'); - } - return - 'Content delivery is OFF. To be able to offload static content ' - .'you may want to subscribe to one of the available CDN services.' - .'
' - .' ' - .$subscribeButton.' ' - .'' - .'
'; - } + private function renderCdsForm() { + if ($this->service->isCdnEnabled()) { + return + 'Content delivery is ON using ' + .''.$this->service->getCds()->getName().'. ' + .'You should be able to get the following variables into your application:' + .'
' + .'' + .'$_SERVER[\'CDN_URL_PREFIX\']' + .'' + .'' + .'$_SERVER[\'GEOIP_COUNTRY_CODE\']' + .'' + .'
'; + } + $cdsServices = $this->service->getAvailableCds($this->getUID()); + $options = ''; + $subscribeButton = InputButton('subscribe')->setId('cds_subscribe'); + if (count($cdsServices) > 0) { + foreach ($cdsServices as $cds) { + $options .= ''; + } + } else { + $options = ''; + $subscribeButton->setDisabled(true); + } + // we cannot subscribe to a CDS if we are not running, because we don't + // have an origin address yet + if (!$this->service->isRunning()) { + $subscribeButton + ->setDisabled(true) + ->setTitle('the service must be running'); + } + return + 'Content delivery is OFF. To be able to offload static content ' + .'you may want to subscribe to one of the available CDN services.' + .'
' + .' ' + .$subscribeButton.' ' + .'' + .'
'; + } - public function renderCdsStatus() { - if ($this->service->isCdnEnabled()) { - return - InputButton('unsubscribe')->setId('cds_unsubscribe') - .' '; - } - return ''; - } + public function renderCdsStatus() { + if ($this->service->isCdnEnabled()) { + return + InputButton('unsubscribe')->setId('cds_unsubscribe') + .' '; + } + return ''; + } - public function renderCdsSection() { - return ''; + public function renderCdsSection() { + return ''; /* - '
' - .'
' - .'' - .'
' - .'Content Delivery' - .'
' - .'
' - .$this->renderCdsStatus() - .'
' - .'
' - .'
' - .'
' - .$this->renderCdsForm() - .'
' - .'
'; + '
' + .'
' + .'' + .'
' + .'Content Delivery' + .'
' + .'
' + .$this->renderCdsStatus() + .'
' + .'
' + .'
' + .'
' + .$this->renderCdsForm() + .'
' + .'
'; */ - } + } - public function renderContent() { - return $this->renderInstancesSection() - .$this->renderCdsSection() - .$this->renderCodeSection() - // .$this->renderAutoscalingSettingsSection() - .$this->renderSettingsSection(); - } + public function renderContent() { + $conf = $this->service->getConfiguration(); + return $this->renderInstancesSection() + .$this->renderCdsSection() + .$this->renderCodeSection() + // .$this->renderAutoscalingSettingsSection($conf) + .$this->renderSettingsSection($conf); + } } diff --git a/conpaas-services/src/conpaas/core/manager.py b/conpaas-services/src/conpaas/core/manager.py index 7555a621..2c340b33 100644 --- a/conpaas-services/src/conpaas/core/manager.py +++ b/conpaas-services/src/conpaas/core/manager.py @@ -950,7 +950,7 @@ def git_push_hook(self, kwargs): if service_id != 0: self.httpsserver.instances[service_id].on_git_push() - return HttpJsonResponse({ 'revision' : revision }) + return HttpJsonResponse('code version: git-%s' % revision) class ManagerException(Exception): diff --git a/conpaas-services/src/conpaas/services/webservers/manager/config.py b/conpaas-services/src/conpaas/services/webservers/manager/config.py index c59627cc..1ebfc65a 100755 --- a/conpaas-services/src/conpaas/services/webservers/manager/config.py +++ b/conpaas-services/src/conpaas/services/webservers/manager/config.py @@ -17,6 +17,7 @@ iaas = None +import copy import time from conpaas.core.node import ServiceNode @@ -65,17 +66,18 @@ def __cmp__(self, other): class PHPINIConfiguration(object): - disable_functions = 'disk_free_space, diskfreespace, dl, exec, '\ - 'fsockopen, highlight_file, ini_alter, ini_restore, mail, openlog, '\ - 'parse_ini_file, passthru, phpinfo, popen, proc_close, '\ - 'proc_get_status, proc_nice, proc_open, proc_terminate, '\ - 'set_time_limit, shell_exec, show_source, symlink, system' + disable_functions = 'pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,'\ + 'pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,'\ + 'pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,'\ + 'pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,'\ + 'pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,'\ + 'pcntl_exec,pcntl_getpriority,pcntl_setpriority' defaults = {'max_execution_time': '30', 'memory_limit': '128M', 'log_errors': 'Off', 'display_errors': 'Off', 'upload_max_filesize': '2M', - 'post_max_size': '4M', + 'post_max_size': '8M', 'disable_functions': disable_functions, } # Do not use $ to match end of string because it matches the end of the @@ -91,7 +93,7 @@ class PHPINIConfiguration(object): } def __init__(self): - self.conf = {} + self.conf = copy.deepcopy(self.defaults) def setAttribute(self, attr_name, value): self.conf[attr_name] = value diff --git a/cps-tools/src/cps_tools/php.py b/cps-tools/src/cps_tools/php.py index 53e4a6d8..9dd33b8b 100644 --- a/cps-tools/src/cps_tools/php.py +++ b/cps-tools/src/cps_tools/php.py @@ -17,7 +17,7 @@ def __init__(self, php_parser, client): WebCmd.__init__(self, php_parser, client, "php", "PHP server sub-commands help") self._add_enable_code() - self._add_get_configuration() + self._add_get_config() self._add_debug() # self._add_enable_autoscaling() # self._add_disable_autoscaling() @@ -53,22 +53,28 @@ def enable_code(self, args): else: print "FAILED!" - # ========== get_configuration - def _add_get_configuration(self): - subparser = self.add_parser('get_configuration', + # ========== get_config + def _add_get_config(self): + subparser = self.add_parser('get_config', help="return the PHP configuration") - subparser.set_defaults(run_cmd=self.get_configuration, parser=subparser) + subparser.set_defaults(run_cmd=self.get_config, parser=subparser) subparser.add_argument('app_name_or_id', help="Name or identifier of an application") subparser.add_argument('serv_name_or_id', help="Name or identifier of a service") - def get_configuration(self, args): + def get_config(self, args): app_id, service_id = self.check_service(args.app_name_or_id, args.serv_name_or_id) conf = self.client.call_manager_get(app_id, service_id, 'get_configuration') - print "%s" % conf + for key, value in conf.iteritems(): + if key == 'phpconf': + print "phpconf:" + for key2, value2 in value.iteritems(): + print "\t%s: %s" % (key2, value2) + else: + print "%s: %s" % (key, value) # ========== debug def _add_debug(self):