bug 11043: rverted the bad fix

This commit is contained in:
Alex Huang 2011-08-11 10:25:10 -07:00
parent 278f2a401f
commit 1079a77024
5 changed files with 208 additions and 85 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<String, Object> details;
public CloudExecutionException(ErrorCode code, String message, Throwable cause) {
super(message, cause);
this.code = code;
details = new HashMap<String, Object>();
}
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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
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<ErrorCode> s_codes = new HashSet<ErrorCode>();
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");
}

View File

@ -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);
}

View File

@ -687,7 +687,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();
@ -929,6 +929,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
try {
if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
@ -939,66 +940,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<T> profile = new VirtualMachineProfileImpl<T>(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<T>(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<T>(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.");
}
@ -1467,7 +1457,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
return commands;
}
protected Map<Long, AgentVmInfo> convertDeltaToInfos(final Map<String, State> states) {
final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
@ -1498,7 +1488,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
return map;
}
protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, VmState> states) {
final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
@ -1701,7 +1691,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
public Commands fullSync(final long hostId, StartupRoutingCommand startup) {
Commands commands = new Commands(OnError.Continue);
Map<Long, AgentVmInfo> infos = convertToInfos(startup.getVmStates());
if( startup.isPoolSync()) {
@ -1728,7 +1718,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);
@ -1738,13 +1728,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);
@ -1752,15 +1742,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()) {
@ -1769,10 +1759,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));
@ -1940,7 +1930,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
this.guru = (VirtualMachineGuru<VMInstanceVO>) guru;
this.host = host;
}
public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state) {
this(name, guru, vm, state, null);
}

View File

@ -64,4 +64,5 @@ 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 CloudExecutionException = Base | 0x27;
}