provision_mysql.module 7.1 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
    '#size' => 30,
  );
  
  return $form;
}
/**
 * @} end "ingroup provisionui"
 */


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

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

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

136 137 138

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

function _provision_mysql_database_exists($name) {
144
  return db_result(db_query("SHOW DATABASES LIKE '%s'", $data['site_db_name']));
145 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
}

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");
}

179
function _provision_master_db_url($data = array()) {
180
  return sprintf("mysql://%s:%s@%s/mysql", variable_get('provision_db_user', 'root'), variable_get('provision_db_passwd', 'root'), variable_get('provision_db_host', 'localhost'));
181
}
182

183 184 185 186 187 188 189 190 191 192

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