/*
* Copyright (c) 2010-2012 Thiago T. Sá
*
* This file is part of CloudReports.
*
* CloudReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CloudReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For more information about your rights as a user of CloudReports,
* refer to the LICENSE file or see <http://www.gnu.org/licenses/>.
*/
package cloudreports.reports;
import cloudreports.business.SettingBusiness;
import cloudreports.dao.CustomerRegistryDAO;
import cloudreports.dao.DatacenterRegistryDAO;
import cloudreports.dao.SettingDAO;
import cloudreports.database.HibernateUtil;
import cloudreports.extensions.PowerDatacenter;
import cloudreports.gui.reports.resources.images.Images;
import cloudreports.gui.reports.resources.js.JS;
import cloudreports.models.CustomerRegistry;
import cloudreports.models.DatacenterRegistry;
import cloudreports.utils.ElapsedTime;
import cloudreports.utils.FileIO;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.cloudbus.cloudsim.DatacenterBroker;
/**
* Provides methods to generate a simulation report.
* The reports are generated as a folder containing several HTML files and a
* raw data file.
*
* @author Thiago T. Sá
* @since 1.0
*/
public class Report {
/** The report's base directory. */
private static String baseDirectory;
/** Indicates whether HTML reports must be generated. */
private static boolean htmlReportsEnabled;
/** Indicates whether raw data reports must be generated. */
private static boolean rawDataReportsEnabled;
/**
* Generates a full report.
*
* @param datacentersList the list of simulated datacenters.
* @param brokersList the list of simulated brokers.
* @param elapsedTime the duration of the simulation.
* @since 1.0
*/
public static void generateReport(List<PowerDatacenter> datacentersList, List<DatacenterBroker> brokersList,
ElapsedTime elapsedTime) throws IOException, URISyntaxException {
baseDirectory = FileIO.getPathOfExecutable();
int simulationId = SettingBusiness.getCurrentSimulation();
baseDirectory += "reports/" + HibernateUtil.getActiveDatabase() + "/report" + simulationId;
SettingDAO sDAO = new SettingDAO();
htmlReportsEnabled = SettingBusiness.isHtmlReportsEnabled();
rawDataReportsEnabled = SettingBusiness.isRawDataReportsEnabled();
createDirectoryTree();
if(htmlReportsEnabled) createOverallReport(datacentersList, brokersList, elapsedTime);
createDatacentersReports(datacentersList, brokersList);
createCustomersReports(brokersList);
if(htmlReportsEnabled) createLogReport(datacentersList, brokersList);
}
/**
* Creates the report's directory tree.
*
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createDirectoryTree() throws IOException, URISyntaxException {
if(htmlReportsEnabled) createHtmlDirectoryTree();
if(rawDataReportsEnabled) createRawDataDirectoryTree();
}
/**
* Creates the raw data report's directory tree.
*
* @throws IOException if any of the directories or files could
* not be created.
* @since 1.1
*/
private static void createRawDataDirectoryTree() throws IOException {
File tempDir = new File(baseDirectory + "/raw");
tempDir.mkdirs();
File tempRawData = new File(baseDirectory + "/raw/rawData.crd");
if(tempRawData.exists()) tempRawData.delete();
tempRawData.createNewFile();
}
/**
* Creates the HTML report's directory tree.
*
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createHtmlDirectoryTree() throws URISyntaxException, IOException {
File tempDir = new File(baseDirectory + "/provider");
tempDir.mkdirs();
tempDir = new File(baseDirectory + "/customers");
tempDir.mkdir();
tempDir = new File(baseDirectory + "/log");
tempDir.mkdir();
//Create the CSS directory and file
tempDir = new File(baseDirectory + "/css");
tempDir.mkdir();
String tempString = FileIO.readStringFromResource("cloudreports/gui/reports/resources/css/style.css");
FileIO.writeStringToFile(baseDirectory + "/css/style.css", tempString);
//Create the images directory and files
tempDir = new File(baseDirectory + "/images");
tempDir.mkdir();
String[] tempFilesArray = FileIO.getResourceListing(Images.class, "cloudreports/gui/reports/resources/images/");
for(String tempFile : tempFilesArray) {
if (tempFile.isEmpty()) continue;
byte[] tempBytes = FileIO.readBytesFromFile("cloudreports/gui/reports/resources/images/" + tempFile);
FileIO.writeBytesToFile(baseDirectory + "/images/" + tempFile, tempBytes);
}
//Create the js directory and files
tempDir = new File(baseDirectory + "/js");
tempDir.mkdir();
tempFilesArray = FileIO.getResourceListing(JS.class, "cloudreports/gui/reports/resources/js/");
for(String tempFile : tempFilesArray) {
if (tempFile.isEmpty()) continue;
tempString = FileIO.readStringFromResource("cloudreports/gui/reports/resources/js/" + tempFile);
FileIO.writeStringToFile(baseDirectory + "/js/" + tempFile, tempString);
}
}
/**
* Creates the overall report.
* This part of the report contains general information about the simulation
* and includes overall data about datacenters and customers.
*
* @param datacentersList the list of simulated datacenters.
* @param brokersList the list of simulated brokers.
* @param elapsedTime the duration of the simulation.
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createOverallReport(List<PowerDatacenter> datacentersList, List<DatacenterBroker> brokersList,
ElapsedTime elapsedTime) throws IOException, URISyntaxException {
String html = FileIO.readStringFromResource("cloudreports/gui/reports/resources/index.html");
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy");
String timeAndDate = sdf.format(Calendar.getInstance().getTime());
html = html.replace("<!--INSERT_TIME-->", timeAndDate.split(" ")[0]);
html = html.replace("<!--INSERT_DATE-->", timeAndDate.split(" ")[1]);
StringBuilder overallInformation = new StringBuilder();
overallInformation.append("Simulation has finished in ")
.append(elapsedTime.toString())
.append(".");
//Insert datacenters' overall information
DatacenterRegistryDAO drDAO = new DatacenterRegistryDAO();
for (PowerDatacenter datacenter : datacentersList) {
DatacenterRegistry dcRegistry = drDAO.getDatacenterRegistry(datacenter.getName());
overallInformation.append("<br/><br/><strong>")
.append(datacenter.getName())
.append(":</strong><br/>Allocation policy: ")
.append(dcRegistry.getAllocationPolicyAlias())
.append("<br/>Number of hosts: ")
.append(drDAO.getNumOfHosts(dcRegistry.getId()))
.append("<br/>Number of migrations: ")
.append(datacenter.getMigrationCount());
}
//Insert customers' overall information
CustomerRegistryDAO crDAO = new CustomerRegistryDAO();
for(DatacenterBroker broker : brokersList) {
CustomerRegistry custRegistry = crDAO.getCustomerRegistry(broker.getName());
overallInformation.append("<br/><br/><strong>")
.append(broker.getName())
.append(":</strong><br/>Broker policy: ")
.append(custRegistry.getUtilizationProfile().getBrokerPolicyAlias())
.append("<br/>Number of virtual machines: ")
.append(crDAO.getNumOfVms(custRegistry.getId()));
}
overallInformation.append("<br/><br/>");
html = html.replace("<!--INSERT_GENERAL_INFORMATION-->", overallInformation.toString());
FileIO.writeStringToFile(baseDirectory + "/index.html", html);
}
/**
* Creates a report for each of the simulated datacenters.
*
* @param datacentersList the list of simulated datacenters.
* @param brokersList the list of simulated brokers.
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createDatacentersReports(List<PowerDatacenter> datacentersList,
List<DatacenterBroker> brokersList) throws IOException, URISyntaxException {
List<DatacenterReport> datacenterReports = new ArrayList<DatacenterReport>();
for(PowerDatacenter datacenter : datacentersList) {
DatacenterReport datacenterReport = new DatacenterReport(datacenter, brokersList, htmlReportsEnabled, rawDataReportsEnabled);
datacenterReports.add(datacenterReport);
}
if(htmlReportsEnabled) {
String html = FileIO.readStringFromResource("cloudreports/gui/reports/resources/datacenters.html");
StringBuilder datacenterOptions = new StringBuilder();
StringBuilder datacentersHtmlList = new StringBuilder();
for(DatacenterReport report : datacenterReports) {
//Insert option element
datacenterOptions.append("<option value=\"datacenter_");
datacenterOptions.append(report.getName());
datacenterOptions.append("\">");
datacenterOptions.append(report.getName());
datacenterOptions.append("</option>\n");
if (datacenterReports.indexOf(report) == 0)
datacentersHtmlList.append(report.getHtml().replace("id=\"datacenter_" + report.getName() + "\" style=\"display: none;\"", "id=\"datacenter_" + report.getName()+ "\""));
else
datacentersHtmlList.append(report.getHtml());
}
html = html.replace("<!--INSERT_DATACENTER_OPTIONS-->", datacenterOptions.toString());
html = html.replace("<!--INSERT_DATACENTERS_LIST-->", datacentersHtmlList.toString());
if(htmlReportsEnabled) FileIO.writeStringToFile(baseDirectory + "/provider/datacenters.html", html);
}
if(rawDataReportsEnabled) {
for(DatacenterReport report : datacenterReports) {
FileIO.appendStringToFile(baseDirectory + "/raw/rawData.crd", report.getRawData());
}
}
}
/**
* Creates a report for each of the simulated customers.
*
* @param brokersList the list of simulated brokers.
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createCustomersReports(List<DatacenterBroker> brokersList) throws IOException, URISyntaxException {
List<CustomerReport> customerReports = new ArrayList<CustomerReport>();
for (DatacenterBroker broker : brokersList) {
CustomerReport customerReport = new CustomerReport(broker, htmlReportsEnabled, rawDataReportsEnabled);
customerReports.add(customerReport);
}
if(htmlReportsEnabled) {
String html = FileIO.readStringFromResource("cloudreports/gui/reports/resources/customers.html");
StringBuilder customerOptions = new StringBuilder();
StringBuilder customersHtmlList = new StringBuilder();
for (CustomerReport report : customerReports) {
//Insert option element
customerOptions.append("<option value=\"customer_");
customerOptions.append(report.getName());
customerOptions.append("\">");
customerOptions.append(report.getName());
customerOptions.append("</option>\n");
if(customerReports.indexOf(report) == 0)
customersHtmlList.append(report.getHtml().replace("id=\"customer_" + report.getName() + "\" style=\"display: none;\"", "id=\"customer_" + report.getName() + "\""));
else
customersHtmlList.append(report.getHtml());
}
html = html.replace("<!--INSERT_CUSTOMER_OPTIONS-->", customerOptions.toString());
html = html.replace("<!--INSERT_CUSTOMERS_LIST-->", customersHtmlList.toString());
if(htmlReportsEnabled) FileIO.writeStringToFile(baseDirectory + "/customers/customers.html", html);
}
if(rawDataReportsEnabled) {
for (CustomerReport report : customerReports) {
FileIO.appendStringToFile(baseDirectory + "/raw/rawData.crd", report.getRawData());
}
}
}
/**
* Creates the log report.
*
* @param datacentersList the list of simulated datacenters.
* @param brokersList the list of simulated brokers.
* @throws IOException if any of the directories or files could
* not be created.
* @throws URISyntaxException if any of the used paths could not be parsed
* successfully.
* @since 1.0
*/
private static void createLogReport(List<PowerDatacenter> datacentersList,
List<DatacenterBroker> brokersList) throws IOException, URISyntaxException {
LogReport logReport = new LogReport(datacentersList, brokersList);
FileIO.writeStringToFile(baseDirectory + "/log/log.html", logReport.getHtml());
}
}