View source
<?php
function hosting_wizard_steps($step = null) {
static $steps = array();
global $user;
if (!sizeof($steps)) {
$steps['intro'] = array(
'title' => t("Introduction"),
'heading' => t("Welcome to your new hosting system"),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
if ($user->uid == 1) {
$steps['account'] = array(
'title' => t("User account"),
'heading' => t("Configure your user account"),
'message' => t('An administrator account has been registered for you. Please change your password to continue with the configuration process.'),
);
}
$steps['provision'] = array(
'title' => t("Provisioning"),
'heading' => t("Configure your provisioning framework"),
'message' => t('To be able to create sites using Hostmaster, we need some information about your server.'),
);
$steps['provision/web'] = array(
'title' => t("Web server"),
'heading' => t("Configure your web server"),
'type' => MENU_DEFAULT_LOCAL_TASK,
'message' => t("You will need somewhere to server your files from."),
);
$steps['provision/paths'] = array(
'title' => t("Paths"),
'heading' => t("Configure where to store provisioning data"),
'message' => t('To be able to create sites using Hostmaster, provisioning needs access to the file system.'),
);
$steps['provision/db'] = array(
'title' => t('Database server'),
'heading' => t('Configure your database server'),
'message' => t("You need to be able to create databases and database users."),
);
$steps['hosting'] = array(
'title' => t('Hosting'),
'heading' => t('Set up your hosting framework'),
'message' => t("Finalize your setup by ensuring communication between the front end and back end."),
);
$steps['hosting/features'] = array(
'title' => t('Features'),
'heading' => t('Enable hosting features'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'message' => t("Enable or disable any of the features available."),
);
$steps['hosting/init'] = array(
'title' => t('Initialize'),
'heading' => t('Initialize the hosting system'),
'message' => t("Finalize your setup by ensuring communication between the front end and back end."),
);
$steps['hosting/verify'] = array(
'title' => t('Verify platform'),
'heading' => t('Verify platform settings'),
'message' => t("Verify that the provisioning system is correctly set up, and new sites can be hosted on it."),
);
$steps['hosting/import'] = array(
'title' => t('Import sites'),
'heading' => t('Import your existing sites'),
'message' => t("Details of any existing sites found and imported into Hostmaster."),
);
$steps['complete'] = array(
'title' => t("Complete"),
'heading' => t('Complete your installation'),
'message' => t("Congratulations, you have finished installation of hostmaster. If you have any questions, go to groups.drupal.org/hm2."),
);
}
if ($step && $steps[$step]) {
return $steps[$step];
}
return $steps;
}
function hosting_wizard_menu($may_cache, &$items) {
$items[] = array(
'path' => 'hosting/wizard',
'title' => t('Hosting wizard'),
'description' => t('Configuration wizard'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'hosting_wizard_intro',
),
'type' => MENU_NORMAL_ITEM,
'access' => user_access('access hosting wizard'),
);
if (!$may_cache && sprintf("%s/%s", arg(0), arg(1)) == 'hosting/wizard') {
hosting_wizard_dummy_theme_block();
$steps = hosting_wizard_steps();
$x = 1;
foreach ($steps as $key => $step) {
$form_id = array(
'hosting_wizard_' . str_replace("/", "_", $key),
);
$wizard_items[$key] = array(
'path' => 'hosting/wizard/' . $key,
'title' => $step['title'],
'description' => $step['message'],
'callback' => 'drupal_get_form',
'callback arguments' => $form_id,
'type' => $step['type'] ? $step['type'] : MENU_LOCAL_TASK,
'access' => user_access('access hosting wizard'),
'weight' => $x++,
);
if ($step['type'] == MENU_DEFAULT_LOCAL_TASK) {
$parts = explode("/", $key);
if (sizeof($parts) >= 2) {
$parent = array_shift($parts);
$wizard_items[$parent]['callback arguments'] = $form_id;
}
}
}
$items = array_merge($items, $wizard_items);
}
}
function hosting_wizard_intro() {
$form['introduction']['#value'] = t("<p>I am a configuration wizard designed to help you through configuring the Aegir provisioning system.</p>\n <p>Once properly configured, this system will help you manage your Drupal sites. \n It will even be able to manage them across multiple versions of Drupal and across multiple servers.</p>\n <p>Before we get started with the configuration, please make sure that your system meets the following requirements:</p>");
$form['drupal'] = array(
'#type' => 'requirement_help',
'#requirement' => 'basic_drupal',
);
$form['unix'] = array(
'#type' => 'requirement_help',
'#requirement' => 'basic_unix',
);
$form['server'] = array(
'#type' => 'requirement_help',
'#requirement' => 'basic_server',
);
return hosting_wizard_form('intro', $form);
}
function hosting_wizard_account() {
global $user;
$form = array();
$form['introduction']['#value'] = t("<p>As part of the installation, we have already created an administrator account on this system for you. One of hostmaster's project goals is to configure itself to the best of it's abilities, so that you don't have to. Unfortunately there will be some information that we can't guess.</p>\n <p>To ensure that you are actually able to log back in and use the system, we would appreciate it if you could please change your password to something we didn't generate randomly.</p>");
$form['account']['name'] = array(
'#type' => 'textfield',
'#title' => t('Username'),
'#default_value' => $user->name,
'#maxlength' => USERNAME_MAX_LENGTH,
'#size' => 30,
'#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'),
'#required' => TRUE,
);
$form['account']['#prefix'] = "<div id='hosting-wizard-account-details'>";
$form['account']['#suffix'] = "</div>";
$form['account']['mail'] = array(
'#type' => 'textfield',
'#title' => t('E-mail address'),
'#default_value' => $user->mail,
'#maxlength' => EMAIL_MAX_LENGTH,
'#size' => 30,
'#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
'#required' => TRUE,
);
$form['pass']['#prefix'] = "<div id='hosting-wizard-account-passwd'>";
$form['pass']['#suffix'] = "</div><br style='clear:both' />";
$form['pass']['pass'] = array(
'#type' => 'password_confirm',
'#description' => t('Provide a password for the new account in both fields.'),
'#required' => hosting_wizard_completed('account') ? FALSE : TRUE,
'#size' => 30,
);
$client_help = hosting_node_help('client');
return hosting_wizard_form('account', $form);
}
function hosting_wizard_account_validate($form_id, $values, $form) {
global $user;
_user_edit_validate($user->uid, $values);
}
function hosting_wizard_account_submit($form_id, $values) {
global $user;
user_save($user, $values);
$node = node_load(HOSTING_DEFAULT_CLIENT);
$node->client_name = $values['name'];
$node->email = $values['mail'];
node_save($node);
}
function hosting_wizard_provision() {
$form = array();
$form['introduction']['#value'] = t("<p>The Provisioning framework provides the back end of the system. It does all the nitty gritty server level things, so that you don't have to.</p>\n <p>Provision is very careful about security, and as such has been designed to run under the absolute minimum permissions it needs to accomplish it's job. For the security of your data, Hostmaster will not run unless it is running in this optimally secure configuration.</p>\n <p>Because of these stringently enforced security requirements, it takes a bit longer to set up than would be ideal, however we feel it is a fair tradeoff.</p>");
t("<p>We have tried to collect as much data about our current environment as we can, and provide these as defaults for server configuration. For a lot of cases this works adequately, however we will perform checks on every item, to ensure that it is in working order.</p>\n <p>In some cases, such as file permissions, we are incapable of testing items until the hosting front end has been succesfully configured. If we do find a problem, you will be directed back to this section to modify your configuration.</p>");
return hosting_wizard_form('provision', $form);
}
function hosting_wizard_provision_paths() {
$form = drupal_retrieve_form('web_server_node_form', node_load(HOSTING_OWN_WEB_SERVER));
_hosting_wizard_cleanse_node_form($form);
$own_link = _hosting_node_link(HOSTING_OWN_WEB_SERVER);
$form['script_user']['#type'] = 'value';
$form['web_group']['#type'] = 'value';
$form['title']['#type'] = 'value';
$form['ip_address']['#type'] = 'value';
$form['restart_cmd']['#type'] = 'value';
$form['drush_path_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'drush_path',
'#weight' => 4,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_DISABLED,
);
$form['drush_path']['#weight'] = 5;
$form['config_path_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'config_path',
'#weight' => 9,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_COLLAPSED,
);
$form['config_path']['#weight'] = 10;
$form['backup_path_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'backup_path',
'#weight' => 14,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_COLLAPSED,
);
$form['backup_path']['#weight'] = 15;
$form['httpd_conf'] = array(
'#type' => 'requirement_help',
'#requirement' => 'httpd_conf',
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_ENABLED,
'#weight' => 20,
);
return hosting_wizard_form('provision/paths', $form);
}
function hosting_wizard_provision_paths_submit($form_id, $values) {
$node = node_load(HOSTING_OWN_WEB_SERVER);
$node->config_path = $values['config_path'];
$node->restart_cmd = $values['restart_cmd'];
$node->backup_path = $values['backup_path'];
$node->drush_path = $values['drush_path'];
node_save($node);
}
function hosting_wizard_provision_web() {
$form = drupal_retrieve_form('web_server_node_form', node_load(HOSTING_OWN_WEB_SERVER));
_hosting_wizard_cleanse_node_form($form);
$own_link = _hosting_node_link(HOSTING_OWN_WEB_SERVER);
$form['title']['#type'] = 'value';
$form['ip_address']['#type'] = 'value';
$form['backup_path']['#type'] = 'value';
$form['config_path']['#type'] = 'value';
$form['drush_path']['#type'] = 'value';
$form['drush_path']['#required'] = FALSE;
$form['user_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'user',
'#weight' => 0,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_COLLAPSED,
);
$form['script_user']['#weight'] = 1;
$form['group_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'group',
'#weight' => 10,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_COLLAPSED,
);
$form['web_group']['#weight'] = 11;
$form['restart_cmd_help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'visudo',
'#weight' => 19,
'#summary' => HOSTING_HELP_ENABLED,
'#configuration' => HOSTING_HELP_COLLAPSED,
);
$form['restart_cmd']['#weight'] = 20;
return hosting_wizard_form('provision/web', $form);
}
function hosting_wizard_provision_web_validate($form_id, $values) {
$node = node_load(HOSTING_OWN_WEB_SERVER);
$node->title = $values['title'];
$node->ip_address = $values['ip_address'];
$node->script_user = $values['script_user'];
$node->web_group = $values['web_group'];
$node->restart_cmd = $values['restart_cmd'];
node_validate($node);
}
function hosting_wizard_provision_web_submit($form_id, $values) {
$node = node_load(HOSTING_OWN_WEB_SERVER);
$node->title = $values['title'];
$node->ip_address = $values['ip_address'];
$node->script_user = $values['script_user'];
$node->web_group = $values['web_group'];
$node->restart_cmd = $values['restart_cmd'];
node_save($node);
}
function hosting_wizard_provision_db() {
$form = drupal_retrieve_form('db_server_node_form', node_load(HOSTING_OWN_DB_SERVER));
_hosting_wizard_cleanse_node_form($form);
$own_link = _hosting_node_link(HOSTING_OWN_DB_SERVER);
$form['introduction']['#weight'] = -9;
$form['introduction']['#value'] = t('<p>You need at least one fully functional database server to be able to manage sites.
Luckily, if you can read this, you are already most of the way there. <strong>If the user you specified when first configuring the Drupal can create databases, you probably do not need to change anything here.</strong></p>
<p>This configuration form is actually the !edit_page for the !own_server database server node.
It has however been heavily annotated and slightly simplified for this installation wizard. And while
the wizard can be run multiple times, it won\'t be able to edit any database servers other than the database
this site is running on.</p>', array(
'!own_server' => $own_link,
'!edit_page' => l(t("edit page"), 'node/' . HOSTING_OWN_DB_SERVER . '/edit'),
));
$form['title']['#type'] = 'value';
$form['db_details'] = array(
'#type' => 'fieldset',
'#collapsed' => false,
'#title' => t('Database account details'),
);
$form['db_details']['help'] = array(
'#type' => 'requirement_help',
'#requirement' => 'mysql_user',
'#configuration' => HOSTING_HELP_COLLAPSED,
'#summary' => HOSTING_HELP_COLLAPSED,
);
$form['db_details']['db_user'] = $form['db_user'];
unset($form['db_user']);
$form['db_details']['db_passwd'] = $form['db_passwd'];
unset($form['db_passwd']);
return hosting_wizard_form('provision/db', $form);
}
function hosting_wizard_provision_db_submit($form_id, $values) {
$node = node_load(HOSTING_OWN_DB_SERVER);
$node->title = $values['title'];
$node->db_user = $values['db_user'];
if ($values['db_passwd']) {
$node->db_passwd = $values['db_passwd'];
}
node_save($node);
}
function hosting_wizard_hosting_init() {
$form = array();
$form['intro']['#value'] = t('<p>The hosting framework provides the user interface used to administer your sites.
All components of the managed sites from the database and web servers, to the packages installed
on them, to the sites themselves are represented by the hosting framework as nodes.
This step is going to ensure that it is correctly initialized.</p>');
$form['cron'] = array(
'#type' => 'requirement_help',
'#requirement' => 'hosting_setup',
'#configuration' => HOSTING_HELP_COLLAPSIBLE,
);
if (!variable_get('hosting_dispatch_enabled', FALSE)) {
$form['cron']['#status'] = HOSTING_STATUS_WARNING;
$form['cron']['#message'] = t('Please follow the configuration help below to initialize the system.');
}
elseif (!variable_get('hosting_dispatch_last_run', false)) {
$form['cron']['#status'] = HOSTING_STATUS_ERROR;
$form['cron']['#message'] = t('The dispatch process has not been run. Please follow the instructions below.');
}
else {
$form['cron']['#status'] = HOSTING_STATUS_SUCCESS;
$form['cron']['#message'] = t('The dispatch process has been succesfully executed');
}
return hosting_wizard_form('hosting', $form);
}
function hosting_wizard_hosting_init_validate() {
if (!variable_get('hosting_dispatch_last_run', false)) {
drupal_goto('hosting/wizard/hosting/init');
}
}
function hosting_wizard_hosting_verify() {
$form = array();
$node = hosting_get_most_recent_task(HOSTING_OWN_PLATFORM, 'verify');
$form['provision'] = array(
'#type' => 'requirement_help',
'#requirement' => 'platform',
);
if ($node->task_status == HOSTING_TASK_SUCCESS) {
$form['provision']['#status'] = HOSTING_STATUS_SUCCESS;
$form['provision']['#message'] = t('Your platform has been succesfully configured. You can now create sites.');
$form['import']['#value'] = t('On the next page we will import any existing sites on this platform.');
}
else {
$form['provision']['#status'] = HOSTING_STATUS_ERROR;
$form['provision']['#message'] = t('One of more errors has occurred during platform verification.');
$form['retry_id'] = array(
'#type' => 'hidden',
'#value' => $node->nid,
);
$form['log_tip']['#value'] = t('Underneath is the log output and status of your verification task.
Check your settings on the previous pages of the wizard, and follow the applicable examples from the configuration
tips.');
$view = hosting_task_view($node);
$form['task_status'] = $view->content['status'];
$form['task_status']['#title'] = t('Errors');
$form['last_attempt'] = array(
'#type' => 'item',
'#title' => t('Last attempt'),
'#value' => hosting_format_interval($node->changed),
);
$form['log'] = $view->content['hosting_log'];
$next = t('Check again');
}
return hosting_wizard_form('hosting/verify', $form, $next);
}
function hosting_wizard_hosting_verify_validate() {
$node = hosting_get_most_recent_task(HOSTING_OWN_PLATFORM, 'verify');
if (!($node->task_status == HOSTING_TASK_SUCCESS)) {
drupal_goto('/hosting/wizard/hosting/verify');
}
}
function hosting_wizard_hosting_import() {
$form = array();
$sites = hosting_get_sites_by_status(HOSTING_OWN_PLATFORM, HOSTING_SITE_IMPORTED);
if ($list = hosting_site_list('platform', HOSTING_OWN_PLATFORM)) {
$form['intro']['#value'] = t('<p>Below is a list of sites which were imported into the Hosting framework. Each of these pre-existing sites have had an import task created for them, and will be imported by the task queue.</p>');
$form['list']['#value'] = $list;
}
else {
$form['intro']['#value'] = t('<p>Hosting has not found any sites to import.</p>') . t('<p>In the future, any additional platforms you create will also automatically have existing sites imported, and at any time you can request an verify task on any existing platform to find and import any sites that may have been added manually.</p>');
}
return hosting_wizard_form('hosting/import', $form);
}
function hosting_wizard_hosting_features() {
$form = drupal_retrieve_form('hosting_features_form');
unset($form['buttons']);
return hosting_wizard_form('hosting/features', $form);
}
function hosting_wizard_hosting_features_submit($form_id, $values) {
hosting_features_form_submit($form_id, $values);
}
function hosting_wizard_complete() {
$form['configure']['#value'] .= _hosting_introduction();
return hosting_wizard_form('complete', $form, t('Go to your site'));
}
function _hosting_wizard_cleanse_node_form(&$form) {
$form['log']['#type'] = 'value';
$form['author']['name']['#type'] = 'value';
$form['author']['date']['#type'] = 'value';
$form['options']['status']['#type'] = 'value';
$form['options']['promote']['#type'] = 'value';
$form['options']['sticky']['#type'] = 'value';
$form['options']['revision']['#type'] = 'value';
$form['options']['#type'] = 'markup';
$form['author']['#type'] = 'markup';
unset($form['submit']);
unset($form['preview']);
unset($form['delete']);
}
function hosting_wizard_form($step, $form, $next = null) {
drupal_add_css(drupal_get_path("module", "hosting") . '/hosting.wizard.css');
drupal_add_css(drupal_get_path("module", "hosting") . '/hosting.wizard.js');
hosting_wizard_set_title($step);
$form['#submit']['hosting_wizard_' . str_replace('/', '_', $step) . '_submit'] = array();
$form['#submit']['hosting_wizard_form_submit'] = array();
$form['#prefix'] = '<div id="hosting-wizard-form">';
$form['#suffix'] = '</div>';
$form['step'] = array(
'#type' => 'value',
'#value' => $step,
);
$form['wizard_form'] = array(
'#prefix' => '<div id="hosting-wizard-form-buttons">',
'#suffix' => '</div>',
'#weight' => 100,
);
$info = hosting_wizard_steps(hosting_wizard_next_step());
$text = $next ? $next : ($info['heading'] ? $info['heading'] : t('Continue'));
$form['wizard_form']['submit'] = array(
'#type' => 'submit',
'#value' => $text . ' ->',
);
return $form;
}
function hosting_wizard_form_submit($form_id, $values) {
$values = (array) $values;
variable_set('hosting_wizard_completed_' . $values['step'], mktime());
$next = hosting_wizard_next_step();
if ($next) {
return "hosting/wizard/" . $next;
}
else {
return variable_get('site_frontpage', 'node');
}
}
function hosting_wizard_completed($step) {
return variable_get("hosting_wizard_completed_" . $step, false);
}
function hosting_wizard_set_title($step) {
$info = hosting_wizard_steps($step);
if ($info['heading']) {
drupal_set_title($info['heading']);
}
}
function hosting_wizard_init() {
}
function hosting_wizard_dummy_theme_block() {
$func = $GLOBALS['conf']['theme_default'] . "_blocks";
if (!function_exists($func)) {
drupal_eval("<?php function {$func}() { return ' ';}");
}
}
function hosting_wizard_current_step() {
if (sprintf("%s/%s", arg(0), arg(1)) == 'hosting/wizard') {
$current = trim(str_replace('hosting/wizard', '', $_GET['q']), '/');
if (!$current) {
$current = 'intro';
}
return $current;
}
}
function hosting_wizard_next_step() {
static $static = null;
if (!$static) {
$steps = hosting_wizard_steps();
$names = array_keys($steps);
reset($names);
$current = current($names);
while ($current != hosting_wizard_current_step()) {
$current = next($names);
}
$static = next($names);
if ($steps[$static]['type'] == MENU_DEFAULT_LOCAL_TASK) {
$static = next($names);
}
}
return $static;
}