provision_mysql.module 7.12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
<?php
/**
 * @file
 *    Mysql provisioning module.
 *
 * The goal of this module is to create mysql databases and user accounts, for sites that are about to be created.
 * It uses the provision API to tie into the right places in the site creation work flow.
 */
 
/**
 * @ingroup provisionui
 * @{
 */
14 15 16 17 18 19 20

 /**
  * Implementation of hook_help().
  */
 function provision_mysql_help($section) {
   switch ($section) {
     case 'admin/help/provision#requirements':
21
       $username = provision_get_script_owner();
22
       $output .= "<ol>";
23
       $command = <<<EOF
24
     [$username@hm2 ~]$ mysql -uroot -pXXXXXXXXX mysql
25 26 27 28 29 30 31 32

     mysql> grant create, drop, grant option  on *.* to 'username_here'@'localhost'
         -> identified by 'mypassword';
     Query OK, 0 rows affected (0.00 sec)

     mysql> flush privileges;
     Query OK, 0 rows affected (0.00 sec)
EOF;
33 34 35 36 37
       $output .= '<li>' . t('<p><strong>Mysql user account capable of creating new databases.</strong>
                To be able to create new sites, the provisioning framework will need to be able to create new databases and users. 
                It is not recommended using the mysql root password for this, but any account with the correct permissions will do.</p>
                <p><strong>To configure:</strong> Log in to your mysql server as root, and type in the following command:
                <pre>@command_text</pre></p>', array('@command_text' => $command)) . '</li>';            
38 39 40 41 42 43
       $output .= "</ol>";
       return $output;
       break;
   }
}

44 45 46 47
/**
 * Implementation of provision_service()
 */
function provision_mysql_provision_service() {
48
  return array("db_server" => t("Mysql database server"));
49 50 51 52 53
}

/**
 * Implementation of provision_configure
 */
54
function provision_mysql_provision_configure($node = null) {
55 56 57
  if (!is_object($node) && ($nid = variable_get('hosting_own_db_server', 0))) {
    $node = node_load($nid);
  }
58 59
  $form['db_type'] = array('#type' => 'hidden', '#value' => 'mysql');
  
60 61 62 63 64
  $form['db_host'] = array(
    '#type' => 'textfield',
    '#title' => t('Mysql server hostname'),
    '#description' => t('The mysql server to connect to.'),
    '#size' => 30,
65
    '#default_value' => ($node->db_host) ? $node->db_host : variable_get('provision_db_host', 'localhost'),
66 67 68 69
    '#maxlength' => 64,
  );
  
  $form['db_user'] = array(
70 71 72 73 74
    '#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,
75
    '#default_value' => ($node->db_user) ? $node->db_user : variable_get('provision_db_user', 'root'),
76 77
    '#maxlength' => 255,
  );
78 79 80
  if ($node->db_passwd) {
    $passwd_description = t('<strong>You have already set a password for this database server.</strong><br />');
  }
81
  $form['db_passwd'] = array(
82 83
    '#type' => 'password_confirm',
    '#required' => (variable_get("provision_db_password", TRUE)) ? FALSE : TRUE,
84
    '#title' => t('Mysql user password'),
85
    '#description' => $passwd_description . t('The user account that will be used to create new mysql users and databases for new sites'),
86 87 88 89 90 91 92 93 94 95 96 97
    '#size' => 30,
    '#maxlength' => 64,
  );
  
  return $form;
}
/**
 * @} end "ingroup provisionui"
 */


function provision_mysql_provision_pre_install($url, &$data) {
98 99 100 101 102 103
  $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.
104 105
  }
  else {
106 107
    $data['site_db_name'] = ereg_replace("^www\.", "", str_replace('-', '_', str_replace(".", "", $url)));
    $data['site_db_username'] = substr($data['site_db_name'], 0, 16);
108 109
  }

110 111
  provision_set_active_db(_provision_master_db_url());
    
112 113
  if ( _provision_mysql_database_exists($data['site_db_name']) ) {
    _provision_mysql_drop_database($data['site_db_name']);
114 115
  }
  
116
  _provision_mysql_create_database($data['site_db_name']);
117
  
118
  if ( !_provision_mysql_database_exists($data['site_db_name']) ) {
119 120
   provision_set_error(PROVISION_DB_ERROR);
   provision_log("error", "Database could not be created.");
121
   provision_set_active_db();
122 123 124
   return FALSE;
  }
  
125 126
  _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']);
127

128 129 130
  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']);
131
  }
132 133
  _provision_mysql_flush();
  provision_set_active_db();
134 135 136
  #TODO : Test to confirm that the database is actually writeable. Taking this on faith for now.
}

137 138 139

function provision_mysql_provision_backup($url, &$data) {
  provision_log("backup", "Generating mysql dump for $url.");
140
  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); 
141
  provision_shell_exec("cd sites/%; tar -rf %s database.sql; rm database.sql", $url, $data['backup_file']);
142 143 144
}

function _provision_mysql_database_exists($name) {
145
  return db_result(db_query("SHOW DATABASES LIKE '%s'", $data['site_db_name']));
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
}

function _provision_mysql_drop_database($name) {
  db_query("DROP DATABASE %s", $name);
}

function _provision_mysql_create_database($name) {
  db_query("CREATE DATABASE %s", $name);  
}

function _provision_mysql_can_create_database() {
  $test = 'provision_test';
  _provision_mysql_create_database($test);
  if (_provision_mysql_database_exists($test)) {
    _provision_mysql_drop_database($test);
    return true;
  }
  return false;
}

function _provision_mysql_grant($name, $username, $password, $host = '') {
  $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 = '') {
  $host = ($host) ? $host : '%';  
  db_query("SET PASSWORD FOR '%s'@'%s' = OLD_PASSWORD('%s')", $username, $host, $password);
}

function _provision_mysql_flush() {
  db_query("FLUSH PRIVILEGES");
}

180 181
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'));
182
}
183

184 185 186 187 188 189 190 191 192 193

/**
 * Implementation of hook_provision_verify
 */
function provision_mysql_provision_verify() {
  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.'));
  }
194 195 196
  else {
    provision_log("message", t('Mysql can create new databases.'));
  }
197
  provision_set_active_db();
198
}