/**
* Copyright (C) 2015 Orange
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.francetelecom.clara.cloud.paas.it.services;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import org.postgresql.core.BaseConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.francetelecom.clara.cloud.commons.TechnicalException;
public class DatabaseDuplicatorPostgres {
public static String DUPLICATOR_PGSQL_ELPAASO_INSTANCE = "duplicatorPgElpaasoInstance";
protected static Logger logger = LoggerFactory.getLogger(DatabaseDuplicatorPostgres.class.getName());
String pgdumpPath = null;
String psqlPath = null;
String dbToCopyDBname;
String dbToCopyHostname;
String dbToCopyPort;
String dbToCopyUser;
String dbToCopyPassword;
String dbHostname;
String dbPort;
String dbName;
String dbUser;
String dbPassword;
String datacenter;
/**
* Called by Spring
*/
public void init() throws ClassNotFoundException, SQLException, IOException {
String elpaasoInstance = System.getProperty(DUPLICATOR_PGSQL_ELPAASO_INSTANCE);
if (elpaasoInstance != null) {
logger.info("Using instance '"+elpaasoInstance+"' to copy database");
ResourceBundle bundle = ResourceBundle.getBundle("com.francetelecom.clara.cloud.commons.testconfigurations.credentials-"+datacenter);
setDbToCopyHostname(bundle.getString("test.monitoring.postgresql_db_"+elpaasoInstance+"_hostname"));
setDbToCopyPort(bundle.getString("test.monitoring.postgresql_db_"+elpaasoInstance+"_port"));
setDbToCopyDBname(bundle.getString("test.monitoring.postgresql_db_"+elpaasoInstance+"_dbname"));
setDbToCopyUser(bundle.getString("test.monitoring.postgresql_db_"+elpaasoInstance+"_user"));
setDbToCopyPassword(bundle.getString("test.monitoring.postgresql_db_"+elpaasoInstance+"_password"));
}
else {
throw new TechnicalException("You must define system property "+DUPLICATOR_PGSQL_ELPAASO_INSTANCE);
}
copyDatabase();
}
/**
* Copy data and structure from dbToCopy to db
*/
public void copyDatabase() throws ClassNotFoundException, SQLException, IOException {
if (pgdumpPath != null && psqlPath != null) {
{
final List<String> baseCmds = new ArrayList<String>();
baseCmds.add(pgdumpPath);
baseCmds.add("-h");
baseCmds.add(dbToCopyHostname);
baseCmds.add("-p");
baseCmds.add(dbToCopyPort);
baseCmds.add("-U");
baseCmds.add(dbToCopyUser);
baseCmds.add("-b"); // blog
// baseCmds.add("-v"); // verbose
baseCmds.add("-O");
baseCmds.add("-x");
baseCmds.add("-f");
baseCmds.add("backup-" + dbToCopyDBname + ".sql");
baseCmds.add(dbToCopyDBname);
final ProcessBuilder pb = new ProcessBuilder(baseCmds);
pb.redirectErrorStream(true);
// Set the password
final Map<String, String> env = pb.environment();
env.put("PGPASSWORD", dbToCopyPassword);
try {
logger.info("Backup database: " + baseCmds.toString());
final Process process = pb.start();
final BufferedReader cin = new BufferedReader(new InputStreamReader(process.getInputStream()));
int charin = cin.read();
while (charin != -1) {
System.err.print((char) charin);
charin = cin.read();
}
cin.close();
final int dcertExitCode = process.waitFor();
logger.info(dcertExitCode + " returned by command " + pb.toString());
if (dcertExitCode != 0) {
new TechnicalException("Error during backup (see logs)");
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
throw e;
} catch (InterruptedException ie) {
logger.error(ie.getMessage(), ie);
throw new TechnicalException(ie.getMessage(), ie);
}
}
{
Class.forName("org.postgresql.Driver");
BaseConnection connectionTo = (BaseConnection) DriverManager.getConnection("jdbc:postgresql://" + dbHostname + ":" + dbPort + "/" + dbName,
dbUser, dbPassword);
ResultSet result = connectionTo
.execSQLQuery("SELECT 'DROP TABLE ' || table_name || ' CASCADE ;' FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE';");
while (result.next()) {
logger.debug(result.getString(1));
connectionTo.execSQLUpdate(result.getString(1));
}
result = connectionTo
.execSQLQuery("SELECT 'DROP SEQUENCE ' || sequence_name || ';' FROM information_schema.sequences WHERE sequence_schema='public';");
while (result.next()) {
logger.debug(result.getString(1));
connectionTo.execSQLUpdate(result.getString(1));
}
final List<String> baseCmds = new ArrayList<String>();
baseCmds.add(psqlPath);
baseCmds.add("-h");
baseCmds.add(dbHostname);
baseCmds.add("-p");
baseCmds.add(dbPort);
baseCmds.add("-U");
baseCmds.add(dbUser);
baseCmds.add("-d");
baseCmds.add(dbName);
// baseCmds.add("-q"); // Quiet
baseCmds.add("-f");
baseCmds.add("backup-" + dbToCopyDBname + ".sql");
final ProcessBuilder pb = new ProcessBuilder(baseCmds);
pb.redirectErrorStream(true);
try {
logger.info("Restore database: " + baseCmds.toString());
// Set the password
final Map<String, String> env = pb.environment();
env.put("PGPASSWORD", dbPassword);
final Process process = pb.start();
OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
writer.append(dbPassword);
writer.flush();
final BufferedReader cin = new BufferedReader(new InputStreamReader(process.getInputStream()));
int charin = cin.read();
while (charin != -1) {
System.err.print((char) charin);
charin = cin.read();
}
cin.close();
final int dcertExitCode = process.waitFor();
logger.info(dcertExitCode + " returned by command " + pb.toString());
if (dcertExitCode != 0) {
new TechnicalException("Error during restore (see logs)");
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
throw e;
} catch (InterruptedException ie) {
logger.error(ie.getMessage(), ie);
throw new TechnicalException(ie.getMessage(), ie);
}
}
}
else {
throw new IllegalArgumentException("You must set test.monitoring.pgdump and test.monitoring.psql properties in order to use DatabaseDuplicatorPostgres");
}
}
public void setDbUser(String dbUser) {
this.dbUser = dbUser;
}
public void setDbPassword(String dbPassword) {
this.dbPassword = dbPassword;
}
public void setDbToCopyUser(String dbToCopyUser) {
this.dbToCopyUser = dbToCopyUser;
}
public void setDbToCopyPassword(String dbToCopyPassword) {
this.dbToCopyPassword = dbToCopyPassword;
}
public void setDbToCopyDBname(String dbToCopyDBname) {
this.dbToCopyDBname = dbToCopyDBname;
}
public void setDbToCopyHostname(String dbToCopyHostname) {
this.dbToCopyHostname = dbToCopyHostname;
}
public void setDbToCopyPort(String dbToCopyPort) {
this.dbToCopyPort = dbToCopyPort;
}
public void setDbHostname(String dbHostname) {
this.dbHostname = dbHostname;
}
public void setDbPort(String dbPort) {
this.dbPort = dbPort;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public void setPgdumpPath(String pgdumpPath) {
this.pgdumpPath = pgdumpPath;
}
public void setPsqlPath(String psqlPath) {
this.psqlPath = psqlPath;
}
public void setDatacenter(String datacenter) {
this.datacenter = datacenter;
}
}