You are viewing a plain text version of this content. The canonical link for it is here.
Posted to kalumet-commits@incubator.apache.org by jb...@apache.org on 2011/10/26 08:52:33 UTC
svn commit: r1189084 - in /incubator/kalumet/trunk:
agent/src/main/java/org/apache/kalumet/agent/
agent/src/main/java/org/apache/kalumet/agent/updater/
agent/src/main/java/org/apache/kalumet/agent/utils/
common/src/main/java/org/apache/kalumet/ utils/s...
Author: jbonofre
Date: Wed Oct 26 08:52:32 2011
New Revision: 1189084
URL: http://svn.apache.org/viewvc?rev=1189084&view=rev
Log:
Add SQL script utils.
Add the software updater.
Added:
incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/updater/SoftwareUpdater.java
incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/utils/EventUtils.java
incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptRunnerUtils.java
incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptUtils.java
Modified:
incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/Main.java
incubator/kalumet/trunk/common/src/main/java/org/apache/kalumet/FileManipulator.java
Modified: incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/Main.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/Main.java?rev=1189084&r1=1189083&r2=1189084&view=diff
==============================================================================
--- incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/Main.java (original)
+++ incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/Main.java Wed Oct 26 08:52:32 2011
@@ -19,8 +19,8 @@
package org.apache.kalumet.agent;
import org.apache.commons.cli.*;
-import org.apache.kalumet.agent.utils.AgentUtils;
import org.apache.kalumet.model.Kalumet;
+import org.apache.kalumet.utils.AgentUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
Added: incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/updater/SoftwareUpdater.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/updater/SoftwareUpdater.java?rev=1189084&view=auto
==============================================================================
--- incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/updater/SoftwareUpdater.java (added)
+++ incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/updater/SoftwareUpdater.java Wed Oct 26 08:52:32 2011
@@ -0,0 +1,1053 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kalumet.agent.updater;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.kalumet.FileManipulator;
+import org.apache.kalumet.FileManipulatorException;
+import org.apache.kalumet.KalumetException;
+import org.apache.kalumet.agent.Configuration;
+import org.apache.kalumet.agent.utils.EventUtils;
+import org.apache.kalumet.model.*;
+import org.apache.kalumet.model.update.UpdateLog;
+import org.apache.kalumet.model.update.UpdateMessage;
+import org.apache.kalumet.utils.*;
+import org.apache.kalumet.ws.client.ClientException;
+import org.apache.kalumet.ws.client.SoftwareClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+
+/**
+ * Software software updater.
+ */
+public class SoftwareUpdater {
+
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(SoftwareUpdater.class);
+
+ /**
+ * Updates a <code>Software</code>.
+ *
+ * @param environment the target environment.
+ * @param software the target software.
+ * @param updateLog the <code>UpdateLog</code> to use.
+ */
+ public static void update(Environment environment, Software software, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Updating software {}", software.getName());
+
+ if (!software.isActive()) {
+ LOGGER.info("Software {} is inactive, so not updated", software.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " is inactive, so not updated"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " is inactive, so not updated");
+ return;
+ }
+
+ if (software.getAgent() != null && software.getAgent().trim().length() > 0 && !software.getAgent().equals(Configuration.AGENT_ID)) {
+ LOGGER.info("Delegating software {} update to agent {}", software.getName(), software.getAgent());
+ EventUtils.post(environment, "UPDATE", "Delegating software " + software.getName() + " update to agent " + software.getAgent());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Delegating software " + software.getName() + " update to agent " + software.getAgent()));
+ Agent delegationAgent = Configuration.CONFIG_CACHE.getAgent(software.getAgent());
+ if (delegationAgent == null) {
+ LOGGER.error("Agent {} is not found in the configuration", software.getAgent());
+ throw new UpdateException("Agent " + software.getAgent() + " is not found in the configuration");
+ }
+ try {
+ LOGGER.debug("Call software WS");
+ SoftwareClient client = new SoftwareClient(delegationAgent.getHostname(), delegationAgent.getPort());
+ client.update(environment.getName(), software.getName(), true);
+ } catch (ClientException clientException) {
+ LOGGER.error("Software {} update failed", software.getName(), clientException);
+ throw new UpdateException("Software " + software.getName() + " update failed", clientException);
+ }
+ return;
+ }
+
+ // add an update message
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Updating software " + software.getName()));
+ // post an event
+ EventUtils.post(environment, "UPDATE", "Updating software " + software.getName());
+
+ // iterate in the software update plan
+ for (Iterator updatePlanIterator = software.getUpdatePlan().iterator(); updatePlanIterator.hasNext(); ) {
+ Object item = updatePlanIterator.next();
+
+ // command update
+ if (item instanceof Command) {
+ Command command = (Command) item;
+ try {
+ SoftwareUpdater.executeCommand(environment, software, command, updateLog);
+ } catch (Exception e) {
+ if (command.isBlocker()) {
+ LOGGER.error("Command {} execution failed", command.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Command " + command.getName() + " execution failed: " + e.getMessage()));
+ EventUtils.post(environment, "ERROR", "Command " + command.getName() + " execution failed: " + e.getMessage());
+ throw new UpdateException("Command " + command.getName() + " execution failed", e);
+ } else {
+ LOGGER.warn("Command {} execution failed", command.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("warn", "Command " + command.getName() + " execution failed: " + e.getMessage()));
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Command " + command.getName() + " is not an update blocker, update continues"));
+ EventUtils.post(environment, "WARN", "Command " + command.getName() + " execution failed: " + e.getMessage());
+ EventUtils.post(environment, "UPDATE", "Command " + command.getName() + " is not an update blocker, update continues");
+ }
+ }
+ }
+
+ // location update
+ if (item instanceof Location) {
+ Location location = (Location) item;
+ try {
+ SoftwareUpdater.updateLocation(environment, software, location, updateLog);
+ } catch (Exception e) {
+ if (location.isBlocker()) {
+ LOGGER.error("Location {} update failed", location.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Location " + location.getName() + " update failed: " + e.getMessage()));
+ EventUtils.post(environment, "ERROR", "Location " + location.getName() + " update failed: " + e.getMessage());
+ throw new UpdateException("Location " + location.getName() + " update failed", e);
+ } else {
+ LOGGER.warn("Location " + location.getName() + " update failed", e);
+ updateLog.addUpdateMessage(new UpdateMessage("warn", "Location " + location.getName() + " update failed: " + e.getMessage()));
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Location " + location.getName() + " is not an update blocker, update continues"));
+ EventUtils.post(environment, "WARN", "Location " + location.getName() + " execution failed: " + e.getMessage());
+ EventUtils.post(environment, "UPDATE", "Location " + location.getName() + " is not an update blocker, update continues");
+ }
+ }
+ }
+
+ // configuration update
+ if (item instanceof ConfigurationFile) {
+ ConfigurationFile configurationFile = (ConfigurationFile) item;
+ try {
+ SoftwareUpdater.updateConfigurationFile(environment, software, configurationFile, updateLog);
+ } catch (Exception e) {
+ if (configurationFile.isBlocker()) {
+ LOGGER.error("Configuration file {} update failed", configurationFile.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage()));
+ EventUtils.post(environment, "ERROR", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage());
+ throw new UpdateException("Configuration file " + configurationFile.getName() + " update failed", e);
+ } else {
+ LOGGER.warn("Configuration file {} update failed", configurationFile.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("warn", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage()));
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Configuration file " + configurationFile.getName() + " is not an update blocker, update continues"));
+ EventUtils.post(environment, "WARN", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage());
+ EventUtils.post(environment, "UPDATE", "Configuration file " + configurationFile.getName() + " is not an update blocker, update continues");
+ }
+ }
+ }
+
+ // database update
+ if (item instanceof Database) {
+ Database database = (Database) item;
+ try {
+ SoftwareUpdater.updateDatabase(environment, software, database, updateLog);
+ } catch (Exception e) {
+ if (database.isBlocker()) {
+ LOGGER.error("Database {} update failed", database.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Database " + database.getName() + " update failed: " + e.getMessage()));
+ EventUtils.post(environment, "ERROR", "Database " + database.getName() + " update failed: " + e.getMessage());
+ throw new UpdateException("Database " + database.getName() + " update failed", e);
+ } else {
+ LOGGER.warn("Database {} update failed", database.getName(), e);
+ updateLog.addUpdateMessage(new UpdateMessage("warn", "Database " + database.getName() + " update failed: " + e.getMessage()));
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Database " + database.getName() + " is not an update blocker, update continues"));
+ EventUtils.post(environment, "WARN", "Database " + database.getName() + " update failed: " + e.getMessage());
+ EventUtils.post(environment, "UPDATE", "Database " + database.getName() + " is not an update blocker, update continues");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Wrapper method to update a software (via WebService).
+ *
+ * @param environmentName the target environment name.
+ * @param softwareName the target software name.
+ * @param delegation flag indicating if the update is a delegation from another agent (true), or a client call (false).
+ */
+ public static void update(String environmentName, String softwareName, boolean delegation) throws KalumetException {
+ LOGGER.info("Software {} update requested by WS", softwareName);
+
+ LOGGER.debug("Loading configuration");
+ Kalumet kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+
+ Environment environment = kalumet.getEnvironment(environmentName);
+ if (environment == null) {
+ LOGGER.error("Environment {} is not found in the configuration", environmentName);
+ throw new KalumetException("Environment " + environmentName + " is not found in the configuration");
+ }
+ Software software = environment.getSoftware(softwareName);
+ if (software == null) {
+ LOGGER.error("Software {} is not found in environment {}", softwareName, environment.getName());
+ throw new KalumetException("Software " + softwareName + " is not found in environment " + environment.getName());
+ }
+
+ LOGGER.debug("Creating an update log");
+ UpdateLog updateLog = new UpdateLog("Software " + software.getName() + " update in progress ...", environment.getName(), environment);
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " update requested by WS");
+
+ if (!delegation) {
+ LOGGER.info("Send a notification and waiting for the count down");
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Send a notification and waiting for the count down"));
+ EventUtils.post(environment, "UPDATE", "Send a notification and waiting for the count down");
+ NotifierUtils.waitAndNotify(environment);
+ }
+ try {
+ LOGGER.debug("Call the software updater");
+ SoftwareUpdater.update(environment, software, updateLog);
+ } catch (Exception e) {
+ LOGGER.error("Software {} update failed", software.getName(), e);
+ EventUtils.post(environment, "ERROR", "Software " + software.getName() + " update failed: " + e.getMessage());
+ if (!delegation) {
+ updateLog.setStatus("Software " + software.getName() + " update failed");
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Software " + software.getName() + " update failed: " + e.getMessage()));
+ PublisherUtils.publish(environment);
+ }
+ throw new KalumetException("Software " + software.getName() + " update failed", e);
+ }
+
+ LOGGER.info("Software {} updated", software.getName());
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " updated");
+ if (!delegation) {
+ LOGGER.debug("The update is a client call, publish result");
+ EventUtils.post(environment, "UPDATE", "Update completed");
+ if (updateLog.isUpdated()) {
+ updateLog.setStatus("Software " + software.getName() + " updated");
+ } else {
+ updateLog.setStatus("Software " + software.getName() + " already up to date");
+ }
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Update completed"));
+ LOGGER.info("Publishing update report");
+ PublisherUtils.publish(environment);
+ }
+ }
+
+ /**
+ * Execute a software command.
+ *
+ * @param environment the target environment.
+ * @param software the target software.
+ * @param command the target command.
+ * @param updateLog the <code>UpdateLog</code> to use.
+ * @throws UpdateException in case of error during the command execution.
+ */
+ public static void executeCommand(Environment environment, Software software, Command command, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Executing software {} command {}", software.getName(), command.getName());
+
+ if (!command.isActive()) {
+ LOGGER.info("Software {} command {} is inactive, so not executed", software.getName(), command.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " command " + command.getName() + " is inactive, so not executed"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " command " + command.getName() + " is inactive, so not executed");
+ return;
+ }
+
+ if (command.getAgent() != null && command.getAgent().trim().length() > 0 && !command.getAgent().equals(Configuration.AGENT_ID)) {
+ // delegates the command execution to another agent
+ LOGGER.info("Delegating command {} execution to agent {}", command.getName(), command.getAgent());
+ Agent agentDelegation = Configuration.CONFIG_CACHE.getAgent(command.getAgent());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Delegating command " + command.getName() + " execution to agent " + command.getAgent()));
+ EventUtils.post(environment, "UPDATE", "Delegating command " + command.getName() + " execution to agent " + command);
+ if (agentDelegation == null) {
+ LOGGER.error("Agent {} is not found in the configuration", command.getAgent());
+ throw new UpdateException("Agent " + command.getAgent() + " is not found in the configuration");
+ }
+ try {
+ LOGGER.debug("Call software WS");
+ SoftwareClient client = new SoftwareClient(agentDelegation.getHostname(), agentDelegation.getPort());
+ client.executeCommand(environment.getName(), software.getName(), command.getName(), true);
+ } catch (ClientException clientException) {
+ LOGGER.error("Command {} execution failed", command.getName(), clientException);
+ throw new UpdateException("Command " + command.getName() + " execution failed: " + clientException.getMessage(), clientException);
+ }
+ return;
+ }
+
+ String commandExec = VariableUtils.replace(command.getCommand(), environment.getVariables());
+ String output = null;
+ try {
+ output = CommandUtils.execute(commandExec);
+ } catch (KalumetException kalumetException) {
+ LOGGER.error("Command {} execution failed", command.getName(), kalumetException);
+ throw new UpdateException("Command " + command.getName() + " execution failed", kalumetException);
+ }
+
+ LOGGER.info("Software {} command {} executed: {}", new Object[]{ software.getName(), command.getName(), output });
+ // add an update message
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " command " + command.getName() + " executed: " + output));
+ // post an event
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " command " + command.getName() + " executed: " + output);
+ }
+
+ /**
+ * Wrapper method to execute a software command (via WS).
+ *
+ * @param environmentName the target environment name.
+ * @param softwareName the target software name.
+ * @param commandName the target command name.
+ * @param delegation flag indicating if the execution is a delegation from another agent (true), or a client call (false).
+ */
+ public static void executeCommand(String environmentName, String softwareName, String commandName, boolean delegation) throws KalumetException {
+ LOGGER.info("Software {} command {} execution requested by WS", softwareName, commandName);
+ Kalumet kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+ Environment environment = kalumet.getEnvironment(environmentName);
+ if (environment == null) {
+ LOGGER.error("Environment {} is not found in the configuration", environmentName);
+ throw new KalumetException("Environment " + environmentName + " is not found in the configuration");
+ }
+ Software software = environment.getSoftware(softwareName);
+ if (software == null) {
+ LOGGER.error("Software {} is not found in environment {}", softwareName, environmentName);
+ throw new KalumetException("Software " + softwareName + " is not found in environment " + environmentName);
+ }
+ Command command = software.getCommand(commandName);
+ if (command == null) {
+ LOGGER.error("Command {} is not found in software {}", commandName, softwareName);
+ throw new KalumetException("Command " + commandName + " is not found in software " + softwareName);
+ }
+ // update the agent configuration cache
+ LOGGER.debug("Updating agent configuration cache");
+ Configuration.CONFIG_CACHE = kalumet;
+ // post a journal event
+ EventUtils.post(environment, "UPDATE", "Software " + softwareName + " command " + commandName + " execution requested by WS");
+ // create an update logger
+ UpdateLog updateLog = new UpdateLog("Software " + softwareName + " command " + commandName + " execution in progress ...", environment.getName(), environment);
+ if (!delegation) {
+ // the call is not a delegation from another agent
+ LOGGER.info("Send a notification and waiting for the count down");
+ EventUtils.post(environment, "UPDATE", "Send a notification and waiting for the count down");
+ NotifierUtils.waitAndNotify(environment);
+ }
+ try {
+ // call the updater
+ LOGGER.debug("Call the software updater");
+ SoftwareUpdater.executeCommand(environment, software, command, updateLog);
+ } catch (Exception e) {
+ LOGGER.error("Command {} execution failed", command.getName(), e);
+ EventUtils.post(environment, "ERROR", "Command " + command.getName() + " execution failed: " + e.getMessage());
+ if (!delegation) {
+ updateLog.setStatus("Command " + command.getName() + " execution failed");
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Command " + command.getName() + " execution failed: " + e.getMessage()));
+ PublisherUtils.publish(environment);
+ }
+ throw new UpdateException("Command " + command.getName() + " execution failed", e);
+ }
+
+ // command execution is completed
+ LOGGER.info("Command {} has been executed successfully", command.getName());
+ EventUtils.post(environment, "UPDATE", "Command " + command.getName() + " has been executed successfully");
+ if (!delegation) {
+ updateLog.setStatus("Command " + command.getName() + " has been executed successfully");
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Command " + command.getName() + " has been executed successfully"));
+ LOGGER.info("Publishing update report");
+ PublisherUtils.publish(environment);
+ }
+ }
+
+ /**
+ * Wrapper method to update a location (via WS).
+ *
+ * @param environmentName the target environment name.
+ * @param softwareName the target software name.
+ * @param locationName the target location name.
+ * @param delegation true if the call is performed by another agent, false else.
+ * @throws UpdateException in case of location update failure.
+ */
+ public static void updateLocation(String environmentName, String softwareName, String locationName, boolean delegation) throws KalumetException {
+ LOGGER.info("Software {} location {} update requested by WS", softwareName, locationName);
+
+ // loading AutoDeploy configuration
+ LOGGER.debug("Loading configuration");
+ Kalumet kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+ Environment environment = kalumet.getEnvironment(environmentName);
+ if (environment == null) {
+ LOGGER.error("Environment {} is not found in the configuration", environmentName);
+ throw new KalumetException("Environment " + environmentName + " is not found in the configuration");
+ }
+ Software software = environment.getSoftware(softwareName);
+ if (software == null) {
+ LOGGER.error("Software {} is not found in environment {}", softwareName, environmentName);
+ throw new KalumetException("Software " + softwareName + " is not found in environment " + environmentName);
+ }
+ Location location = software.getLocation(locationName);
+ if (location == null) {
+ LOGGER.error("Location {} is not found in software {}",locationName, softwareName);
+ throw new KalumetException("Location " + locationName + " is not found in software " + softwareName);
+ }
+
+ // update configuration cache
+ LOGGER.debug("Updating configuration cache");
+ Configuration.CONFIG_CACHE = kalumet;
+
+ // post journal event
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " location " + location.getName() + " update requested by WS");
+ // create an update logger
+ UpdateLog updateLog = new UpdateLog("Software " + software.getName() + " location " + location.getName() + " update in progress ....", environment.getName(), environment);
+
+ if (!delegation) {
+ // the call is not a delegation from another agent, it's an atomic update
+ LOGGER.info("Send a notification and waiting for the count down");
+ EventUtils.post(environment, "UPDATE", "Send a notification and waiting for the count down");
+ NotifierUtils.waitAndNotify(environment);
+ }
+ try {
+ // call software updater
+ LOGGER.debug("Call software updater");
+ SoftwareUpdater.updateLocation(environment, software, location, updateLog);
+ } catch (Exception e) {
+ LOGGER.error("Location {} update failed", location.getName(), e);
+ EventUtils.post(environment, "ERROR", "Location " + location.getName() + " update failed: " + e.getMessage());
+ if (!delegation) {
+ updateLog.setStatus("Location " + locationName + " update failed");
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Location " + locationName + " update failed: " + e.getMessage()));
+ PublisherUtils.publish(environment);
+ }
+ throw new UpdateException("Location " + location.getName() + " update failed", e);
+ }
+
+ // location updated
+ LOGGER.info("Location {} updated", location.getName());
+ EventUtils.post(environment, "UPDATE", "Location " + location.getName() + " updated");
+ if (!delegation) {
+ updateLog.setStatus("Location " + location.getName() + " updated");
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Location " + location.getName() + " updated"));
+ LOGGER.info("Publishing update report");
+ PublisherUtils.publish(environment);
+ }
+ }
+
+ /**
+ * Updates an <code>Software</code> <code>Location</code>.
+ *
+ * @param environment the target <code>Environment</code>.
+ * @param software the target <code>Software</code>.
+ * @param location the target <code>Location</code>.
+ * @param updateLog the <code>UpdateLog</code> to use.
+ * @throws UpdateException in case of error during the location update.
+ */
+ public static void updateLocation(Environment environment, Software software, Location location, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Updating software {} location {}", software.getName(), location.getName());
+
+ if (!location.isActive()) {
+ LOGGER.info("Software {} location {} is inactive, so not updated", software.getName(), location.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " location " + location.getName() + " is inactive, so not updated"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " location " + location.getName() + "is inactive, so not updated");
+ return;
+ }
+
+ if (location.getAgent() != null && location.getAgent().trim().length() > 0 && !location.getAgent().equals(Configuration.AGENT_ID)) {
+ // delegates the location update to another agent
+ LOGGER.info("Delegating location {} update to agent {}", location.getName(), location.getAgent());
+ Agent agentDelegation = Configuration.CONFIG_CACHE.getAgent(location.getAgent());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Delegating location " + location.getName() + " update to agent " + location.getAgent()));
+ EventUtils.post(environment, "UPDATE", "Delegating location " + location.getName() + " update to agent " + location.getAgent());
+ if (agentDelegation == null) {
+ LOGGER.error("Agent {} is not found in the configuration", location.getAgent());
+ throw new UpdateException("Agent " + location.getAgent() + " is not found in the configuration");
+ }
+ try {
+ // call the WebService
+ LOGGER.debug("Call software WS");
+ SoftwareClient client = new SoftwareClient(agentDelegation.getHostname(), agentDelegation.getPort());
+ client.updateLocation(environment.getName(), software.getName(), location.getName(), true);
+ } catch (ClientException clientException) {
+ LOGGER.error("Location {} update failed", location.getName(), clientException);
+ throw new UpdateException("Location " + location.getName() + " update failed: " + clientException.getMessage(), clientException);
+ }
+ return;
+ }
+
+ // constructs the location URI
+ String locationUri = VariableUtils.replace(location.getUri(), environment.getVariables());
+ if (!FileManipulator.protocolExists(locationUri)) {
+ LOGGER.debug("The location URI is relative to the software URI");
+ locationUri = FileManipulator.format(VariableUtils.replace(software.getUri(), environment.getVariables())) + "!/" + locationUri;
+ }
+ // constructs the location destination path
+ String locationPath = VariableUtils.replace(location.getPath(), environment.getVariables());
+ // get a file manipulator
+ FileManipulator fileManipulator = null;
+ try {
+ fileManipulator = FileManipulator.getInstance();
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't initialize file manipulator", fileManipulatorException);
+ throw new UpdateException("Can't initialize file manipulator", fileManipulatorException);
+ }
+ try {
+ LOGGER.debug("Copying {} to {}", locationUri, locationPath);
+ fileManipulator.copy(locationUri, locationPath);
+ updateLog.setUpdated(true);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Location {} update failed", location.getName(), fileManipulatorException);
+ throw new UpdateException("Location " + location.getName() + " update failed", fileManipulatorException);
+ }
+ LOGGER.info("Software {} location {} updated", software.getName(), location.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " location " + location.getName() + " updated"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " location " + location.getName() + " updated");
+ }
+
+ /**
+ * Wrapper method to update a configuration file (via WS).
+ *
+ * @param environmentName the target environment name.
+ * @param softwareName the target software name.
+ * @param configurationFileName the target configuration file name.
+ * @param delegation true if the call is made by another agent (delegation), false if the call is made by a client.
+ * @throws KalumetException in case of update failure.
+ */
+ public static void updateConfigurationFile(String environmentName, String softwareName, String configurationFileName, boolean delegation) throws KalumetException {
+ LOGGER.info("Software {} configuration file {} update requested by WS", softwareName, configurationFileName);
+
+ // loading configuration
+ LOGGER.debug("Loading configuration");
+ Kalumet kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+
+ Environment environment = kalumet.getEnvironment(environmentName);
+ if (environment == null) {
+ LOGGER.error("Environment {} is not found in the configuration", environmentName);
+ throw new KalumetException("Environment " + environmentName + " is not found in the configuration");
+ }
+ Software software = environment.getSoftware(softwareName);
+ if (software == null) {
+ LOGGER.error("Software {} is not found in environment {}", softwareName, environmentName);
+ throw new KalumetException("Software " + softwareName + " is not found in environment " + environmentName);
+ }
+ ConfigurationFile configurationFile = software.getConfigurationFile(configurationFileName);
+ if (configurationFile == null) {
+ LOGGER.error("Configuration file {} is not found in software {}", configurationFileName, softwareName);
+ throw new KalumetException("Configuration file " + configurationFileName + " is not found in software " + softwareName);
+ }
+
+ // update agent configuration cache
+ LOGGER.debug("Updating agent configuration cache");
+ Configuration.CONFIG_CACHE = kalumet;
+
+ // post journal event
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " configuration file " + configurationFile.getName() + " update requested by WS");
+ // create update log
+ UpdateLog updateLog = new UpdateLog("Software " + software.getName() + " configuration file " + configurationFile.getName() + " update in progress ...", environment.getName(), environment);
+
+ if (!delegation) {
+ // the update is not call by another agent, it's an atomic update
+ LOGGER.info("Send a notification and waiting for the count down");
+ EventUtils.post(environment, "UPDATE", "Send a notification and waiting for the count down");
+ NotifierUtils.waitAndNotify(environment);
+ }
+
+ try {
+ // call software updater
+ LOGGER.debug("Call software updater");
+ SoftwareUpdater.updateConfigurationFile(environment, software, configurationFile, updateLog);
+ } catch (Exception e) {
+ LOGGER.error("Configuration file {} update failed", configurationFile.getName(), e);
+ EventUtils.post(environment, "ERROR", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage());
+ if (!delegation) {
+ updateLog.setStatus("Configuration file " + configurationFile.getName() + " update failed");
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Configuration file " + configurationFile.getName() + " update failed: " + e.getMessage()));
+ PublisherUtils.publish(environment);
+ }
+ throw new UpdateException("Configuration file " + configurationFile.getName() + " update failed", e);
+ }
+
+ // configuration file updated
+ LOGGER.info("Configuration file {} updated", configurationFile.getName());
+ EventUtils.post(environment, "UPDATE", "Configuration file " + configurationFile.getName() + " updated");
+ if (!delegation) {
+ updateLog.setStatus("Configuration file " + configurationFile.getName() + " updated");
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Configuration file " + configurationFile.getName() + " updated"));
+ LOGGER.info("Publishing update report");
+ PublisherUtils.publish(environment);
+ }
+ }
+
+ /**
+ * Update an <code>Software</code> <code>ConfigurationFile</code>.
+ *
+ * @param environment the target <code>Environment</code>.
+ * @param software the target <code>Software</code>.
+ * @param configurationFile the target <code>ConfigurationFile</code>.
+ * @param updateLog the <code>UpdateLog</code> to use.
+ * @throws UpdateException in case of error during the configuration file update.
+ */
+ public static void updateConfigurationFile(Environment environment, Software software, ConfigurationFile configurationFile, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Updating software {} configuration file {}", software.getName(), configurationFile.getName());
+
+ if (!configurationFile.isActive()) {
+ LOGGER.info("Software {} configuration file {} is inactive, so not updated", software.getName(), configurationFile.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " configuration file " + configurationFile.getName() + " is inactive, so not updated"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " configuration file " + configurationFile.getName() + " is inactive, so not updated");
+ return;
+ }
+
+ if (configurationFile.getAgent() != null && configurationFile.getAgent().trim().length() > 0 && !configurationFile.getAgent().equals(Configuration.AGENT_ID)) {
+ // delegates configuration file update to another agent
+ LOGGER.info("Delegating configuration file {} update to agent {}", configurationFile.getName(), configurationFile.getAgent());
+ Agent agentDelegation = Configuration.CONFIG_CACHE.getAgent(configurationFile.getAgent());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Delegating configuration file " + configurationFile.getName() + " update to agent " + configurationFile.getAgent()));
+ EventUtils.post(environment, "UPDATE", "Delegating configuration file " + configurationFile.getName() + " update to agent " + configurationFile.getAgent());
+ if (agentDelegation == null) {
+ LOGGER.error("Agent {} is not found in the configuration", configurationFile.getAgent());
+ throw new UpdateException("Agent " + configurationFile.getAgent() + " is not found in the configuration");
+ }
+ try {
+ // call WS
+ LOGGER.debug("Call software WS");
+ SoftwareClient client = new SoftwareClient(agentDelegation.getHostname(), agentDelegation.getPort());
+ client.updateConfigurationFile(environment.getName(), software.getName(), configurationFile.getName(), true);
+ } catch (ClientException clientException) {
+ LOGGER.error("Configuration file {} update failed", configurationFile.getName(), clientException);
+ throw new UpdateException("Configuration file " + configurationFile.getName() + " update failed", clientException);
+ }
+ return;
+ }
+
+ // defines the configuration file URI
+ LOGGER.debug("Getting configuration file URI");
+ String configurationFileUri = VariableUtils.replace(configurationFile.getUri(), environment.getVariables());
+ if (!FileManipulator.protocolExists(configurationFileUri)) {
+ LOGGER.debug("The configuration file URI is relative to the software URI");
+ configurationFileUri = FileManipulator.format(VariableUtils.replace(software.getUri(), environment.getVariables())) + "!/" + configurationFileUri;
+ }
+
+ // defines the software cache directory
+ LOGGER.debug("Getting software cache directory");
+ String softwareCacheDir = null;
+ try {
+ softwareCacheDir = FileManipulator.createSoftwareCacheDir(environment, software);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't initialize software cache directory", fileManipulatorException);
+ throw new UpdateException("Can't initialize software cache directory", fileManipulatorException);
+ }
+
+ // initializes file manipulator
+ LOGGER.debug("Initializing file manipulator");
+ FileManipulator fileManipulator = null;
+ try {
+ fileManipulator = FileManipulator.getInstance();
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't initialize file manipulator", fileManipulatorException);
+ throw new UpdateException("Can't initialize file manipulator", fileManipulatorException);
+ }
+
+ // copy configuration file into cache
+ String configurationFileCacheLocation = softwareCacheDir + "/config/" + configurationFile.getName();
+ LOGGER.debug("Copying configuration file {} into cache", configurationFile.getName());
+ try {
+ fileManipulator.copy(configurationFileUri, configurationFileCacheLocation);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't copy configuration file {} into cache", configurationFile.getName(), fileManipulatorException);
+ throw new UpdateException("Can't copy configuration file " + configurationFile.getName() + " into cache", fileManipulatorException);
+ }
+
+ // change mappings into the configuration file cache
+ LOGGER.debug("Replacing mappings key/value");
+ for (Iterator mappingIterator = configurationFile.getMappings().iterator(); mappingIterator.hasNext(); ) {
+ Mapping mapping = (Mapping) mappingIterator.next();
+ FileManipulator.searchAndReplace(mapping.getKey(), VariableUtils.replace(mapping.getValue(), environment.getVariables()), configurationFileCacheLocation);
+ }
+
+ // compare configuration file cache with target
+ LOGGER.debug("Comparing the configuration file cache with the target location");
+ String configurationFileDestinationPath = VariableUtils.replace(configurationFile.getPath(), environment.getVariables());
+ try {
+ if (!fileManipulator.contentEquals(configurationFileCacheLocation, configurationFileDestinationPath)) {
+ // the configuration file needs to be updated
+ LOGGER.debug("Configuration file {} needs to be updated", configurationFile.getName());
+ fileManipulator.copy(configurationFileCacheLocation, configurationFileDestinationPath);
+ updateLog.setStatus("UPDATE PERFORMED");
+ updateLog.setUpdated(true);
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Configuration file " + configurationFile.getName() + " updated"));
+ EventUtils.post(environment, "UPDATE", "Configuration file " + configurationFile.getName() + " updated");
+ LOGGER.info("Configuration file {} updated", configurationFile.getName());
+ }
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Configuration file {} update failed", configurationFile.getName(), fileManipulatorException);
+ throw new UpdateException("Configuration file " + configurationFile.getName() + " update failed: " + fileManipulatorException.getMessage(), fileManipulatorException);
+ }
+ }
+
+ /**
+ * Wrapper method to update a software database (via WS).
+ *
+ * @param environmentName the target environment name.
+ * @param softwareName the target software name.
+ * @param databaseName the target database name.
+ * @param delegation true if the call is made by another agent (delegation), false if the call is made by a client.
+ * @throws KalumetException in case of update failure.
+ */
+ public static void updateDatabase(String environmentName, String softwareName, String databaseName, boolean delegation) throws KalumetException {
+ LOGGER.info("Software {} database {} update requested by WS", softwareName, databaseName);
+
+ // load configuration
+ Kalumet kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+ Environment environment = kalumet.getEnvironment(environmentName);
+ if (environment == null) {
+ LOGGER.error("Environment {} is not found in the configuration", environmentName);
+ throw new KalumetException("Environment " + environmentName + " is not found in the configuration");
+ }
+ Software software = environment.getSoftware(softwareName);
+ if (software == null) {
+ LOGGER.error("Software {} is not found in environment {}", softwareName, environmentName);
+ throw new KalumetException("Software " + softwareName + " is not found in environment " + environmentName);
+ }
+ Database database = software.getDatabase(databaseName);
+ if (database == null) {
+ LOGGER.error("Database {} is not found in software {}", databaseName, softwareName);
+ throw new KalumetException("Database " + databaseName + " is not found in software " + softwareName);
+ }
+
+ // updating configuration cache
+ LOGGER.debug("Updating configuration cache");
+ Configuration.CONFIG_CACHE = kalumet;
+
+ // post journal event
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " database " + database.getName() + " update requested by WS");
+ // create update log
+ UpdateLog updateLog = new UpdateLog("Software " + software.getName() + " database " + database.getName() + " update in progress ...", environment.getName(), environment);
+
+ if (!delegation) {
+ // the call is not a delegation from another agent, it's an atomic update
+ LOGGER.info("Send a notification and waiting for the count down");
+ EventUtils.post(environment, "UPDATE", "Send a notification and waiting for the count down");
+ NotifierUtils.waitAndNotify(environment);
+ }
+
+ try {
+ // call software updater
+ LOGGER.debug("Call software updater");
+ SoftwareUpdater.updateDatabase(environment, software, database, updateLog);
+ } catch (Exception e) {
+ LOGGER.error("Database {} update failed", database.getName(), e);
+ EventUtils.post(environment, "ERROR", "Database " + database.getName() + " update failed: " + e.getMessage());
+ if (!delegation) {
+ updateLog.setStatus("Database " + database.getName() + " update failed");
+ updateLog.addUpdateMessage(new UpdateMessage("error", "Database " + database.getName() + " update failed: " + e.getMessage()));
+ PublisherUtils.publish(environment);
+ }
+ throw new UpdateException("Database " + database.getName() + " update failed", e);
+ }
+
+ // database updated
+ LOGGER.info("Database {} updated", database.getName());
+ EventUtils.post(environment, "UPDATE", "Database " + database.getName() + " updated");
+ if (!delegation) {
+ updateLog.setStatus("Database " + database.getName() + " updated");
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Database " + database.getName() + " updated"));
+ LOGGER.info("Publishing update report");
+ PublisherUtils.publish(environment);
+ }
+ }
+
+ /**
+ * Update a software database.
+ *
+ * @param environment the target <code>Environment</code>.
+ * @param software the target <code>Software</code>.
+ * @param database the target <code>Database</code>.
+ * @param updateLog the update logger to use.
+ */
+ public static void updateDatabase(Environment environment, Software software, Database database, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Update software {} database {}", software.getName(), database.getName());
+
+ if (!database.isActive()) {
+ LOGGER.info("Software {} database {} (environment {}) is inactive, so not updated", new Object[]{ software.getName(), database.getName(), environment.getName() });
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Software " + software.getName() + " database " + database.getName() + " is inactive, so not updated"));
+ EventUtils.post(environment, "UPDATE", "Software " + software.getName() + " database " + database.getName() + " is inactive, so not updated");
+ return;
+ }
+
+ if (database.getAgent() != null && database.getAgent().trim().length() > 0 && !database.getAgent().equals(Configuration.AGENT_ID)) {
+ // the database update is delegated to another agent
+ LOGGER.info("Delegating software {} database {} update to agent {}", new Object[]{ software.getName(), database.getName(), database.getAgent() });
+ Agent delegationAgent = Configuration.CONFIG_CACHE.getAgent(database.getAgent());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Delegating database " + database.getName() + " update to agent " + database.getAgent()));
+ EventUtils.post(environment, "UPDATE", "Delegating database " + database.getName() + " update to agent " + database.getAgent());
+ if (delegationAgent == null) {
+ // the database agent is not found in the configuration
+ LOGGER.error("Agent {} is not found in the configuration", database.getAgent());
+ throw new UpdateException("Agent " + database.getAgent() + " is not found in the configuration");
+ }
+ try {
+ // call the WebService
+ LOGGER.debug("Call software WS");
+ SoftwareClient client = new SoftwareClient(delegationAgent.getHostname(), delegationAgent.getPort());
+ client.updateDatabase(environment.getName(), software.getName(), database.getName(), true);
+ } catch (ClientException clientException) {
+ LOGGER.error("Database {} update failed", database.getName(), clientException);
+ throw new UpdateException("Database " + database.getName() + " update failed", clientException);
+ }
+ return;
+ }
+
+ // launch SQL scripts of the database
+ LOGGER.debug("Executing SQL scripts");
+ for (Iterator sqlScriptIterator = database.getSqlScripts().iterator(); sqlScriptIterator.hasNext(); ) {
+ SqlScript sqlScript = (SqlScript) sqlScriptIterator.next();
+ try {
+ SoftwareUpdater.executeSqlScript(environment, software, database, sqlScript, updateLog);
+ } catch (UpdateException updateException) {
+ // SQL script execution has failed
+ if (sqlScript.isBlocker()) {
+ // the SQL script is update blocker
+ LOGGER.error("SQL script {} execution failed", updateException);
+ throw new UpdateException("SQL script " + sqlScript.getName() + " execution failed", updateException);
+ } else {
+ // the SQL script is not update blocker
+ LOGGER.warn("SQL script {} execution failed", updateException);
+ updateLog.addUpdateMessage(new UpdateMessage("warn", "SQL script " + sqlScript.getName() + " execution failed: " + updateException.getMessage()));
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + sqlScript.getName() + " is not update blocker, update continues"));
+ EventUtils.post(environment, "WARN", "SQL script " + sqlScript.getName() + " execution failed: " + updateException.getMessage());
+ EventUtils.post(environment, "UPDATE", "SQL script " + sqlScript.getName() + " is not update blocker, update continues");
+ }
+ }
+ }
+ }
+
+ /**
+ * Executes SQL script.
+ *
+ * @param environment the target <code>Environment</code>.
+ * @param software the target <code>Software</code>.
+ * @param database the target <code>Database</code>.
+ * @param sqlScript the target <code>SqlScript</code>.
+ * @param updateLog the update log to use.
+ * @throws UpdateException in case of error during the SQL script execution.
+ */
+ public static void executeSqlScript(Environment environment, Software software, Database database, SqlScript sqlScript, UpdateLog updateLog) throws UpdateException {
+ LOGGER.info("Executing SQL script {}", sqlScript.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "Executing SQL script " + sqlScript.getName()));
+ EventUtils.post(environment, "UPDATE", "Executing SQL script " + sqlScript.getName());
+
+ if (!sqlScript.isActive()) {
+ // the SQL script is not active
+ LOGGER.info("SQL script {} is inactive, so not executed", sqlScript.getName());
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + sqlScript.getName() + " is inactive, so not executed"));
+ EventUtils.post(environment, "UPDATE", "SQL script " + sqlScript.getName() + " is inactive, so not executed");
+ return;
+ }
+
+ // construct the SQL script URI
+ String sqlScriptUri = VariableUtils.replace(sqlScript.getUri(), environment.getVariables());
+ if (!FileManipulator.protocolExists(sqlScriptUri)) {
+ // the SQL script URI is relative, constructs using the software URI
+ LOGGER.debug("The SQL script URI is relative to the software URI");
+ sqlScriptUri = FileManipulator.format(VariableUtils.replace(software.getUri(), environment.getVariables())) + "!/" + sqlScriptUri;
+ }
+
+ // get the cache directory
+ LOGGER.debug("Getting software cache directory");
+ String softwareCacheDir = null;
+ try {
+ softwareCacheDir = FileManipulator.createSoftwareCacheDir(environment, software);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't initialize software cache directory", fileManipulatorException);
+ throw new UpdateException("Can't initialize software cache directory", fileManipulatorException);
+ }
+
+ // get file manipulator instance
+ LOGGER.debug("Initializing file manipulator");
+ FileManipulator fileManipulator = null;
+ try {
+ fileManipulator = FileManipulator.getInstance();
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't initialize file manipulator", fileManipulatorException);
+ throw new UpdateException("Can't initialize file manipulator", fileManipulatorException);
+ }
+
+ // copy the SQL script into the software cache directory
+ LOGGER.debug("Copying the SQL script into the software cache directory");
+ String sqlScriptCache = softwareCacheDir + "/sql/" + sqlScript.getName() + ".cache";
+ String sqlScriptRuntime = softwareCacheDir + "/sql/" + sqlScript.getName();
+ try {
+ fileManipulator.copy(sqlScriptUri, sqlScriptCache);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.error("Can't copy SQL script from {} to {}", new Object[]{ sqlScriptUri, sqlScriptCache }, fileManipulatorException);
+ throw new UpdateException("Can't copy SQL script " + sqlScriptUri + " to " + sqlScriptCache, fileManipulatorException);
+ }
+
+ if (fileManipulator.isFolder(sqlScriptCache)) {
+ // TODO add a generic method to reuse in the case of directory
+
+ // the user provided a directory
+ updateLog.addUpdateMessage(new UpdateMessage("info", sqlScript.getName() + "is a folder, iterate in the SQL scripts"));
+ EventUtils.post(environment, "UPDATE", sqlScript.getName() + " is a folder, iterate in the SQL scripts");
+ LOGGER.info("{} is a folder, iterate in the SQL scripts", sqlScript.getName());
+ FileObject[] children = fileManipulator.browse(sqlScriptCache);
+ for (int i = 0; i < children.length; i++) {
+ FileObject current = children[i];
+ String name = current.getName().getBaseName();
+ String singleSqlScriptCache = sqlScriptCache + "/" + name;
+ String singleSqlScriptRuntime = sqlScriptRuntime + "/" + name;
+ // change mappings in the current SQL script
+ for (Iterator mappingIterator = sqlScript.getMappings().iterator(); mappingIterator.hasNext(); ) {
+ Mapping mapping = (Mapping) mappingIterator.next();
+ FileManipulator.searchAndReplace(mapping.getKey(), VariableUtils.replace(mapping.getValue(), environment.getVariables()), singleSqlScriptCache);
+ }
+ try {
+ if (sqlScript.isForce() || (!fileManipulator.contentEquals(singleSqlScriptCache, singleSqlScriptRuntime))) {
+ fileManipulator.copy(singleSqlScriptCache, singleSqlScriptRuntime);
+
+ if (database.getSqlCommand() != null && database.getSqlCommand().trim().length() > 0) {
+ // execute SQL script using system command
+ String command = VariableUtils.replace(database.getSqlCommand(), environment.getVariables());
+ String output = SqlScriptUtils.executeUsingCommand(singleSqlScriptRuntime, command);
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + name + " executed: " + output));
+ EventUtils.post(environment, "UPDATE", "SQL script " + name + " executed: " + output);
+ LOGGER.info("SQL script {} executed: {}", name, output);
+ } else {
+ // execute SQL script using JDBC
+ String user = null;
+ String password = null;
+ String driver = null;
+ String url = null;
+ if (database.getConnectionPool() != null && database.getConnectionPool().trim().length() > 0) {
+ // the database is linked to a connection pool
+ // looking for the connection pool (from the cache)
+ LOGGER.debug("Database has a reference to a connection pool");
+ // looking for the connection pool definition
+ String connectionPoolName = VariableUtils.replace(database.getConnectionPool(), environment.getVariables());
+ JDBCConnectionPool connectionPool = null;
+ for (Iterator applicationServerIterator = environment.getJ2EEApplicationServers().getJ2EEApplicationServers().iterator(); applicationServerIterator.hasNext(); ) {
+ J2EEApplicationServer applicationServer = (J2EEApplicationServer) applicationServerIterator.next();
+ connectionPool = applicationServer.getJDBCConnectionPool(connectionPoolName);
+ if (connectionPool != null) {
+ break;
+ }
+ }
+ if (connectionPool == null) {
+ LOGGER.error("JDBC connection pool {} is not found in any J2EE application servers", connectionPoolName);
+ throw new UpdateException("JDBC connection pool " + connectionPoolName + " is not found in any J2EE application servers");
+ }
+ user = VariableUtils.replace(connectionPool.getUser(), environment.getVariables());
+ password = VariableUtils.replace(connectionPool.getPassword(), environment.getVariables());
+ driver = VariableUtils.replace(connectionPool.getDriver(), environment.getVariables());
+ url = VariableUtils.replace(connectionPool.getUrl(), environment.getVariables());
+ } else {
+ // use the database connection data
+ user = VariableUtils.replace(database.getUser(), environment.getVariables());
+ password = VariableUtils.replace(database.getPassword(), environment.getVariables());
+ driver = VariableUtils.replace(database.getDriver(), environment.getVariables());
+ url = VariableUtils.replace(database.getJdbcurl(), environment.getVariables());
+ }
+ // execute SQL script using JDBC
+ SqlScriptUtils.executeUsingJdbc(singleSqlScriptRuntime, driver, user, password, url);
+ }
+ // add message
+ updateLog.setStatus("Update performed");
+ updateLog.setUpdated(true);
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + sqlScript.getName() + " executed"));
+ EventUtils.post(environment, "UPDATE", "SQL script " + sqlScript.getName() + " executed");
+ LOGGER.info("SQL script " + sqlScript.getName() + " executed");
+ }
+ } catch (Exception e) {
+ // SQL script execution failed, delete the SQL script from the cache
+ try {
+ fileManipulator.delete(sqlScriptRuntime);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.warn("Can't delete SQL script cache", fileManipulatorException);
+ }
+ LOGGER.error("SQL script {} execution failed", sqlScript.getName(), e);
+ throw new UpdateException("SQL script " + sqlScript.getName() + " execution failed", e);
+ }
+ }
+ } else {
+ // the user provided a single SQL script
+
+ // change mappings into the SQL script
+ LOGGER.debug("Replacing mappings into the SQL script {}", sqlScript.getName());
+ for (Iterator mappingIterator = sqlScript.getMappings().iterator(); mappingIterator.hasNext(); ) {
+ Mapping mapping = (Mapping) mappingIterator.next();
+ FileManipulator.searchAndReplace(mapping.getKey(), mapping.getValue(), sqlScriptCache);
+ }
+
+ // compare the SQL script origin with the runtime one
+ try {
+ if (!fileManipulator.contentEquals(sqlScriptCache, sqlScriptRuntime)) {
+ // the SQL script needs to be executed
+ LOGGER.debug("The SQL script {} needs to be executed", sqlScript.getName());
+ // copy the SQL script cache to the runtime
+ LOGGER.debug("Copy the SQL script cache to the runtime");
+ fileManipulator.copy(sqlScriptCache, sqlScriptRuntime);
+ if (database.getSqlCommand() != null && database.getSqlCommand().trim().length() > 0) {
+ // execute the SQL script using a command
+ LOGGER.info("Executing the SQL script using a system command");
+ String command = VariableUtils.replace(database.getSqlCommand(), environment.getVariables());
+ String output = SqlScriptUtils.executeUsingCommand(sqlScriptRuntime, command);
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + sqlScript.getName() + " executed: " + output));
+ EventUtils.post(environment, "UPDATE", "SQL script " + sqlScript.getName() + " executed: " + output);
+ LOGGER.info("SQL script " + sqlScript.getName() + " executed: " + output);
+ } else {
+ // execute SQL script using JDBC
+ LOGGER.info("Executing SQL script using JDBC");
+ String user = null;
+ String password = null;
+ String driver = null;
+ String url = null;
+ if (database.getConnectionPool() != null && database.getConnectionPool().trim().length() > 0) {
+ // the database has a reference to an existing connection pool
+ LOGGER.debug("Database has a reference to a connection pool");
+ // looking for the connection pool definition
+ String connectionPoolName = VariableUtils.replace(database.getConnectionPool(), environment.getVariables());
+ JDBCConnectionPool connectionPool = null;
+ for (Iterator applicationServerIterator = environment.getJ2EEApplicationServers().getJ2EEApplicationServers().iterator(); applicationServerIterator.hasNext(); ) {
+ J2EEApplicationServer applicationServer = (J2EEApplicationServer) applicationServerIterator.next();
+ connectionPool = applicationServer.getJDBCConnectionPool(connectionPoolName);
+ if (connectionPool != null) {
+ break;
+ }
+ }
+ if (connectionPool == null) {
+ LOGGER.error("JDBC connection pool {} is not found in any J2EE application servers", connectionPoolName);
+ throw new UpdateException("JDBC connection pool " + connectionPoolName + " is not found in any J2EE application servers");
+ }
+ user = VariableUtils.replace(connectionPool.getUser(), environment.getVariables());
+ password = VariableUtils.replace(connectionPool.getPassword(), environment.getVariables());
+ driver = VariableUtils.replace(connectionPool.getDriver(), environment.getVariables());
+ url = VariableUtils.replace(connectionPool.getUrl(), environment.getVariables());
+ } else {
+ // use the database data
+ LOGGER.debug("Use database data definition");
+ user = VariableUtils.replace(database.getUser(), environment.getVariables());
+ password = VariableUtils.replace(database.getPassword(), environment.getVariables());
+ driver = VariableUtils.replace(database.getDriver(), environment.getVariables());
+ url = VariableUtils.replace(database.getJdbcurl(), environment.getVariables());
+ }
+ // execute SQL script
+ SqlScriptUtils.executeUsingJdbc(sqlScriptRuntime, driver, user, password, url);
+ }
+ // add log messages
+ updateLog.setStatus("Update performed");
+ updateLog.setUpdated(true);
+ updateLog.addUpdateMessage(new UpdateMessage("info", "SQL script " + sqlScript.getName() + " executed"));
+ EventUtils.post(environment, "UPDATE", "SQL script " + sqlScript.getName() + " executed");
+ LOGGER.info("SQL script " + sqlScript.getName() + " executed");
+ }
+ } catch (Exception e) {
+ // SQL script execution failed, delete SQL script from the cache
+ try {
+ fileManipulator.delete(sqlScriptRuntime);
+ } catch (FileManipulatorException fileManipulatorException) {
+ LOGGER.warn("Can't delete SQL script cache", fileManipulatorException);
+ }
+ LOGGER.error("SQL script {} execution failed", sqlScript.getName(), e);
+ throw new UpdateException("SQL script " + sqlScript.getName() + " execution failed", e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
Added: incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/utils/EventUtils.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/utils/EventUtils.java?rev=1189084&view=auto
==============================================================================
--- incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/utils/EventUtils.java (added)
+++ incubator/kalumet/trunk/agent/src/main/java/org/apache/kalumet/agent/utils/EventUtils.java Wed Oct 26 08:52:32 2011
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kalumet.agent.utils;
+
+import org.apache.kalumet.KalumetException;
+import org.apache.kalumet.agent.Configuration;
+import org.apache.kalumet.model.Environment;
+import org.apache.kalumet.model.Kalumet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Agent utils method to post event.
+ */
+public class EventUtils {
+
+ private final static transient Logger LOGGER = LoggerFactory.getLogger(EventUtils.class);
+
+ /**
+ * Wrapper method to post an event.
+ *
+ * @param environment the target environment.
+ * @param author the event author.
+ * @param severity the event severity.
+ * @param event the event message.
+ */
+ public static void post(Environment environment, String author, String severity, String event) {
+ LOGGER.debug("Loading configuration from the cache");
+ Kalumet kalumet = Configuration.CONFIG_CACHE;
+ if (kalumet == null) {
+ LOGGER.debug("No configuration in cache, updating it");
+ try {
+ kalumet = Kalumet.digeste(Configuration.CONFIG_LOCATION);
+ } catch (KalumetException kalumetException) {
+ LOGGER.warn("Can't post journal event", kalumetException);
+ return;
+ }
+ Configuration.CONFIG_CACHE = kalumet;
+ }
+ org.apache.kalumet.utils.EventUtils.post(environment, author, severity, event, kalumet);
+ }
+
+ /**
+ * Wrapper method to post an event.
+ *
+ * @param environment the target environment.
+ * @param severity the event severity.
+ * @param event the event message.
+ */
+ public static void post(Environment environment, String severity, String event) {
+ EventUtils.post(environment, Configuration.AGENT_ID, severity, event);
+ }
+
+}
Modified: incubator/kalumet/trunk/common/src/main/java/org/apache/kalumet/FileManipulator.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/common/src/main/java/org/apache/kalumet/FileManipulator.java?rev=1189084&r1=1189083&r2=1189084&view=diff
==============================================================================
--- incubator/kalumet/trunk/common/src/main/java/org/apache/kalumet/FileManipulator.java (original)
+++ incubator/kalumet/trunk/common/src/main/java/org/apache/kalumet/FileManipulator.java Wed Oct 26 08:52:32 2011
@@ -466,7 +466,7 @@ public class FileManipulator {
* @return the environment j2EEApplication cache directory path.
* @throws FileManipulatorException in case of creation failure.
*/
- public static String createEnvironmentApplicationCacheDir(Environment environment, J2EEApplication j2EEApplication) throws FileManipulatorException {
+ public static String createJ2EEApplicationCacheDir(Environment environment, J2EEApplication j2EEApplication) throws FileManipulatorException {
String directory = FileManipulator.createEnvironmentCacheDir(environment);
directory = directory + "/applications/" + j2EEApplication.getName();
FileManipulator fileManipulator = FileManipulator.getInstance();
@@ -482,7 +482,7 @@ public class FileManipulator {
* @return the environment software cache directory path.
* @throws FileManipulatorException in case of creation failure.
*/
- public static String createEnvironmentSoftwareCacheDir(Environment environment, Software software) throws FileManipulatorException {
+ public static String createSoftwareCacheDir(Environment environment, Software software) throws FileManipulatorException {
String directory = FileManipulator.createEnvironmentCacheDir(environment);
directory = directory + "/softwares/" + software.getName();
FileManipulator fileManipulator = FileManipulator.getInstance();
Added: incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptRunnerUtils.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptRunnerUtils.java?rev=1189084&view=auto
==============================================================================
--- incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptRunnerUtils.java (added)
+++ incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptRunnerUtils.java Wed Oct 26 08:52:32 2011
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kalumet.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.sql.*;
+
+public class SqlScriptRunnerUtils {
+
+ private final static transient Logger LOGGER = LoggerFactory.getLogger(SqlScriptRunnerUtils.class);
+
+ private static final String DEFAULT_DELIMITER = ";";
+
+ private Connection connection;
+
+ private boolean stopOnError = false;
+ private boolean autoCommit = false;
+
+ private String delimiter = DEFAULT_DELIMITER;
+ private boolean fullLineDelimiter = false;
+
+ public SqlScriptRunnerUtils(Connection connection) {
+ this.connection = connection;
+ }
+
+ public void setStopOnError(boolean stopOnError) {
+ this.stopOnError = stopOnError;
+ }
+
+ public void setAutoCommit(boolean autoCommit) {
+ this.autoCommit = autoCommit;
+ }
+
+ public void setDelimiter(String delimiter) {
+ this.delimiter = delimiter;
+ }
+
+ public void setFullLineDelimiter(boolean fullLineDelimiter) {
+ this.fullLineDelimiter = fullLineDelimiter;
+ }
+
+ public void runScript(Reader reader) throws Exception {
+ runScriptWithConnection(connection, reader);
+ }
+
+ public void closeConnection() {
+ try {
+ connection.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Execute an SQL script (read in using the Reader parameter) using the connection passed in.
+ *
+ * @param conn the connection to use for the script.
+ * @param reader the source of the script.
+ * @throws java.sql.SQLException if any SQL errors occur.
+ * @throws java.io.IOException if there is an error reading from the Reader.
+ */
+ private void runScriptWithConnection(Connection conn, Reader reader) throws Exception {
+ StringBuffer command = null;
+ try {
+ BufferedReader lineReader = new BufferedReader(reader);
+ String line;
+ while ((line = lineReader.readLine()) != null) {
+ if (command == null) {
+ command = new StringBuffer();
+ }
+ String trimmedLine = line.trim();
+ if (trimmedLine.length() < 1) {
+ // do nothing
+ } else if (trimmedLine.startsWith("//") || trimmedLine.startsWith("--")) {
+ LOGGER.info(trimmedLine);
+ } else if (!fullLineDelimiter && trimmedLine.endsWith(delimiter)
+ || fullLineDelimiter && trimmedLine.equals(delimiter)) {
+ command.append(line.substring(0, line.lastIndexOf(delimiter)));
+ command.append(" ");
+ Statement statement = conn.createStatement();
+
+ LOGGER.info(command.toString());
+
+ if (stopOnError) {
+ statement.execute(command.toString());
+ } else {
+ try {
+ statement.execute(command.toString());
+ } catch (SQLException e) {
+ e.fillInStackTrace();
+ LOGGER.warn("Error executing SQL {}", command);
+ }
+ }
+
+ if (autoCommit && !conn.getAutoCommit()) {
+ conn.commit();
+ }
+
+ command = null;
+ try {
+ statement.close();
+ } catch (Exception e) {
+ // ignore to workaround a bug in Jakarta DBCP
+ }
+ Thread.yield();
+ } else {
+ command.append(line);
+ command.append(" ");
+ }
+ }
+ if (!autoCommit && !conn.getAutoCommit()) {
+ conn.commit();
+ }
+ } catch (Exception e) {
+ LOGGER.error("Error executing SQL {}", command, e);
+ throw e;
+ } finally {
+ conn.rollback();
+ }
+ }
+
+}
+
Added: incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptUtils.java
URL: http://svn.apache.org/viewvc/incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptUtils.java?rev=1189084&view=auto
==============================================================================
--- incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptUtils.java (added)
+++ incubator/kalumet/trunk/utils/src/main/java/org/apache/kalumet/utils/SqlScriptUtils.java Wed Oct 26 08:52:32 2011
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.kalumet.utils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.sql.DriverManager;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kalumet.KalumetException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SQL script execution utils.
+ */
+public class SqlScriptUtils {
+
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(SqlScriptUtils.class);
+
+ /**
+ * Execute a SQL script using a system command.
+ *
+ * @param path the SQL script path.
+ * @param command the system command to use for SQL script execution.
+ * @return the SQL script execution output.
+ * @throws KalumetException in case of error during the SQL script execution.
+ */
+ public static String executeUsingCommand(String path, String command) throws KalumetException {
+ LOGGER.info("Executing SQL script {} using command {}", path, command);
+ // replace %s by the SQL script path in the command
+ LOGGER.debug("Replacing %s by the SQL script path in the command");
+ String execCommand = StringUtils.replace(command, "%s", path);
+ LOGGER.debug("Executing the SQL command");
+ String output = null;
+ try {
+ output = CommandUtils.execute(execCommand);
+ } catch (KalumetException kalumetException) {
+ LOGGER.error("SQL script {} execution failed", path, kalumetException);
+ throw new KalumetException("SQL script " + path + " execution failed", kalumetException);
+ }
+ return output;
+ }
+
+ /**
+ * Execute a SQL script using a JDBC connection.
+ *
+ * @param path the SQL script path.
+ * @param driver the JDBC connection driver class name.
+ * @param user the JDBC connection user name.
+ * @param password the JDBC connection user password.
+ * @param url the JDBC connection URL.
+ * @throws KalumetException in case of error during the SQL script execution.
+ */
+ public static void executeUsingJdbc(String path, String driver, String user, String password, String url) throws KalumetException {
+ LOGGER.info("Executing SQL script {} using JDBC connection {}", path, url);
+ Connection connection = null;
+ try {
+ // creates JDBC connection.
+ LOGGER.debug("Creating JDBC connection");
+ connection = SqlScriptUtils.getConnection(driver, user, password, url);
+ // creates the SQL script buffered reader.
+ LOGGER.debug("Creating the SQL script buffered reader");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(path))));
+ // uses the SQL script runner
+ LOGGER.debug("Call SQL script runner");
+ SqlScriptRunnerUtils sqlScriptRunner = new SqlScriptRunnerUtils(connection);
+ sqlScriptRunner.setAutoCommit(true);
+ sqlScriptRunner.setStopOnError(true);
+ sqlScriptRunner.runScript(reader);
+ } catch (Exception e) {
+ LOGGER.error("SQL script {} execution failed", path, e);
+ throw new KalumetException("SQL script " + path + " execution failed", e);
+ } finally {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (Exception e) {
+ LOGGER.warn("Can't close the JDBC connection", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a JDBC connection.
+ *
+ * @param driver the JDBC driver class name.
+ * @param user the JDBC user name.
+ * @param password the JDBC user password.
+ * @param url the JDBC URL.
+ * @return the JDBC connection.
+ */
+ private static Connection getConnection(String driver, String user, String password, String url) throws KalumetException {
+ try {
+ Class.forName(driver);
+ return DriverManager.getConnection(url, user, password);
+ } catch (Exception e) {
+ LOGGER.error("Can't create JDBC connection", e);
+ throw new KalumetException("Can't create JDBC connection", e);
+ }
+ }
+
+}