diff --git a/server/src/com/cloud/upgrade/DatabaseCreator.java b/server/src/com/cloud/upgrade/DatabaseCreator.java index 5dde0578b03..99e63a673c0 100755 --- a/server/src/com/cloud/upgrade/DatabaseCreator.java +++ b/server/src/com/cloud/upgrade/DatabaseCreator.java @@ -18,14 +18,14 @@ */ package com.cloud.upgrade; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import com.cloud.utils.PropertiesUtil; @@ -36,39 +36,128 @@ import com.cloud.utils.db.Transaction; // Creates the CloudStack Database by using the 4.0 schema and apply // upgrade steps to it. public class DatabaseCreator { + protected static void printHelp(String cmd) { System.out.println( - "DatabaseCreator creates the database schema by removing the \n" + + "\nDatabaseCreator creates the database schema by removing the \n" + "previous schema, creating the schema, and running \n" + "through the database updaters."); - System.out.println("Usage: " + cmd + " [db.properties files] [schema.sql files] [database upgrade class]"); + System.out.println("Usage: " + cmd + " [options] [db.properties file] [schema.sql files] [database upgrade class]\nOptions:" + + "\n --database=a,b comma separate databases to initialize, use the db name in db.properties defined as db.xyz.host, xyz should be passed" + + "\n --rootpassword=password, by default it will try with an empty password" + + "\n --dry or -d, this would not run any process, just does a dry run" + + "\n --verbose or -v to print running sql commands, by default it won't print them" + + "\n --help or -h for help"); + } + + private static boolean fileExists(String file) { + File f = new File(file); + if (!f.exists()) + System.out.println("========> WARNING: Provided file does not exist: " + file); + return f.exists(); + } + + private static void runScript(Connection conn, Reader reader, String filename, boolean verbosity) { + ScriptRunner runner = new ScriptRunner(conn, false, true, verbosity); + try { + runner.runScript(reader); + } catch (IOException e) { + System.err.println("Unable to read " + filename + ": " + e.getMessage()); + System.exit(1); + } catch (SQLException e) { + System.err.println("Unable to execute " + filename + ": " + e.getMessage()); + System.exit(1); + } + } + + private static void runQuery(String host, String port, String rootPassword, String query, boolean dryRun) { + System.out.println("============> Running query: " + query); + Connection conn = null; + try { + conn = DriverManager.getConnection(String.format("jdbc:mysql://%s:%s/", host, port), + "root", rootPassword); + Statement stmt = conn.createStatement(); + if (!dryRun) + stmt.executeUpdate(query); + conn.close(); + } catch (SQLException e) { + System.out.println("SQL exception in trying initDB: " + e); + System.exit(1); + } + } + + private static void initDB(String dbPropsFile, String rootPassword, String[] databases, boolean dryRun) { + Properties dbProperties = new Properties(); + try { + dbProperties.load(new FileInputStream(new File(dbPropsFile))); + } catch (IOException e) { + System.out.println("IOError: unable to load/read db properties file: " + e); + System.exit(1); + } + + for (String database: databases) { + String host = dbProperties.getProperty(String.format("db.%s.host", database)); + String port = dbProperties.getProperty(String.format("db.%s.port", database)); + String username = dbProperties.getProperty(String.format("db.%s.username", database)); + String password = dbProperties.getProperty(String.format("db.%s.password", database)); + String dbName = dbProperties.getProperty(String.format("db.%s.name", database)); + System.out.println(String.format("========> Initializing database=%s with host=%s port=%s username=%s password=%s", dbName, host, port, username, password)); + + List queries = new ArrayList(); + queries.add(String.format("drop database if exists `%s`", dbName)); + queries.add(String.format("create database `%s`", dbName)); + queries.add(String.format("GRANT ALL ON %s.* to '%s'@`localhost` identified by '%s'", dbName, username, password)); + queries.add(String.format("GRANT ALL ON %s.* to '%s'@`%%` identified by '%s'", dbName, username, password)); + + for (String query: queries) { + runQuery(host, port, rootPassword, query, dryRun); + } + } } public static void main(String[] args) { - List dbPropFiles = new ArrayList(); + String dbPropsFile = ""; List sqlFiles = new ArrayList(); List upgradeClasses = new ArrayList(); + String[] databases = new String[] {}; + String rootPassword = ""; + boolean verbosity = false; + boolean dryRun = false; + // Process opts for (String arg: args) { - if (arg.endsWith(".sql")) { + if (arg.equals("--help") || arg.equals("-h")) { + printHelp("DatabaseCreator"); + System.exit(0); + } else if (arg.equals("--verbose") || arg.equals("-v")) { + verbosity = true; + } else if (arg.equals("--dry") || arg.equals("-d")) { + dryRun = true; + } else if (arg.startsWith("--rootpassword=")) { + rootPassword = arg.substring(arg.lastIndexOf("=") + 1, arg.length()); + } else if (arg.startsWith("--database=")) { + databases = arg.substring(arg.lastIndexOf("=") + 1, arg.length()).split(","); + } else if (arg.endsWith(".sql")) { sqlFiles.add(arg); - } else if (arg.endsWith(".properties") || arg.endsWith("properties.override")) { - dbPropFiles.add(arg); + } else if (arg.endsWith(".properties")) { + if (!dbPropsFile.endsWith("properties.override") && fileExists(arg)) + dbPropsFile = arg; + } else if (arg.endsWith("properties.override")) { + if (fileExists(arg)) + dbPropsFile = arg; } else { upgradeClasses.add(arg); } } - if ((dbPropFiles.size() == 0) + if ((dbPropsFile.isEmpty()) || (sqlFiles.size() == 0) && upgradeClasses.size() == 0) { printHelp("DatabaseCreator"); System.exit(1); } - // Process db.properties files - for (String dbPropFile: dbPropFiles) { - - } + Transaction.initDataSource(dbPropsFile); + initDB(dbPropsFile, rootPassword, databases, dryRun); // Process sql files for (String sqlFile: sqlFiles) { @@ -79,12 +168,9 @@ public class DatabaseCreator { System.exit(1); } - System.out.println("=============> Processing SQL file at " + sqlScript.getAbsolutePath()); - + System.out.println("========> Processing SQL file at " + sqlScript.getAbsolutePath()); Connection conn = Transaction.getStandaloneConnection(); try { - - ScriptRunner runner = new ScriptRunner(conn, false, true); FileReader reader = null; try { reader = new FileReader(sqlScript); @@ -92,15 +178,8 @@ public class DatabaseCreator { System.err.println("Unable to read " + sqlFile + ": " + e.getMessage()); System.exit(1); } - try { - runner.runScript(reader); - } catch (IOException e) { - System.err.println("Unable to read " + sqlFile + ": " + e.getMessage()); - System.exit(1); - } catch (SQLException e) { - System.err.println("Unable to execute " + sqlFile + ": " + e.getMessage()); - System.exit(1); - } + if (!dryRun) + runScript(conn, reader, sqlFile, verbosity); } finally { try { conn.close(); @@ -112,7 +191,7 @@ public class DatabaseCreator { // Process db upgrade classes for (String upgradeClass: upgradeClasses) { - System.out.println("=============> Processing upgrade: " + upgradeClass); + System.out.println("========> Processing upgrade: " + upgradeClass); Class clazz = null; try { clazz = Class.forName(upgradeClass);