diff --git a/api/src/com/cloud/exception/CloudExecutionException.java b/api/src/com/cloud/exception/CloudExecutionException.java
new file mode 100755
index 00000000000..979043289e4
--- /dev/null
+++ b/api/src/com/cloud/exception/CloudExecutionException.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It 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 any later version.
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.exception;
+
+import java.util.HashMap;
+
+import com.cloud.utils.SerialVersionUID;
+
+/**
+ * CloudExecutionException is a generic exception thrown by components in
+ * CloudStack. It indicates an error in the execution of the business logic.
+ * When using this exception, it is important to give detail information
+ * about the error. At the entry points, this exception is caught but the
+ * stack trace is not logged so the information has to be detail enough
+ * that one can find out what the error is simply by reading the error message.
+ *
+ */
+public class CloudExecutionException extends RuntimeException {
+ private final static long serialVersionUID = SerialVersionUID.CloudExecutionException;
+
+ private final ErrorCode code;
+ private final HashMap details;
+
+ public CloudExecutionException(ErrorCode code, String message, Throwable cause) {
+ super(message, cause);
+ this.code = code;
+ details = new HashMap();
+ }
+
+ public ErrorCode getErrorCode() {
+ return code;
+ }
+
+ public String getErrorMessage() {
+ return new StringBuilder("Error Code=").append(code).append("; Error Message=").append(super.toString()).toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+ buff.append("Error Code=").append(code);
+ buff.append("; Error Message=").append(super.toString());
+ if (details.size() > 0) {
+ buff.append("; Error Details=").append(details.toString());
+ }
+ return buff.toString();
+ }
+}
diff --git a/api/src/com/cloud/exception/ErrorCode.java b/api/src/com/cloud/exception/ErrorCode.java
new file mode 100755
index 00000000000..046443c0bad
--- /dev/null
+++ b/api/src/com/cloud/exception/ErrorCode.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved
+ *
+ * This software is licensed under the GNU General Public License v3 or later.
+ *
+ * It 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 any later version.
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.cloud.exception;
+
+import java.util.HashSet;
+
+/**
+ * ErrorCode is a standard error code given by the API to represent the error.
+ */
+public class ErrorCode {
+ String code;
+ private static HashSet s_codes = new HashSet();
+
+ public ErrorCode(String code) {
+ this.code = code;
+ assert !s_codes.contains(this) : "There is already an error code registered for this code: " + code;
+ s_codes.add(this);
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public int hashCode() {
+ return code.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (!(that instanceof ErrorCode)) {
+ return false;
+ }
+
+ return this.code.equals(((ErrorCode)that).code);
+ }
+
+ public final static ErrorCode UnableToReachResource = new ErrorCode("resource.unavailable");
+}
diff --git a/api/src/com/cloud/network/guru/NetworkGuru.java b/api/src/com/cloud/network/guru/NetworkGuru.java
index 5ead472300e..b2d2842b82f 100644
--- a/api/src/com/cloud/network/guru/NetworkGuru.java
+++ b/api/src/com/cloud/network/guru/NetworkGuru.java
@@ -52,29 +52,37 @@ public interface NetworkGuru extends Adapter {
* @return NetworkConfiguration
*/
Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner);
-
+
/**
- * allocate a nic in this network. This method implementation cannot take a long time as
- * it is meant to allocate for the DB.
- * @param network configuration to allocate the nic in.
- * @param nic user specified
- * @param vm virtual machine the network configuraiton will be in.
+ * allocate a nic in this network. This method implementation cannot take a long time as it is meant to allocate for
+ * the DB.
+ *
+ * @param network
+ * configuration to allocate the nic in.
+ * @param nic
+ * user specified
+ * @param vm
+ * virtual machine the network configuration will be in.
* @return NicProfile.
* @throws InsufficientVirtualNetworkCapcityException
* @throws InsufficientAddressCapacityException
*/
NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile extends VirtualMachine> vm) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException;
-
+
/**
* Fully implement the network configuration as specified.
- * @param network network configuration
- * @param offering offering that the network configuration was based on.
- * @param destination where were deploying to.
+ *
+ * @param network
+ * network configuration
+ * @param offering
+ * offering that the network configuration was based on.
+ * @param destination
+ * where were deploying to.
* @return a fully implemented NetworkConfiguration.
- * @throws InsufficientVirtualNetworkCapcityException TODO
+ * @throws InsufficientVirtualNetworkCapcityException
*/
Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context) throws InsufficientVirtualNetworkCapcityException;
-
+
/**
* reserve a nic for this VM in this network.
* @param nic
@@ -89,13 +97,20 @@ public interface NetworkGuru extends Adapter {
void reserve(NicProfile nic, Network network, VirtualMachineProfile extends VirtualMachine> vm, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException;
boolean release(NicProfile nic, VirtualMachineProfile extends VirtualMachine> vm, String reservationId);
-
+
void deallocate(Network network, NicProfile nic, VirtualMachineProfile extends VirtualMachine> vm);
-
+
+ /**
+ * @deprecated This method should not be here in the first place. What does this really mean? Is it always persisted
+ * in the nic? When is it persisted in the nic? When is it called? No Idea.
+ * @param profile
+ * @param network
+ */
+ @Deprecated
void updateNicProfile(NicProfile profile, Network network);
-
+
void shutdown(NetworkProfile network, NetworkOffering offering);
-
+
/**
* Throw away the design.
* @param network
@@ -104,7 +119,7 @@ public interface NetworkGuru extends Adapter {
* @return
*/
boolean trash(Network network, NetworkOffering offering, Account owner);
-
+
void updateNetworkProfile(NetworkProfile networkProfile);
-
+
}
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 64f3f20ca0c..0e70a7c2e5b 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -684,7 +684,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
if (dest == null) {
- throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
+ throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId());
}
long destHostId = dest.getHost().getId();
@@ -926,6 +926,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
VirtualMachineGuru vmGuru = getVmGuru(vm);
+ VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
try {
if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
@@ -936,66 +937,55 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
throw new CloudRuntimeException("We cannot stop " + vm + " when it is in state " + vm.getState());
}
s_logger.debug("Unable to transition the state but we're moving on because it's forced stop");
- }
-
- VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm);
- if ((vm.getState() == State.Starting || vm.getState() == State.Stopping || vm.getState() == State.Migrating) && forced) {
- ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
- if (work == null) {
- if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) {
- try {
- return stateTransitTo(vm, Event.AgentReportStopped, null);
- } catch (NoTransitionException e) {
- s_logger.warn("Unable to cleanup " + vm);
- return false;
- }
- }
- } else {
- try {
- return stateTransitTo(vm, Event.AgentReportStopped, null);
- } catch (NoTransitionException e) {
- s_logger.warn("Unable to cleanup " + vm);
- return false;
- }
- }
- }
-
- if (vm.getHostId() != null) {
- String routerPrivateIp = null;
- if (vm.getType() == VirtualMachine.Type.DomainRouter) {
- routerPrivateIp = vm.getPrivateIpAddress();
- }
- StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null, routerPrivateIp);
- boolean stopped = false;
- StopAnswer answer = null;
- try {
- answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
- stopped = answer.getResult();
- if (!stopped) {
- throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
- }
- vmGuru.finalizeStop(profile, answer);
-
- } catch (AgentUnavailableException e) {
- } catch (OperationTimedoutException e) {
- } finally {
- if (!stopped) {
- if (!forced) {
- s_logger.warn("Unable to stop vm " + vm);
+ if (state == State.Starting || state == State.Stopping || state == State.Migrating) {
+ ItWorkVO work = _workDao.findByOutstandingWork(vm.getId(), vm.getState());
+ if (work != null) {
+ if (cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.StopRequested, forced, user, account)) {
try {
- stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
+ return stateTransitTo(vm, Event.AgentReportStopped, null);
} catch (NoTransitionException e) {
- s_logger.warn("Unable to transition the state " + vm);
+ s_logger.warn("Unable to cleanup " + vm);
+ return false;
}
- return false;
- } else {
- s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
- vmGuru.finalizeStop(profile, answer);
}
}
}
}
+ String routerPrivateIp = null;
+ if (vm.getType() == VirtualMachine.Type.DomainRouter) {
+ routerPrivateIp = vm.getPrivateIpAddress();
+ }
+ StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null, routerPrivateIp);
+ boolean stopped = false;
+ StopAnswer answer = null;
+ try {
+ answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
+ stopped = answer.getResult();
+ if (!stopped) {
+ throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
+ }
+ vmGuru.finalizeStop(profile, answer);
+
+ } catch (AgentUnavailableException e) {
+ } catch (OperationTimedoutException e) {
+ } finally {
+ if (!stopped) {
+ if (!forced) {
+ s_logger.warn("Unable to stop vm " + vm);
+ try {
+ stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
+ } catch (NoTransitionException e) {
+ s_logger.warn("Unable to transition the state " + vm);
+ }
+ return false;
+ } else {
+ s_logger.warn("Unable to actually stop " + vm + " but continue with release because it's a force stop");
+ vmGuru.finalizeStop(profile, answer);
+ }
+ }
+ }
+
if (s_logger.isDebugEnabled()) {
s_logger.debug(vm + " is stopped on the host. Proceeding to release resource held.");
}
@@ -1464,7 +1454,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
return commands;
}
-
+
protected Map convertDeltaToInfos(final Map states) {
final HashMap map = new HashMap();
@@ -1495,7 +1485,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
return map;
}
-
+
protected Map convertToInfos(final Map states) {
final HashMap map = new HashMap();
@@ -1698,7 +1688,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
public Commands fullSync(final long hostId, StartupRoutingCommand startup) {
-
+
Commands commands = new Commands(OnError.Continue);
Map infos = convertToInfos(startup.getVmStates());
if( startup.isPoolSync()) {
@@ -1725,7 +1715,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
hId = host.getId();
}
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
-
+
Command command = compareState(hId, castedVm, info, true, hvGuru.trackVmHostChange());
if (command != null) {
commands.addCommand(command);
@@ -1735,13 +1725,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
s_logger.warn("Stopping a VM that we have no record of: " + left.name);
commands.addCommand(cleanup(left.name));
}
-
+
} else {
final List extends VMInstanceVO> vms = _vmDao.listByHostId(hostId);
s_logger.debug("Found " + vms.size() + " VMs for host " + hostId);
for (VMInstanceVO vm : vms) {
AgentVmInfo info = infos.remove(vm.getId());
-
+
VMInstanceVO castedVm = null;
if (info == null) {
info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
@@ -1749,15 +1739,15 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
} else {
castedVm = info.vm;
}
-
+
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType());
-
+
Command command = compareState(hostId, castedVm, info, true, hvGuru.trackVmHostChange());
if (command != null) {
commands.addCommand(command);
}
}
-
+
for (final AgentVmInfo left : infos.values()) {
boolean found = false;
for (VirtualMachineGuru extends VMInstanceVO> vmGuru : _vmGurus.values()) {
@@ -1766,10 +1756,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
found = true;
HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
if(hvGuru.trackVmHostChange()) {
- Command command = compareState(hostId, vm, left, true, true);
- if (command != null) {
- commands.addCommand(command);
- }
+ Command command = compareState(hostId, vm, left, true, true);
+ if (command != null) {
+ commands.addCommand(command);
+ }
} else {
s_logger.warn("Stopping a VM, VM " + left.name + " migrate from Host " + vm.getHostId() + " to Host " + hostId );
commands.addCommand(cleanup(left.name));
@@ -1937,7 +1927,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
this.guru = (VirtualMachineGuru) guru;
this.host = host;
}
-
+
public AgentVmInfo(String name, VirtualMachineGuru extends VMInstanceVO> guru, VMInstanceVO vm, State state) {
this(name, guru, vm, state, null);
}
diff --git a/utils/src/com/cloud/utils/SerialVersionUID.java b/utils/src/com/cloud/utils/SerialVersionUID.java
index bbc401d5281..5bfbb84b339 100755
--- a/utils/src/com/cloud/utils/SerialVersionUID.java
+++ b/utils/src/com/cloud/utils/SerialVersionUID.java
@@ -64,5 +64,6 @@ public interface SerialVersionUID {
public static final long VirtualMachineMigrationException = Base | 0x24;
public static final long DiscoveredWithErrorException = Base | 0x25;
public static final long NoTransitionException = Base | 0x26;
- public static final long CallFailedException = Base | 0x26;
+ public static final long CloudExecutionException = Base | 0x27;
+ public static final long CallFailedException = Base | 0x28;
}