You are here

hosting_migrate.module in Hostmaster (Aegir) 6

File

modules/hosting/migrate/hosting_migrate.module
View source
<?php

/**
 * @file
 *   Migrate sites between platforms, performing upgrades when necessary.
 */
include_once 'hosting_migrate.batch.inc';

/**
 * Implementation of hook_perm().
 */
function hosting_migrate_perm() {
  return array(
    'create migrate task',
  );
}

/**
 * Implementation of hook_menu().
 */
function hosting_migrate_menu() {

  // TODO: add some security here
  $items['hosting/migrate/compare'] = array(
    'title' => 'Compare packages',
    'page callback' => 'hosting_migrate_comparison',
    'access arguments' => array(
      'create migrate task',
    ),
    'type' => MENU_CALLBACK,
  );

  /*
   $items['node/%hosting_platform_node/task_migrate'] = array(
     'title' => t('Migrate'),
     'description' => t('Migrate sites to a new platform'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('hosting_migrate_platform', 1),
     'access arguments' => array('create migrate task'),
     'type' => MENU_LOCAL_TASK,
     'weight' => ($info['weight']) ? $info['weight'] : 0,
   );
  */
  return $items;
}

/**
 * Implementation of hook_hosting_tasks().
 */
function hosting_migrate_hosting_tasks() {
  $tasks = array();
  $tasks['site']['migrate'] = array(
    'title' => t('Migrate'),
    'description' => t('Move the site to a new platform.'),
    'dialog' => TRUE,
  );
  $tasks['platform']['migrate'] = array(
    'title' => t('Migrate'),
    'description' => t('Migrate sites to a new platform.'),
    'page arguments' => array(
      'hosting_migrate_platform',
      1,
    ),
    'dialog' => TRUE,
  );
  return $tasks;
}

/**
 * Implementation of hook_validate().
 *
 * A site may be migrated if it's URL, Platform or DB server has changed.
 * Only one of these needs to change for a valid migration to be possible.
 */
function hosting_task_migrate_form_validate($form, &$form_state) {
  $migrate_possible = false;
  $site = $form['parameters']['#node'];
  $url = strtolower(trim($form_state['values']['parameters']['new_uri']));

  // domain names are case-insensitive
  if ($url != strtolower(trim($site->title))) {
    $migrate_possible = TRUE;
    if (!_hosting_valid_fqdn($url)) {
      form_set_error('title', t("You have not specified a valid url for this site."));
    }
    if (hosting_site_exists($url)) {
      form_set_error('title', t("The domain name you have specified is not unique."));
    }
  }
  if ($form_state['values']['parameters']['target_platform'] != $site->platform) {
    $migrate_possible = TRUE;
  }
  if ($form_state['values']['parameters']['new_db_server'] != $site->db_server) {
    $migrate_possible = TRUE;
  }
  if (!$migrate_possible) {
    form_set_error('parameters][target_platform', t("To migrate a site you need to modify at least one of the following fields: Domain name, Platform or Database server"));
  }
}

/**
 * Implementation of hook_theme().
 */
function hosting_migrate_theme($existing, $type, $theme, $path) {
  return array(
    'hosting_migrate_comparison' => array(
      'arguments' => array(
        'packages' => NULL,
      ),
    ),
  );
}

/**
 * Implementation of hook_form().
 */
function hosting_task_migrate_form($node) {
  $node->check_profile_migrations = TRUE;
  $valid_options = hosting_site_available_options($node);
  $form['new_uri'] = array(
    '#title' => t('Domain name'),
    '#description' => t("Changing the domain name when migrating effectively 'renames' the site."),
    '#type' => 'textfield',
    '#required' => TRUE,
    '#weight' => '-1',
    '#default_value' => strtolower(trim($node->title)),
  );
  $db_servers = hosting_get_servers('db');
  if (sizeof($db_servers) > 1) {
    $form['new_db_server'] = array(
      '#type' => 'radios',
      '#title' => t('Database server'),
      '#required' => TRUE,
      '#description' => t('The database server the site will use to host its content.'),
      '#options' => $db_servers,
      '#default_value' => $node->db_server,
    );
  }
  else {
    $form['new_db_server'] = array(
      '#type' => 'hidden',
      '#value' => $node->db_server,
    );
  }
  drupal_add_js(drupal_get_path('module', 'hosting_migrate') . '/hosting_migrate.js');
  $packages = array();
  $site_profile = node_load($node->profile);
  $profile_platform_instances = hosting_package_instances_load(array(
    'r.type' => 'platform',
    'n.nid' => $node->profile,
    'h.status' => HOSTING_PLATFORM_ENABLED,
  ));

  // In the list of possible targets, we also include install profiles on platforms that
  // USED to be named the same as our current install profile. Such as the d6 -> d7 rename
  // of the default profile to standard.
  $profile_platform_instances = array_merge($profile_platform_instances, hosting_package_instances_load(array(
    'r.type' => 'platform',
    'p.old_short_name' => $site_profile->short_name,
  )));
  $site_platform = node_load($node->platform);

  // Don't show the current platform if it's locked
  if (!_hosting_platform_is_locked($node->platform)) {
    $form[$node->platform]['target_platform'] = array(
      '#type' => 'radio',
      '#title' => $site_platform->title,
      "#return_value" => $node->platform,
      "#default_value" => $node->platform,
      '#description' => t("Current platform"),
      '#parents' => array(
        'parameters',
        'target_platform',
      ),
    );
  }
  foreach ($profile_platform_instances as $profile_instance) {
    if ($profile_instance->rid != $node->platform && in_array($profile_instance->rid, $valid_options['platform'])) {
      $status = hosting_package_comparison($node->nid, $profile_instance->iid);
      $description = t("Upgrades: !upgrades, Warnings: !missing, Errors: !errors | <a href='!url' class='hosting-package-comparison-link'>Compare platforms</a>", array(
        '!upgrades' => $status['upgrade'],
        '!missing' => $status['missing'] + $status['downgrade'],
        '!errors' => $status['error'],
        '!url' => url('hosting/migrate/compare/' . $node->nid . '/' . $profile_instance->iid),
      ));
      $platform = node_load($profile_instance->rid);
      $form[$platform->nid]['target_platform'] = array(
        '#type' => 'radio',
        '#title' => $platform->title,
        '#parents' => array(
          'parameters',
          'target_platform',
        ),
        "#return_value" => $platform->nid,
        '#description' => $description,
      );
      if ($status['error']) {
        $form[$platform->nid]['target_platform']['#disabled'] = TRUE;
      }
    }
  }
  $form['#node'] = $node;
  return $form;
}

/**
 * Compare package schema versions between the current and target platform in temp tables
 */
function hosting_migrate_comparison($current, $target) {
  $current_tbl = _hosting_package_temporary_table($current);
  $target_tbl = _hosting_package_temporary_table($target);
  $packages = array();
  $result = db_query("SELECT c.nid, c.short_name, \n    c.version as current_version, t.version as target_version,\n    c.version_code as current_version_code, t.version_code as target_version_code,\n    c.schema_version as current_schema, t.schema_version as target_schema, c.status AS enabled \n    FROM %s c LEFT JOIN %s t ON c.nid = t.nid ORDER BY c.status DESC, short_name", $current_tbl, $target_tbl);
  while ($obj = db_fetch_object($result)) {
    if (isset($obj->current_schema) && (int) $obj->target_schema > 0 && (int) $obj->current_schema > (int) $obj->target_schema) {
      $obj->status = 'downgrade';
    }
    elseif ($obj->current_version_code > $obj->target_version_code || is_null($obj->target_version_code)) {
      $obj->status = 'missing';
    }
    elseif ($obj->current_version_code < $obj->target_version_code || $obj->current_schema < $obj->target_schema) {
      $obj->status = 'upgrade';
    }
    else {
      $obj->status = 'same';
    }
    $packages[$obj->nid] = $obj;
  }
  return theme("hosting_migrate_comparison", $packages);
}
function _hosting_migrate_version_display($version, $schema = null, $status = null) {
  $status = !is_null($status) ? $status : 'same';
  if (is_null($version)) {
    $display = 'missing';
  }
  else {
    $display = $version == 0 ? t('Unknown') : $version;
  }
  if ($schema) {
    $display .= " (" . $schema . ")";
  }
  return array(
    'class' => 'hosting-package-' . $status,
    'data' => $display,
  );
}

/**
 * Render a list of compared packages for migration.
 */
function theme_hosting_migrate_comparison($packages) {
  $rows = array();
  $headers = array(
    t("Package"),
    t("Current"),
    t("Target"),
  );
  foreach ($packages as $key => $instance) {
    $row = array();
    $row[] = array(
      'data' => $instance->short_name,
      'class' => 'hosting-status',
    );
    $target_schema = (int) $instance->target_schema == 0 ? $instance->current_schema : $instance->target_schema;
    $row[] = _hosting_migrate_version_display($instance->current_version, $instance->current_schema);
    $row[] = _hosting_migrate_version_display($instance->target_version, $target_schema, $instance->status);
    $rows[] = array(
      'data' => $row,
      'class' => $instance->enabled ? 'hosting-success' : 'hosting-info',
    );
  }
  $options['attributes']['class'] = 'hosting-migrate-comparison-return';
  $link = l(t('Go back'), 'node/' . arg(3) . '/site_migrate', $options);
  return "<div id='hosting-package-comparison'>" . $link . theme('table', $headers, $rows) . $link . "</div>";
}

Functions

Namesort descending Description
hosting_migrate_comparison Compare package schema versions between the current and target platform in temp tables
hosting_migrate_hosting_tasks Implementation of hook_hosting_tasks().
hosting_migrate_menu Implementation of hook_menu().
hosting_migrate_perm Implementation of hook_perm().
hosting_migrate_theme Implementation of hook_theme().
hosting_task_migrate_form Implementation of hook_form().
hosting_task_migrate_form_validate Implementation of hook_validate().
theme_hosting_migrate_comparison Render a list of compared packages for migration.
_hosting_migrate_version_display