From 83f57f6ef840f913d6bf189c69141d59cc65b272 Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Mon, 11 Feb 2008 16:55:39 +0000 Subject: [PATCH] In progress commit. Remove dependency on date module. Lots of help additions. Added verify step so the back end (mostly) configures itself. Switched templating to use php instead of tokens (needed loops in templates). Turned options to use underscore instead of dash for separation (now consistent). Lots of validation and logging, including strict permission checking. --- provision.inc | 176 ++++++++++++++++++--------- provision.module | 195 ++++++++++++++++++++---------- provision_apache.module | 95 ++++++++------- provision_drupal.module | 102 +++++++++------- provision_mysql.module | 89 +++++--------- templates/apache_vhost.tpl.php | 21 ++++ templates/drupal_settings.tpl.php | 8 ++ 7 files changed, 414 insertions(+), 272 deletions(-) create mode 100644 templates/apache_vhost.tpl.php create mode 100644 templates/drupal_settings.tpl.php diff --git a/provision.inc b/provision.inc index 13d91eaf..fc2510b0 100644 --- a/provision.inc +++ b/provision.inc @@ -81,7 +81,7 @@ function provision_invoke($hook, $url, &$data, $rollback = false) { * @param extra * An associative array containing additional data to be returned from the command. @see provision_stats_stats() */ -function provision_output($url, $data, $extra = null) { +function provision_output($url = null, $data = array(), $extra = null) { $return = $extra; $return['site'] = $data; $return['error_status'] = provision_get_error(); // error code being returned @@ -91,12 +91,13 @@ function provision_output($url, $data, $extra = null) { print serialize($return); } else { - foreach (provision_get_log() as $entry) { - printf("%10s|%10s|%10%s", $entry['timestamp'], $entry['type'], $entry['severity'], $entry['message']); - } - if ($data) { - /** TODO : return a cleanly formatted display of all the necessary information */ - print_r($return); + if ($return) { + if ($output = theme("provision_" . $data['action_type'] . "_output", $url, $return)) { + return $output; + } else { + /** TODO : return a cleanly formatted display of all the necessary information */ + print_r($return); + } } } exit(provision_get_error()); @@ -245,22 +246,22 @@ function provision_get_site_data($url) { global $args; #TODO: Accept serialized string via unix pipe. foreach ($args['options'] as $key => $value) { - if (preg_match("/^site-/", $key)) { + if (preg_match("/^site_/", $key)) { $site_data[$key] = $value; } } - $site_data['site-url'] = $url; - $site_data['site-action-type'] = $args['commands'][1]; - $docroot = variable_get('provision_root', ''); - $site_data['site-document-root'] = ($docroot) ? $docroot . '/webroot' : $_SERVER['DOCUMENT_ROOT']; - $site_data['site-temporary-url'] = str_replace('.', '-', $url) . '.' . variable_get('provision_tempurl_base', $_SERVER['HTTP_HOST']); - $site_data['site-profile'] = ($site_data['site-profile']) ? $site_data['site-profile'] : variable_get('provision_default_profile', 'default'); - $site_data['site-ip'] = variable_get('provision_apache_server_ip', '127.0.0.1'); - $site_data['site-port'] = variable_get('provision_apache_server_ip', 80); + $site_data['site_url'] = $url; + $site_data['site_action_type'] = $args['commands'][1]; + $docroot = drush_get_option("r", $_SERVER['PWD']); + $site_data['site_document_root'] = ($docroot) ? $docroot . '/webroot' : $_SERVER['DOCUMENT_ROOT']; + $site_data['site_profile'] = ($site_data['site_profile']) ? $site_data['site_profile'] : variable_get('provision_default_profile', 'default'); + $site_data['site_ip'] = variable_get('provision_apache_server_ip', '127.0.0.1'); + $site_data['site_port'] = variable_get('provision_apache_server_ip', 80); if ($old_data = provision_load_site_data($url)) { # Merge previously saved data with the new data. This way, old parameters overwrite new ones. $site_data = array_merge(provision_load_site_data($url), $site_data); } + return $site_data; } @@ -303,9 +304,9 @@ function provision_save_site_data($url, $data) { } else { fwrite($fp, " $data['action-id'], + $action = array('id' => $data['action_id'], 'timestamp' => mktime(), - 'action' => $data['site-action-type'], + 'action' => $data['site_action_type'], 'success' => $data['success']); $line = "\n\n\$actions[] = " . var_export($action, TRUE) . ';'; fwrite($fp, $line); @@ -342,16 +343,16 @@ function provision_save_site_data($url, $data) { * A keyed array listing the substitution tokens. Elements should be * in the form of: $list[$type][$token] = $description */ -function provision_token_values($type, $object = null) { - global $args; - switch ($type) { - case 'site': - $values = array_merge(provision_get_site_data($args['commands'][2]), $object) ; - break; - } - return (array) $values; - -} +#function provision_token_values($type, $object = null) { +# global $args; +# switch ($type) { +# case 'site': +# $values = array_merge(provision_get_site_data($args['commands'][2]), $object) ; +# break; +# } +# return (array) $values; +#} + /** * Implementation of hook_token_list(). * @@ -365,18 +366,30 @@ function provision_token_values($type, $object = null) { function provision_token_list($type = 'all') { if ($type == 'site') { /** TODO: Complete the token list to allow the front end to more easily edit the settings. */ - $tokens['site']['site-url'] = t("The domain name used to access the site. This is defaulted to the value used on the command line."); - $tokens['site']['site-db-type'] = t("The type of database server used"); - $tokens['site']['site-db-username'] = t("Username to access database for site"); - $tokens['site']['site-db-password'] = t("Password to access database for site"); - $tokens['site']['site-db-name'] = t("Database name for the site"); - $tokens['site']['site-profile'] = t("Install profile of site"); - $tokens['site']['site-action-type'] = t("What type of action has been used. Only used in conjuction with hosting front end"); - $tokens['site']['site-action-type'] = t("What type of action has been used. Only used in conjuction with hosting front end"); + $tokens['site']['site_url'] = t("The domain name used to access the site. This is defaulted to the value used on the command line."); + $tokens['site']['site_db_type'] = t("The type of database server used"); + $tokens['site']['site_db_username'] = t("Username to access database for site"); + $tokens['site']['site_db_password'] = t("Password to access database for site"); + $tokens['site']['site_db_name'] = t("Database name for the site"); + $tokens['site']['site_profile'] = t("Install profile of site"); + $tokens['site']['site_action_type'] = t("What type of action has been used. Only used in conjuction with hosting front end"); + $tokens['site']['site_action_type'] = t("What type of action has been used. Only used in conjuction with hosting front end"); } return $tokens; } +/** + * Generate the text for a config file using php + */ +function provision_render_config($template, $variables) { + extract($variables, EXTR_SKIP); // Extract the variables to a local namespace + ob_start(); // Start output buffering + eval("?>" . $template); // Generate content + $contents = ob_get_contents(); // Get the contents of the buffer + ob_end_clean(); // End buffering and discard + return $contents; // Return the contents +} + /** * @} End of "defgroup provisiontokens". */ @@ -388,11 +401,6 @@ function provision_token_list($type = 'all') { */ function provision_confirm_drush() { - #confirm that code is running through the command line. - if (php_isapi_name() != 'cli') { - drupal_set_message(t("This function should only be called via the command line Drush utility.")); - return false; - } return true; } @@ -405,28 +413,32 @@ function _provision_backup_path() { return variable_get('provision_backup_path', implode("/" , $parts) . '/backups'); } + /** - * Get the drushrc path of the Provision installation + * Get the base configuration path for the system */ -function _provision_drushrc_path() { - $parts = explode("/", $_SERVER['DOCUMENT_ROOT']); - array_pop($parts); - return variable_get('provision_drushrc_path', implode("/" , $parts) . '/platform.d'); +function _provision_config_path() { + $path = ($_SERVER['PWD']) ? $_SERVER['PWD'] : $_SERVER['DOCUMENT_ROOT']; + $parts = explode("/", $path); + array_pop($parts); + return variable_get('provision_apache_config_path', implode("/" , $parts) . '/config') ; } /** * Get the vhost path of the Provision installation */ function _provision_vhost_path() { - $parts = explode("/", $_SERVER['DOCUMENT_ROOT']); - array_pop($parts); - return variable_get('provision_vhost_path', implode("/" , $parts) . '/vhost.d'); + return _provision_config_path() . '/vhost.d'; } -function _provision_path_can_be_created($path) { - +/** + * Get the drushrc path of the Provision installation + */ +function _provision_drushrc_path() { + return _provision_config_path() . '/drush'; } + /** * Wrapper around drush_shell_exec to provide sprintf functionality with some more safety. */ @@ -456,11 +468,13 @@ function provision_set_active_db($new_db_url = null) { #initialize static if (!$old_db_url) { $old_db_url = $db_url; + $db_url = array(); + $db_url['default'] = $old_db_url; } - + if ($new_db_url) { - $db_url = $new_db_url; - db_set_active(); + $db_url['new'] = $new_db_url; + db_set_active('new'); } else { $db_url = $old_db_url; @@ -485,4 +499,58 @@ function provision_get_script_owner() { function provision_get_group_name() { $info = posix_getgrgid(posix_getgid()); return variable_get('provision_group', $info['name']); +} + +/** + * Perform tests on directory. + * + * Perform test on path, and log error messages / codes on failure. + */ +function provision_check_path($path, $type, $test = true, $succeed_message = '', $fail_message = '', $error_codes = null) { + # The code style is a bit weird here, but it's a bit easier to read this way. + switch ($type) { + case "writeable" : + case "writable" : $value = is_writable($path); + break; + case "exists" : $value = file_exists($path); + break; + case "readable" : $value = is_readable($path); + break; + case "is_dir" : $value = is_dir($path); + break; + case "owner" : $value = fileowner($path); + break; + case "group" : $value = filegroup($path); + break; + case "mkdir" : $value = mkdir($path, 0770, true); + break; + case "chmod" : chmod($path, $test); + $value = sprintf("%o", fileperms($path)); + break; + case "chown" : chown($path, $test); + $value = fileowner($path); + break; + case "chgrp" : chgrp($path, $test); + $value = filegroup($path); + break; + case "unlink" : $value = (file_exists($path)) ? unlink($path) : false; + break; + case "rmdir" : $value = (file_exists($path) && is_dir($path)) ? rmdir($path) : false; + break; + } + $status = ($value == $test) ? true : false; + if ($status) { + if ($succeed_message) { + provision_log("message", $succeed_message); + } + } + else { + if ($error_codes) { + provision_set_error($error_codes); + } + if ($fail_message) { + provision_log("error", $fail_message); + } + } + return $status; } \ No newline at end of file diff --git a/provision.module b/provision.module index 1153094b..7d27aa05 100644 --- a/provision.module +++ b/provision.module @@ -37,10 +37,50 @@ /** Include the provisioning API. */ include_once('provision.inc'); +/** + * Implementation of hook_provision_service + */ function provision_provision_service() { return t("Basic configuration"); } + +/** + * Implementation of hook_perm(). + */ +function provision_perm() { + return array("administer provisioning"); +} + +/** + * @defgroup provisionui Configure provisioning framework. + * @{ + */ + +/** + * Implementation of hook_menu(). + */ +function provision_menu($may_cache = true) { + if ($may_cache) { + $items[] = array( + 'path' => 'admin/settings/provision', + 'title' => t('Provisioning'), + 'description' => t("Configure how new Drupal sites will be provisioned."), + 'callback' => 'drupal_get_form', + 'callback arguments' => array('provision_configure'), + 'access' => user_access('administer provisioning'), + ); + $items[] = array( + 'path' => 'admin/help/provision/requirements', + 'title' => t('Provisioning requirements'), + 'description' => t("Information of how to configure the provisioning system."), + 'callback' => 'provision_help_requirements', + 'type' => MENU_CALLBACK + ); + } + return $items; +} + /** * Implementation of hook_help() */ @@ -60,7 +100,9 @@ function provision_help($section) { $output .= "
"; foreach ($commands as $command => $info) { if (preg_match('/^provision/', $command)) { - $command .= ' ' . implode(' ', (array) key($info['arguments'])); + if (sizeof($info['arguments'])) { + $command .= ' ' . implode(' ', (array) key($info['arguments'])); + } if (sizeof($info['optional arguments'])) { $command .= ' [' . implode('] [', (array) key($info['optional arguments'])) . ']'; } @@ -105,20 +147,23 @@ EOF; username to "@username" and the group to "@group", but you can change these in the provisioning section.

', array("@username" => $username, "@group" => $group, "@provision_link" => url('admin/settings/provision'))) . ''; - $output .= '
  • ' . t('Write access to a directory to store backups. + $output .= '
  • ' . t('

    Write access to a directory to store backups. The drush user needs to be able to maintain the backups repository to ensure that your site is backed up successfully. It is incredibly important that this path is not accessible via the web server, so that no undesirables can get their - hands on your database. The recommended path is directly above your platform path, but it can be anywhere.
    + hands on your database. The recommended path is directly above your platform path, but it can be anywhere.

    - Based on your server configuration we have determined that your path should be @backup_path, - but you can change it change them in the provisioning section
    - To create and configure this directory correctly, please enter the following commands : +

    Based on your server configuration we have determined that your path should be @backup_path, + but you can change this in the provisioning section.

    + To configure: Please enter the following commands :
    @mkdir_cmd
    ',$mkdir_cmd) . '
  • '; $output .= ""; return $output; } } +/** + * Page callback with in depth requirement documentation + */ function provision_help_requirements() { $output .= t('

    Unfortunately, due to the requirements of some of the functionality, significantly more access than is usually allowed on a shared hosting solution is required, and as such, a virtual server or dedicated hosting system will be required to run this system.

    '); @@ -128,7 +173,7 @@ function provision_help_requirements() { $name = module_invoke($module, 'provision_service'); $help = module_invoke($module, 'help', 'admin/help/provision#requirements'); if ($name && $help) { - $output .= '

    ' . t($name) . '

    '; + $output .= '

    ' . t($name) . '

    '; $output .= $help; } } @@ -136,42 +181,6 @@ function provision_help_requirements() { return $output; } -/** - * Implementation of hook_perm(). - */ -function provision_perm() { - return array("administer provisioning"); -} - - -/** - * @defgroup provisionui Configure provisioning framework. - * @{ - */ - -/** - * Implementation of hook_menu(). - */ -function provision_menu($may_cache = true) { - if ($may_cache) { - $items[] = array( - 'path' => 'admin/settings/provision', - 'title' => t('Provisioning'), - 'description' => t("Configure how new Drupal sites will be provisioned."), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('provision_configure'), - 'access' => user_access('administer provisioning'), - ); - $items[] = array( - 'path' => 'admin/help/provision/requirements', - 'title' => t('Provisioning requirements'), - 'description' => t("Information of how to configure the provisioning system."), - 'callback' => 'provision_help_requirements', - 'type' => MENU_CALLBACK - ); - } - return $items; -} /** * Menu callback. @@ -197,15 +206,7 @@ function provision_configure() { * Implementation of provision_configure */ function provision_provision_configure() { - $form['provision_tempurl_base'] = array( - '#type' => 'textfield', - '#required' => TRUE, - '#title' => t('Temporary URL base'), - '#description' => t('Each new domain that gets created gets created with a temporary url base that allows it to be immediately accessible.'), - '#default_value' => variable_get('provision_tempurl_base', $_SERVER['HTTP_HOST']), - '#size' => 40, - '#maxlength' => 255, - ); + $form['provision_user'] = array( '#type' => 'textfield', @@ -224,7 +225,15 @@ function provision_provision_configure() { '#size' => 40, '#maxlength' => 255, ); - + $form['provision_backup_path'] = array( + '#type' => 'textfield', + '#required' => TRUE, + '#title' => t('Path to backup directory'), + '#description' => t('The file system location where backups will be stored.'), + '#default_value' => _provision_backup_path(), + '#size' => 40, + '#maxlength' => 255, + ); return $form; } @@ -241,6 +250,7 @@ function provision_provision_configure() { * Implementation of hook_drush_command(). */ function provision_drush_command() { + $items['provision install'] = array( 'callback' => 'provision_install_cmd', 'arguments' => array('domain.com' => t('The domain of the site to install.')), @@ -251,12 +261,14 @@ function provision_drush_command() { 'callback' => '_provision_synch', 'arguments' => array('domain.com' => t('The domain of the site to synch.')), 'description' => t('Regenerate all the config files for a site.') - ); + ); + $items['provision import'] = array( 'callback' => '_provision_import', 'arguments' => array('domain.com' => t('The domain of the site to import.')), 'description' => t('Turn an already running site into a provisioned site.') ); + $items['provision backup'] = array( 'callback' => '_provision_backup', 'arguments' => array('domain.com' => t('The domain of the site to back up.')), @@ -274,6 +286,12 @@ function provision_drush_command() { 'arguments' => array('domain.com' => t('The domain of the site to disable (only if disabled).')), 'description' => 'Disable a site.' ); + $items['provision verify'] = array( + 'callback' => '_provision_verify', +# 'arguments' => array('domain.com' => t('The domain of the site to disable (only if disabled).')), + 'description' => 'Verify that the provisioning framework is correctly installed.' + ); + /* // Not implemented yet. $items['provision delete'] = array( @@ -322,7 +340,7 @@ function provision_install_cmd($url) { print "Usage: drush.php provision install DOMAIN [OPTIONS]\n"; print "Install a new site for the domain DOMAIN.\n"; print "Example: drush.php provision install mydomain.com --site-db-host localhost\n"; - provision_set_log("error", "Incorrect usage of the provisioning framework"); + provision_log("error", "Incorrect usage of the provisioning framework"); drupal_set_error(PROVISION_FRAMEWORK_ERROR); provision_output($url, $data); } @@ -389,17 +407,17 @@ function _provision_pre_install($url, &$data) { * Boolean denoting whether the provision_invoke rolled back changes made. */ function _provision_install($url, &$data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return; $rolled_back = provision_invoke("install", $url, $data); -# if (!$rolled_back) { + if (!$rolled_back) { _provision_drupal_switch_active_site($url); # Change headers and db info, also backs up _provision_drupal_force_load_modules($url); - _provision_drupal_install_schema($data['site-profile']); + _provision_drupal_install_schema($data['site_profile']); _provision_drupal_force_load_modules(); _provision_drupal_switch_active_site(); # This *should* bring the site back to where we were before installing -# } + + } + return $rolled_back; } @@ -528,13 +546,58 @@ function _provision_import($url) { include_once("sites/$url/settings.php"); $parts = parse_url($db_url); - $data['site-db-type'] = $parts['scheme']; - $data['site-db-user'] = $parts['user']; - $data['site-db-host'] = $parts['host']; - $data['site-db-passwd'] = $parts['pass']; - $data['site-db-name'] = substr($parts['path'], 1); - $data['site-profile'] = $installed_profile; + $data['site_db_type'] = $parts['scheme']; + $data['site_db_user'] = $parts['user']; + $data['site_db_host'] = $parts['host']; + $data['site_db_passwd'] = $parts['pass']; + $data['site_db_name'] = substr($parts['path'], 1); + $data['site_profile'] = $installed_profile; provision_save_site_data($url, $data); provision_output($url, $data); } + + +/** + * Import a running Drupal site into a provisioned site. + * + * This is accomplished by inspecting the settings.php file and generating a site.php file. + * + * @param url + * The url of the site being synched. + * @return + * Output of provision_output() function. + * Will exit with a PROVISION_SITE_NOT_FOUND error if the site does not exist. + */ +function _provision_verify($url = '') { + $path = _provision_config_path(); + $exists = provision_check_path($path, "exists", true , + t("Provision configuration path exists."), + t("Provision configuration path does not exist.")); + if (!$exists) { + $made = provision_check_path($path, "mkdir", true, + t("Provision configuration path has been created."), + t("Provision configuration could not be created."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + } + + provision_check_path($path, "writable", true , + t("Provision configuration path is writable."), + t("Provision configuration path is not writable."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + provision_check_path($path, "chown", provision_get_script_owner(), + t("Changed ownership of %path", array("%path" => $path)), + t("Could not change ownership %path", array("%path" => $path)), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR ); + provision_check_path($path, "chmod", 0700, + t("Changed permissions of %path to %perms", array("%path" => $path, '%perms' => 0700)), + t("Could not change ownership %path to %perms", array("%path" => $path, '%perms' => 0700)), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR ); + + $data = array(); + $rolled_back = provision_invoke("verify", $url, $data); + if ($url) { + provision_save_site_data($url, $data); + } + provision_output($url, $data); +} diff --git a/provision_apache.module b/provision_apache.module index f38ade3b..702c7a3a 100644 --- a/provision_apache.module +++ b/provision_apache.module @@ -92,14 +92,15 @@ function provision_apache_provision_configure() { '#rows' => 5, ); - $default_path = variable_get('provision_root', ereg_replace("/webroot$", "", $_SERVER['DOCUMENT_ROOT'])) . '/vhost.d'; - $form['provision_apache_vhost_path'] = array( + $default_path = variable_get('provision_config_path', ereg_replace("/webroot$", "", $_SERVER['DOCUMENT_ROOT'])) . '/config'; + $form['provision_apache_config_path'] = array( '#type' => 'textfield', - '#title' => t('Path to the directory to store apache configuration files for hosted sites'), + '#title' => t('Path to the directory to store configuration files for hosted sites.'), '#size' => 40, - '#default_value' => variable_get('provision_apache_vhost_path', $default_path), + '#default_value' => variable_get('provision_config_path', $default_path), '#maxlength' => 255, ); + $form['provision_apache_restart_cmd'] = array( '#type' => 'textfield', '#title' => t('Apache restart command'), @@ -116,21 +117,7 @@ function provision_apache_provision_configure() { * The default template provided for the virtual host configuration */ function _provision_apache_default_template() { - return << - ServerAdmin [site-email] - DocumentRoot [site-document-root] - ServerName [site-url] - ServerAlias [site-temporary-url] - ServerAlias www.[site-url] - - # Error handler for Drupal > 4.6.7 - - SetHandler This_is_a_Drupal_security_line_do_not_remove - - - -EOF; + return file_get_contents(drupal_get_path('module', 'provision_apache') . "/templates/apache_vhost.tpl.php"); } /** @@ -176,10 +163,7 @@ function provision_apache_provision_disable($url, &$data) { /** * Implementation of hook_provision_sync */ -function provision_apache_provision_sync($url, &$data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - +function provision_apache_provision_synch($url, &$data) { _provision_apache_create_vhost_config($url, $data); _provision_apache_restart_apache(); } @@ -188,42 +172,30 @@ function provision_apache_provision_sync($url, &$data) { * Delete virtual host file */ function _provision_apache_delete_vhost_config($url, $data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - - $vhost_path = variable_get('provision_apache_vhost_path', 'vhost.d'); - if (file_exists()) { - unlink($vhost_path . '/' . $url); - } + provision_check_path(_provision_vhost_path() . "/$url", "unlink", true, + t("Removed apache virtual host configuration")); } /** * Generate virtual host file */ function _provision_apache_create_vhost_config($url, $data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - - $vhost_path = variable_get('provision_apache_vhost_path', 'vhost.d'); - $file = fopen($vhost_path . '/' . $url, "w"); - if (!$file) { - provision_log("error", "Could not create apache configuration file."); - provision_set_error(PROVISION_WEB_ERROR | PROVISION_PERM_ERROR); - return false; - } - $text = token_replace(variable_get('provision_apache_vhost_template', _provision_apache_default_template()) , 'site', $data); - - fwrite($file, $text); - fclose($file); + $writable = provision_check_path(_provision_vhost_path(), "writable", true , + t("Virtual host configuration path is writable."), + t("Virtual host configuration path is not writable."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + if ($writable) { + $file = fopen(_provision_vhost_path() . '/' . $url, "w"); + $text = provision_render_config(variable_get('provision_apache_vhost_template', _provision_apache_default_template()), $data); + fwrite($file, $text); + fclose($file); + } } /** * Restart Apache */ function _provision_apache_restart_apache() { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - # This is required to be configurable, due to the fact that different hosts might need to do this differently. # TODO : add configuration / test for this $apache_restart_cmd = escapeshellcmd(variable_get('provision_apache_restart_cmd', 'sudo apachectl graceful')); @@ -233,3 +205,32 @@ function _provision_apache_restart_apache() { provision_log("error", "Web server could not be restarted. Changes might not be available until this has been done."); } } + +function provision_apache_provision_verify() { + $path = _provision_vhost_path(); + $exists = provision_check_path($path, "exists", true , + t("Virtual Host configuration path exists."), + t("Virtual Host configuration path does not exist.")); + if (!$exists) { + $made = provision_check_path($path, "mkdir", true, + t("Virtual host configuration path has been created."), + t("Virtual host configuration path could not be created."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + } + else { + $writable = provision_check_path($path, "writable", true , + t("Virtual host configuration path is writable."), + t("Virtual host configuration path is not writable."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + if (!$writable) { + provision_check_path($path, "chown", provision_get_script_owner(), + t("Changed ownership of %path", array("%path" => $path)), + t("Could not change ownership %path", array("%path" => $path)), + PROVISION_PERM_ERROR); + provision_check_path($path, "chmod", 0700, + t("Changed permissions of %path to %perms", array("%path" => $path, '%perms' => 0700)), + t("Could not change ownership %path to %perms", array("%path" => $path, '%perms' => 0700)), + PROVISION_PERM_ERROR ); + } + } +} diff --git a/provision_drupal.module b/provision_drupal.module index 74b38779..5ba22936 100644 --- a/provision_drupal.module +++ b/provision_drupal.module @@ -102,17 +102,7 @@ function provision_drupal_provision_backup($url, $data) { * The default template for the config file */ function _provision_drupal_default_template() { - return << -END; + return file_get_contents(drupal_get_path('module', 'provision_drupal') . '/templates/drupal_settings.tpl.php'); } /** @@ -125,19 +115,16 @@ END; * because the modules might provide additional information about the site. */ function _provision_drupal_create_settings_file($url, &$data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - $fp = fopen("sites/$url/settings.php", "w"); - $text = variable_get('provision_settings_template', _provision_drupal_default_template()); - fwrite($fp, token_replace($text, 'site', $data)); + $text = variable_get('provision_drupal_settings_template', _provision_drupal_default_template()); + fwrite($fp, " '0750', - "sites/$url/files" => '2750', - "sites/$url/files/tmp" => '2770', - "sites/$url/files/images" => '2770', - "sites/$url/files/pictures" => '2770', - "sites/$url/themes" => '2750', - "sites/$url/modules" => '2750', + "sites/$url" => 0750, + "sites/$url/files" => 2750, + "sites/$url/files/tmp" => 2770, + "sites/$url/files/images" => 2770, + "sites/$url/files/pictures" => 2770, + "sites/$url/themes" => 2750, + "sites/$url/modules" => 2750, ); foreach ($paths as $path => $perm) { if (!is_dir($path)) { - mkdir($path); + provision_check_path($path, "mkdir", true, + t("Created %path", array("%path" => $path)), + t("Could not create %path", array("%path" => $path)), + PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); } - # Change the ownership of the files so that they are owned by the user the script is running as, and the - # web server has access to them. - # chown($path, variable_get('provision_user', 'hosting'), variable_get('provision_group', 'apache')); - - # Change the permissions to the optimal settings that were specified. -# system("chmod $perm $path"); + provision_check_path($path, "chown", provision_get_script_owner(), + t("Changed ownership of %path", array("%path" => $path)), + t("Could not change ownership %path", array("%path" => $path)), + PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); + provision_check_path($path, "chgrp", provision_get_group_name(), + t("Changed group ownership of %path", array("%path" => $path)), + t("Could not change group ownership %path", array("%path" => $path)), + PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); + provision_check_path($path, "chmod", $perm, + t("Changed permissions of %path to %perms", array("%path" => $path, '%perms' => $perms)), + t("Could not change ownership %path to %perms", array("%path" => $path, '%perms' => $perms)), + PROVISION_PERM_ERROR | PROVISION_INSTALL_ERROR ); } } @@ -183,9 +176,6 @@ function _provision_drupal_create_directories($url, $profile = null) { * main provisioning site. */ function _provision_drupal_switch_active_site($url = null) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - static $backups; if ($url) { /* Pretend to be the site being installed */ @@ -257,9 +247,6 @@ function _provision_drupal_switch_active_site($url = null) { * Force drupal to load the modules it expects to find on an uninstalled site */ function _provision_drupal_force_load_modules($url = null) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - static $backup_list; if ($url) { $backup_list = module_list(); @@ -284,9 +271,6 @@ function _provision_drupal_force_load_modules($url = null) { * Install the drupal schema and install profile */ function _provision_drupal_install_schema($profile) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - // Load the profile. require_once "./profiles/$profile/$profile.profile"; @@ -325,8 +309,32 @@ function _provision_drupal_install_schema($profile) { /** * implementation of provision_verify */ -function provision_drupal_provision_verify() { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; +function provision_drupal_provision_verify($url, &$data) { + provision_check_path("sites", "writable", true, t("Drupal sites directory is writable by the provisioning script"), + t("Drupal sites directory is not writable by the provisioning script"), PROVISION_PERM_ERROR); + + $path = _provision_drushrc_path(); + $exists = provision_check_path($path, "exists", true , + t("Virtual Host configuration path exists."), + t("Virtual Host configuration path does not exist.")); + if (!$exists) { + $made = provision_check_path($path, "mkdir", true, + t("Virtual host configuration path has been created."), + t("Virtual host configuration path could not be created."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + } + else { + $writable = provision_check_path($path, "writable", true , + t("Virtual host configuration path is writable."), + t("Virtual host configuration path is not writable."), + PROVISION_PERM_ERROR | PROVISION_FRAMEWORK_ERROR); + if (!$writable) { + chmod($path, 0770); + } + } + $profiles = file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS', '.svn'), 0, TRUE, 'name', 0); + $data['profiles'] = $profiles; + $data['modules'] = module_rebuild_cache(); + } \ No newline at end of file diff --git a/provision_mysql.module b/provision_mysql.module index 95e4063e..9d34f1f7 100644 --- a/provision_mysql.module +++ b/provision_mysql.module @@ -52,30 +52,30 @@ function provision_mysql_provision_service() { * Implementation of provision_configure */ function provision_mysql_provision_configure() { - $form['provision_mysql_user'] = array( + $form['provision_db_user'] = array( '#type' => 'textfield', '#required' => TRUE, '#title' => t('Mysql user account'), '#description' => t('The user that will be used to create users and databases for new sites.'), '#size' => 40, - '#default_value' => variable_get('provision_mysql_user', 'root'), + '#default_value' => variable_get('provision_db_user', 'root'), '#maxlength' => 255, ); - $form['provision_mysql_password'] = array( - '#type' => 'password', - '#required' => TRUE, + $form['provision_db_password'] = array( + '#type' => 'password_confirm', + '#required' => (variable_get("provision_db_password", TRUE)) ? FALSE : TRUE, '#title' => t('Mysql user password'), '#description' => t('The user account that will be used to create new mysql users and databases for new sites'), '#size' => 30, '#maxlength' => 64, ); - $form['provision_mysql_host'] = array( + $form['provision_db_host'] = array( '#type' => 'textfield', '#title' => t('Mysql server hostname'), '#description' => t('The mysql server to connect to.'), '#size' => 30, - '#default_value' => variable_get('provision_mysql_host', 'localhost'), + '#default_value' => variable_get('provision_db_host', 'localhost'), '#maxlength' => 64, ); return $form; @@ -86,42 +86,39 @@ function provision_mysql_provision_configure() { function provision_mysql_provision_pre_install($url, &$data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - - $data['site-db-type'] = 'mysql'; # only support innodb. for now. - $data['site-db-host'] = ($data['site-db-host']) ? $data['site-db-host'] : variable_get('provision_mysql_host', 'localhost'); - $data['site-db-passwd'] = user_password(); # generate a random password for use - if ($data['site-id']) { - $data['site-db-name'] = 'site_' . $data['site-id']; - $data['site-db-username'] = $data['site-db-name']; // mysql has some really really stupid rules about who db / usernames, so site id is the safest. + $data['site_db_type'] = 'mysql'; # only support innodb. for now. + $data['site_db_host'] = ($data['site_db_host']) ? $data['site_db_host'] : variable_get('provision_db_host', 'localhost'); + $data['site_db_passwd'] = user_password(); # generate a random password for use + if ($data['site_id']) { + $data['site_db_name'] = 'site_' . $data['site_id']; + $data['site_db_username'] = $data['site_db_name']; // mysql has some really really stupid rules about who db / usernames, so site id is the safest. } else { - $data['site-db-name'] = ereg_replace("^www\.", "", str_replace('-', '_', str_replace(".", "", $url))); - $data['site-db-username'] = substr($data['site-db-name'], 0, 16); + $data['site_db_name'] = ereg_replace("^www\.", "", str_replace('-', '_', str_replace(".", "", $url))); + $data['site_db_username'] = substr($data['site_db_name'], 0, 16); } provision_set_active_db(_provision_master_db_url()); - if ( _provision_mysql_database_exists($data['site-db-name']) ) { - _provision_drop_database($data['site-db-name']); + if ( _provision_mysql_database_exists($data['site_db_name']) ) { + _provision_mysql_drop_database($data['site_db_name']); } - _provision_create_database($data['site-db-name']); + _provision_mysql_create_database($data['site_db_name']); - if ( !_provision_mysql_database_exists($data['site-db-name']) ) { + if ( !_provision_mysql_database_exists($data['site_db_name']) ) { provision_set_error(PROVISION_DB_ERROR); provision_log("error", "Database could not be created."); provision_set_active_db(); return FALSE; } - _provision_mysql_grant($data['site-db-name'], $data['site-db-username'], $data['site-db-passwd']); - _provision_mysql_grant($data['site-db-name'], $data['site-db-username'], $data['site-db-passwd'], $data['site-db-host']); + _provision_mysql_grant($data['site_db_name'], $data['site_db_username'], $data['site_db_passwd']); + _provision_mysql_grant($data['site_db_name'], $data['site_db_username'], $data['site_db_passwd'], $data['site_db_host']); - if ($data['site-mysql-old-passwords']) { - _provision_mysql_old_password($data['site-db-username'], $data['site-db-passwd']); - _provision_mysql_old_password($data['site-db-username'], $data['site-db-passwd'], $data['site-db-host']); + if ($data['site_mysql_old_passwords']) { + _provision_mysql_old_password($data['site_db_username'], $data['site_db_passwd']); + _provision_mysql_old_password($data['site_db_username'], $data['site_db_passwd'], $data['site_db_host']); } _provision_mysql_flush(); provision_set_active_db(); @@ -130,39 +127,24 @@ function provision_mysql_provision_pre_install($url, &$data) { function provision_mysql_provision_backup($url, &$data) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - provision_log("backup", "Generating mysql dump for $url."); - provision_shell_exec("mysqldump -u%s -p%s %s > sites/%s/database.sql", $data['site-db-username'], $data['site-db-passwd'], $data['site-db-name'], $url); + provision_shell_exec("mysqldump -u%s -p%s %s > sites/%s/database.sql", $data['site_db_username'], $data['site_db_passwd'], $data['site_db_name'], $url); provision_shell_exec("cd sites/%; tar -rf %s database.sql; rm database.sql", $url, $data['backup_file']); } function _provision_mysql_database_exists($name) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - - return db_result(db_query("SHOW DATABASES LIKE '%s'", $data['site-db-name'])); + return db_result(db_query("SHOW DATABASES LIKE '%s'", $data['site_db_name'])); } function _provision_mysql_drop_database($name) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - db_query("DROP DATABASE %s", $name); } function _provision_mysql_create_database($name) { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - db_query("CREATE DATABASE %s", $name); } function _provision_mysql_can_create_database() { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - $test = 'provision_test'; _provision_mysql_create_database($test); if (_provision_mysql_database_exists($test)) { @@ -173,30 +155,21 @@ function _provision_mysql_can_create_database() { } function _provision_mysql_grant($name, $username, $password, $host = '') { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - $host = ($host) ? $host : '%'; db_query("GRANT ALL PRIVILEGES ON %s.* TO %s@`%s` IDENTIFIED BY '%s'", $name, $username, $host, $password); } function _provision_mysql_old_password($username, $password, $host = '') { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - $host = ($host) ? $host : '%'; db_query("SET PASSWORD FOR '%s'@'%s' = OLD_PASSWORD('%s')", $username, $host, $password); } function _provision_mysql_flush() { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - db_query("FLUSH PRIVILEGES"); } -function _provision_master_db_url() { - return sprintf("mysql://%s:%s@%s/mysql", variable_get('provision_mysql_user', 'root'), variable_get('provision_mysql_password', 'root'), $data['site-db-host']); +function _provision_master_db_url($data = array()) { + return sprintf("mysql://%s:%s@%s/mysql", variable_get('provision_db_user', 'root'), variable_get('provision_db_password', 'root'), variable_get('provision_db_host', 'localhost')); } @@ -204,13 +177,13 @@ function _provision_master_db_url() { * Implementation of hook_provision_verify */ function provision_mysql_provision_verify() { - #safety mechanism to ensure back end calls are not made via the front end. - if (!provision_confirm_drush()) return null; - provision_set_active_db(_provision_master_db_url()); if (!_provision_mysql_can_create_database()) { provision_set_error(PROVISION_DB_ERROR | PROVISION_FRAMEWORK_ERROR); provision_log('error', t('Unable to create new databases.')); } + else { + provision_log("message", t('Mysql can create new databases.')); + } provision_set_active_db(); } diff --git a/templates/apache_vhost.tpl.php b/templates/apache_vhost.tpl.php new file mode 100644 index 00000000..b53e0582 --- /dev/null +++ b/templates/apache_vhost.tpl.php @@ -0,0 +1,21 @@ + + + ServerAdmin + + DocumentRoot + + ServerName + + + ServerAlias + + + # Error handler for Drupal > 4.6.7 + /sites//files"> + SetHandler This_is_a_Drupal_security_line_do_not_remove + + + \ No newline at end of file diff --git a/templates/drupal_settings.tpl.php b/templates/drupal_settings.tpl.php new file mode 100644 index 00000000..227fe221 --- /dev/null +++ b/templates/drupal_settings.tpl.php @@ -0,0 +1,8 @@ + + $db_url = ''; + $profile = ""; + + # Additional host wide configuration settings. Useful for safely specifying configuration settings. + if (file_exists('includes/global.inc')) { + include_once('includes/global.inc'); + } -- GitLab