/**
 * Loads a complete database dump from a template, and does some update.
 * @uses $CFG
 * @param object $vmoodledata All the Host_form data.
 * @param object $this_as_host The mnet_host record that represents the master.
 * @return bool If true, fixing database from template was sucessful, otherwise false.
 */
function vmoodle_fix_database($vmoodledata, $this_as_host)
{
    global $CFG, $SITE;
    // debug_trace('fixing_database ; IN');
    $manifest = vmoodle_get_vmanifest($vmoodledata->vtemplate);
    $hostname = mnet_get_hostname_from_uri($CFG->wwwroot);
    $cfgipaddress = gethostbyname($hostname);
    // SQL files paths.
    $temporarysetup_path = $CFG->dataroot . '/vmoodle/' . $vmoodledata->vtemplate . '_sql/vmoodle_setup_template.temp.sql';
    // debug_trace('fixing_database ; opening setup script file');
    if (!($FILE = fopen($temporarysetup_path, 'wb'))) {
        print_error('couldnotwritethesetupscript', 'local_vmoodle');
        return false;
    }
    $PREFIX = $vmoodledata->vdbprefix;
    $vmoodledata->description = str_replace("'", "''", $vmoodledata->description);
    // Setup moodle name and description.
    fwrite($FILE, "UPDATE {$PREFIX}course SET fullname='{$vmoodledata->name}', shortname='{$vmoodledata->shortname}', summary='{$vmoodledata->description}' WHERE category = 0 AND id = 1;\n");
    // Setup a suitable cookie name.
    $cookiename = clean_param($vmoodledata->shortname, PARAM_ALPHANUM);
    fwrite($FILE, "UPDATE {$PREFIX}config SET value='{$cookiename}' WHERE name = 'sessioncookie';\n\n");
    // Delete all logs.
    fwrite($FILE, "DELETE FROM {$PREFIX}log;\n\n");
    fwrite($FILE, "DELETE FROM {$PREFIX}mnet_log;\n\n");
    fwrite($FILE, "DELETE FROM {$PREFIX}mnet_session;\n\n");
    // purge mnet logs and sessions
    /*
     * we need :
     * clean host to service
     * clean mnet_hosts unless All Hosts and self record
     * rebind self record to new wwwroot, ip and cleaning public key
     */
    fwrite($FILE, "--\n-- Cleans all mnet tables but keeping service configuration in place \n--\n");
    // We first remove all services. Services will be next rebuild based on template or minimal strategy.
    // We expect all service declaraton are ok in the template DB as the template comes from homothetic installation.
    fwrite($FILE, "DELETE FROM {$PREFIX}mnet_host2service;\n\n");
    // We first remove all services. Services will be next rebuild based on template or minimal strategy.
    fwrite($FILE, "DELETE FROM {$PREFIX}mnet_host WHERE wwwroot != '' AND wwwroot != '{$manifest['templatewwwroot']}';\n\n");
    $vmoodlenodename = str_replace("'", "''", $vmoodledata->name);
    fwrite($FILE, "UPDATE {$PREFIX}mnet_host SET id = 1, wwwroot = '{$vmoodledata->vhostname}', name = '{$vmoodlenodename}' , public_key = '', public_key_expires = 0, ip_address = '{$cfgipaddress}'  WHERE wwwroot = '{$manifest['templatewwwroot']}';\n\n");
    fwrite($FILE, "UPDATE {$PREFIX}config SET value = 1 WHERE name = 'mnet_localhost_id';\n\n");
    // ensure consistance
    fwrite($FILE, "UPDATE {$PREFIX}user SET deleted = 1 WHERE auth = 'mnet' AND username != 'admin';\n\n");
    // disable all mnet users
    /* 
     * this is necessary when using a template from another location or deployment target as
     * the salt may have changed. We would like that all primary admins be the same techn admin.
     */
    $localadmin = get_admin();
    fputs($FILE, "--\n-- Force physical admin with same credentials than in master.  \n--\n");
    fwrite($FILE, "UPDATE {$PREFIX}user SET password = '******' WHERE auth = 'manual' AND username = '******';\n\n");
    if ($vmoodledata->mnet == -1) {
        // NO MNET AT ALL.
        /*
         * we need :
         * disable mnet
         */
        fputs($FILE, "UPDATE {$PREFIX}config SET value = 'off' WHERE name = 'mnet_dispatcher_mode';\n\n");
    } else {
        // ALL OTHER CASES.
        /*
         * we need : 
         * enable mnet
         * push our master identity in mnet_host table
         */
        fputs($FILE, "UPDATE {$PREFIX}config SET value = 'strict' WHERE name = 'mnet_dispatcher_mode';\n\n");
        fputs($FILE, "INSERT INTO {$PREFIX}mnet_host (wwwroot, ip_address, name, public_key, applicationid, public_key_expires) VALUES ('{$this_as_host->wwwroot}', '{$this_as_host->ip_address}', '{$SITE->fullname}', '{$this_as_host->public_key}', {$this_as_host->applicationid}, '{$this_as_host->public_key_expires}');\n\n");
        fputs($FILE, "--\n-- Enable the service 'mnetadmin, sso_sp and sso_ip' with host which creates this host.  \n--\n");
        fputs($FILE, "INSERT INTO {$PREFIX}mnet_host2service VALUES (null, (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'), (SELECT id FROM {$PREFIX}mnet_service WHERE name LIKE 'mnetadmin'), 1, 0);\n\n");
        fputs($FILE, "INSERT INTO {$PREFIX}mnet_host2service VALUES (null, (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'), (SELECT id FROM {$PREFIX}mnet_service WHERE name LIKE 'sso_sp'), 1, 0);\n\n");
        fputs($FILE, "INSERT INTO {$PREFIX}mnet_host2service VALUES (null, (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'), (SELECT id FROM {$PREFIX}mnet_service WHERE name LIKE 'sso_idp'), 0, 1);\n\n");
        fputs($FILE, "--\n-- Insert master host user admin.  \n--\n");
        fputs($FILE, "INSERT INTO {$PREFIX}user (auth, confirmed, policyagreed, deleted, mnethostid, username, password) VALUES ('mnet', 1, 0, 0, (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'), 'admin', '');\n\n");
        fputs($FILE, "--\n-- Links role and capabilites for master host admin.  \n--\n");
        $roleid = "(SELECT id FROM {$PREFIX}role WHERE shortname LIKE 'manager')";
        $contextid = 1;
        $userid = "(SELECT id FROM {$PREFIX}user WHERE auth LIKE 'mnet' AND username = '******' AND mnethostid = (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'))";
        $timemodified = time();
        $modifierid = $userid;
        $component = "''";
        $itemid = 0;
        $sortorder = 1;
        fputs($FILE, "INSERT INTO {$PREFIX}role_assignments(id,roleid,contextid,userid,timemodified,modifierid,component,itemid,sortorder) VALUES (0, {$roleid}, {$contextid}, {$userid}, {$timemodified}, {$modifierid}, {$component}, {$itemid}, {$sortorder});\n\n");
        fputs($FILE, "--\n-- Add new network admin to local siteadmins.  \n--\n");
        $adminidsql = "(SELECT id FROM {$PREFIX}user WHERE auth LIKE 'mnet' AND username = '******' AND mnethostid = (SELECT id FROM {$PREFIX}mnet_host WHERE wwwroot LIKE '{$this_as_host->wwwroot}'))";
        fputs($FILE, "UPDATE {$PREFIX}config SET value = CONCAT(value, ',', {$adminidsql}) WHERE name = 'siteadmins';\n");
        fputs($FILE, "--\n-- Create a disposable key for renewing new host's keys.  \n--\n");
        fputs($FILE, "INSERT INTO {$PREFIX}config (name, value) VALUES ('bootstrap_init', '{$this_as_host->wwwroot}');\n");
    }
    fclose($FILE);
    // debug_trace('fixing_database ; setup script written');
    $sqlcmd = vmoodle_get_database_dump_cmd($vmoodledata);
    // Make final commands to execute, depending on the database type.
    $import = $sqlcmd . $temporarysetup_path;
    // Prints log messages in the page and in 'cmd.log'.
    // debug_trace("fixing_database ; executing $import ");
    // Ensure utf8 is correctly handled by php exec().
    // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input
    // this is required only with PHP exec through a web access.
    if (!CLI_SCRIPT) {
        putenv('LANG=en_US.utf-8');
    }
    // Execute the command.
    exec($import, $output, $return);
    // debug_trace(implode("\n", $output)."\n");
    // Remove temporary files.
    //    if(!unlink($temporarysetup_path)){
    //        return false;
    //    }
    // End.
    return true;
}
Example #2
0
/**
 * Loads a complete database dump from a template, and does some update.
 * @uses $CFG, $DB
 * @param object $vmoodledata All the Host_form data.
 * @param array $outputfile The variables to inject in setup template SQL.
 * @return bool If true, loading database from template was sucessful, otherwise false.
 */
function vmoodle_load_database_from_template($vmoodledata)
{
    global $CFG, $DB;
    // Gets the HTTP adress scheme (http, https, etc...) if not specified.
    if (is_null(parse_url($vmoodledata->vhostname, PHP_URL_SCHEME))) {
        $vmoodledata->vhostname = parse_url($CFG->wwwroot, PHP_URL_SCHEME) . '://' . $vmoodledata->vhostname;
    }
    $manifest = vmoodle_get_vmanifest($vmoodledata->vtemplate);
    $hostname = mnet_get_hostname_from_uri($CFG->wwwroot);
    $description = $DB->get_field('course', 'fullname', array('id' => SITEID));
    $cfgipaddress = gethostbyname($hostname);
    if ($vmoodledata->vdbtype == 'sqlsrv') {
        if ($manifest['templatevdbprefix'] != $vmoodledata->vdbprefix) {
            print_error('changeprefixforsqlsrvnotimplemented', 'local_vmoodle');
            return false;
        }
        $pgm = !empty($CFG->local_vmoodle_cmd_sqlsrvmount) ? stripslashes($CFG->local_vmoodle_cmd_sqlsrvmount) : false;
        $pgm = str_replace("/", DIRECTORY_SEPARATOR, $pgm);
        // Take the host given (SQL host specified can be different)
        if (strstr($vmoodledata->vdbhost, ':') !== false) {
            list($vmoodledata->vdbhost, $vmoodledata->vdbport) = split(':', $vmoodledata->vdbhost);
        }
        //$dbsource = substr($vmoodledata->vtemplate, strrpos($vmoodledata->vtemplate, "_"));
        $dbsource = vmoodle_get_dbname_for_templatename($vmoodledata->vtemplate);
        if (!$dbsource) {
            print_error('templatenotfound', 'local_vmoodle');
        }
        $cmd = "-vhost {$vmoodledata->vdbhost} -vusr {$vmoodledata->vdblogin} -vpwd {$vmoodledata->vdbpass} -vpath {$CFG->dataroot}/vmoodle/{$vmoodledata->vtemplate}_sql -dbsource {$dbsource} -dbtarget {$vmoodledata->vdbname}";
        $cmd = "powershell {$pgm} {$cmd}";
        // Prints log messages in the page and in 'cmd.log'.
        if ($LOG = fopen(dirname("{$CFG->dataroot}/vmoodle/{$vmoodledata->vtemplate}_sql") . '/cmd.log', 'a')) {
            fwrite($LOG, $cmd . "\n");
        }
        // Executes the SQL command.
        exec($cmd, $execoutput, $returnvalue);
        if ($LOG) {
            foreach ($execoutput as $execline) {
                fwrite($LOG, $execline . "\n");
            }
            fwrite($LOG, $returnvalue . "\n");
            fclose($LOG);
        }
    } else {
        // SQL files paths.
        $templatesqlfile_path = $CFG->dataroot . '/vmoodle/' . $vmoodledata->vtemplate . '_sql/vmoodle_master.sql';
        // Create temporaries files for replacing data.
        $temporarysqlfile_path = $CFG->dataroot . '/vmoodle/' . $vmoodledata->vtemplate . '_sql/vmoodle_master.temp.sql';
        // Retrieves files contents into strings.
        // debug_trace("load_database_from_dump : getting sql content");
        if (!($dumptxt = file_get_contents($templatesqlfile_path))) {
            print_error('nosql', 'local_vmoodle');
            return false;
        }
        // Change the tables prefix if required prefix does not match manifest's one (sql template).
        if ($manifest['templatevdbprefix'] != $vmoodledata->vdbprefix) {
            $dumptxt = str_replace($manifest['templatevdbprefix'], $vmoodledata->vdbprefix, $dumptxt);
        }
        // Fix special case on adodb_logsql table if prefix has a schema part (PostgreSQL).
        if (preg_match('/(.*)\\./', $vmoodledata->vdbprefix, $matches)) {
            // We have schema, thus relocate adodb_logsql table within schema.
            $dumptxt = str_replace('adodb_logsql', $matches[1] . '.adodb_logsql', $dumptxt);
        }
        // Puts strings into the temporary files.
        // debug_trace("load_database_from_dump : writing modified sql");
        if (!file_put_contents($temporarysqlfile_path, $dumptxt)) {
            print_error('nooutputfortransformedsql', 'local_vmoodle');
            return false;
        }
        // Creates the new database before importing the data.
        $DB->create_database($vmoodledata->vdbhost, $vmoodledata->vdblogin, $vmoodledata->vdbpass, $vmoodledata->vdbname);
        $sqlcmd = vmoodle_get_database_dump_cmd($vmoodledata);
        // Make final commands to execute, depending on the database type.
        $import = $sqlcmd . $temporarysqlfile_path;
        // Execute the command.
        // debug_trace("load_database_from_dump : executing feeding sql");
        if (!defined('CLI_SCRIPT')) {
            putenv('LANG=en_US.utf-8');
        }
        // Ensure utf8 is correctly handled by php exec().
        // @see http://stackoverflow.com/questions/10028925/call-a-program-via-shell-exec-with-utf-8-text-input
        exec($import, $output, $return);
        // debug_trace(implode("\n", $output)."\n");
        // Remove temporary files.
        //    if(!unlink($temporarysqlfile_path))){
        //        return false;
        //    }
        // End.
        // debug_trace("load_database_from_dump : OUT");
    }
    return true;
}