bug 7811: Start domR/Dhcp if it's not running when do userVmReboot

status 7811: resolved fixed

Other fixes:
* vmExpunge: cleanup LB/PF rules after vm was marked as Expunging in the DB to avoid the situation when user recovers a vm in the middle of expunge job.
This commit is contained in:
alena 2011-01-24 16:53:00 -08:00
parent 2466589e2f
commit 0e4196448a
13 changed files with 153 additions and 48 deletions

View File

@ -28,6 +28,8 @@ import com.cloud.api.ServerApiException;
import com.cloud.api.response.UserVmResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -89,7 +91,7 @@ public class RebootVMCmd extends BaseAsyncCmd {
}
@Override
public void execute(){
public void execute() throws ResourceUnavailableException, InsufficientCapacityException{
UserVm result = _userVmService.rebootVirtualMachine(this);
if (result !=null){
UserVmResponse response = _responseGenerator.createUserVmResponse(result);

View File

@ -30,6 +30,8 @@ import com.cloud.api.ServerApiException;
import com.cloud.api.response.UserVmResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
@ -107,7 +109,7 @@ public class ResetVMPasswordCmd extends BaseAsyncCmd {
Random _rand = new Random(System.currentTimeMillis());
@Override
public void execute(){
public void execute() throws ResourceUnavailableException, InsufficientCapacityException{
password = Long.toHexString(_rand.nextLong());
UserVm result = _userVmService.resetVMPassword(this, password);
if (result != null){

View File

@ -73,7 +73,7 @@ public interface UserVmService {
* @param cmd - the command specifying vmId, password
* @return the VM if reset worked successfully, null otherwise
*/
UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password);
UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException;
/**
* Attaches the specified volume to the specified VM
@ -93,7 +93,7 @@ public interface UserVmService {
UserVm startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException;
UserVm stopVirtualMachine(StopVMCmd cmd) throws ServerApiException, ConcurrentOperationException;
UserVm rebootVirtualMachine(RebootVMCmd cmd);
UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
UserVm updateVirtualMachine(UpdateVMCmd cmd);
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;

View File

@ -19,6 +19,7 @@ package com.cloud.configuration;
import java.util.List;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO;
@ -175,5 +176,9 @@ public interface ConfigurationManager extends ConfigurationService, Manager {
DataCenterVO getZone(long id);
HostPodVO getPod(long id);
ClusterVO getCluster(long id);
boolean deleteAccountSpecificVirtualRanges(long accountId);
}

View File

@ -58,6 +58,7 @@ import com.cloud.api.commands.UpdateZoneCmd;
import com.cloud.configuration.ResourceCount.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterIpAddressVO;
@ -69,6 +70,7 @@ import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl;
@ -158,6 +160,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@Inject SecondaryStorageVmDao _secStorageDao;
@Inject AccountManager _accountMgr;
@Inject NetworkManager _networkMgr;
@Inject ClusterDao _clusterDao;
@Inject(adapter=SecurityChecker.class)
Adapters<SecurityChecker> _secChecker;
@ -2707,4 +2710,14 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
}
return result;
}
@Override
public HostPodVO getPod(long id) {
return _podDao.findById(id);
}
@Override
public ClusterVO getCluster(long id) {
return _clusterDao.findById(id);
}
}

View File

@ -109,6 +109,8 @@ public interface NetworkManager extends NetworkService {
void cleanupNics(VirtualMachineProfile<? extends VMInstanceVO> vm);
void expungeNics(VirtualMachineProfile<? extends VMInstanceVO> vm);
List<? extends Nic> getNics(VirtualMachine vm);
List<AccountVO> getAccountsUsingNetwork(long configurationId);

View File

@ -1259,6 +1259,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
}
@Override
public void expungeNics(VirtualMachineProfile<? extends VMInstanceVO> vm) {
List<NicVO> nics = _nicDao.listIncludingRemovedBy(vm.getId());
for (NicVO nic : nics) {
_nicDao.expunge(nic.getId());
}
}
@Override
public Network createNetwork(CreateNetworkCmd cmd) throws InvalidParameterValueException, PermissionDeniedException {
Long networkOfferingId = cmd.getNetworkOfferingId();

View File

@ -208,10 +208,15 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
_lb2VmMapDao.persist(map);
s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId);
}
applyLoadBalancerConfig(loadBalancerId);
_lb2VmMapDao.remove(loadBalancerId, instanceIds, null);
s_logger.debug("Load balancer rule id " + loadBalancerId + " is removed for vms " + instanceIds);
if (applyLoadBalancerConfig(loadBalancerId)) {
_lb2VmMapDao.remove(loadBalancerId, instanceIds, null);
s_logger.debug("Load balancer rule id " + loadBalancerId + " is removed for vms " + instanceIds);
} else {
s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds);
throw new CloudRuntimeException("Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds);
}
} catch (ResourceUnavailableException e) {
s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e);
return false;
@ -418,7 +423,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
String dstIp = null;
for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) {
UserVm vm = _vmDao.findById(lbVmMap.getInstanceId());
Nic nic = _nicDao.findByInstanceIdAndNetworkId(lb.getNetworkId(), vm.getId());
Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId());
dstIp = nic.getIp4Address();
LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke());
dstList.add(lbDst);

View File

@ -44,8 +44,6 @@ import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.GetVmStatsAnswer;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SnapshotCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
@ -85,6 +83,7 @@ import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.VlanDao;
@ -237,6 +236,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Inject AccountService _accountService;
@Inject AsyncJobManager _asyncMgr;
@Inject VlanDao _vlanDao;
@Inject ClusterDao _clusterDao;
@Inject AccountVlanMapDao _accountVlanMapDao;
@Inject StoragePoolDao _storagePoolDao;
@Inject VMTemplateHostDao _vmTemplateHostDao;
@ -281,7 +281,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
@Override
public UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password){
public UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException{
Account account = UserContext.current().getCaller();
Long userId = UserContext.current().getCallerUserId();
Long vmId = cmd.getId();
@ -313,7 +313,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
return userVm;
}
private boolean resetVMPasswordInternal(ResetVMPasswordCmd cmd, String password) {
private boolean resetVMPasswordInternal(ResetVMPasswordCmd cmd, String password) throws ResourceUnavailableException, InsufficientCapacityException{
return true;
// Long vmId = cmd.getId();
// Long userId = UserContext.current().getCallerUserId();
@ -331,7 +332,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// }
// if (_routerMgr.savePasswordToRouter(vmInstance.getDomainRouterId(), vmInstance.getPrivateIpAddress(), password)) {
// // Need to reboot the virtual machine so that the password gets redownloaded from the DomR, and reset on the VM
// if (!rebootVirtualMachine(userId, vmId)) {
// if (rebootVirtualMachine(userId, vmId) == null) {
// if (vmInstance.getState() == State.Stopped) {
// return true;
// }
@ -785,25 +786,21 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
private boolean rebootVirtualMachine(long userId, long vmId) {
private UserVm rebootVirtualMachine(long userId, long vmId) throws InsufficientCapacityException, ResourceUnavailableException{
UserVmVO vm = _vmDao.findById(vmId);
User caller = _accountMgr.getActiveUser(userId);
Account owner = _accountMgr.getAccount(vm.getAccountId());
if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging || vm.getRemoved() != null) {
return false;
s_logger.warn("Vm id=" + vmId + " doesn't exist");
return null;
}
if (vm.getState() == State.Running && vm.getHostId() != null) {
RebootCommand cmd = new RebootCommand(vm.getInstanceName());
RebootAnswer answer = (RebootAnswer)_agentMgr.easySend(vm.getHostId(), cmd);
if (answer != null) {
return true;
} else {
return false;
}
return _itMgr.reboot(vm, null, caller, owner);
} else {
s_logger.error("Vm id=" + vmId + " is not in Running state, failed to reboot");
return false;
return null;
}
}
@Override
@ -1142,9 +1139,17 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
public boolean expunge(UserVmVO vm, long callerUserId, Account caller) {
try {
//Cleanup LB/PF rules before expunging the vm
long vmId = vm.getId();
//cleanup port forwarding rules
if (!_itMgr.advanceExpunge(vm, _accountMgr.getSystemUser(), caller)) {
s_logger.info("Did not expunge " + vm);
return false;
}
_networkGroupMgr.removeInstanceFromGroups(vm.getId());
removeInstanceFromGroup(vm.getId());
//Cleanup LB/PF rules before expunging the vm
long vmId = vm.getId();
//cleanup port forwarding rules
if (_rulesMgr.revokePortForwardingRule(vmId)) {
s_logger.debug("Port forwarding rules are removed successfully as a part of vm id=" + vmId + " expunge");
} else {
@ -1157,16 +1162,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
} else {
s_logger.warn("Fail to remove lb rules as a part of vm id=" + vmId + " expunge");
}
if (!_itMgr.advanceExpunge(vm, _accountMgr.getSystemUser(), caller)) {
s_logger.info("Did not expunge " + vm);
return false;
}
_networkGroupMgr.removeInstanceFromGroups(vm.getId());
removeInstanceFromGroup(vm.getId());
_itMgr.remove(vm, _accountMgr.getSystemUser(), caller);
return true;
} catch (ResourceUnavailableException e) {
@ -1622,7 +1618,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
@Override
public UserVm rebootVirtualMachine(RebootVMCmd cmd) {
public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException{
Account account = UserContext.current().getCaller();
Long userId = UserContext.current().getCallerUserId();
Long vmId = cmd.getId();
@ -1635,14 +1631,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
userId = accountAndUserValidation(vmId, account, userId, vmInstance);
boolean status = rebootVirtualMachine(userId, vmId);
if (status) {
return _vmDao.findById(vmId);
} else {
s_logger.warn("Failed to reboot vm with id: " + vmId);
return null;
}
return rebootVirtualMachine(userId, vmId);
}
@Override

View File

@ -95,4 +95,8 @@ public interface VirtualMachineManager extends Manager {
boolean migrateAway(VirtualMachine.Type type, long vmid, long hostId) throws InsufficientServerCapacityException;
<T extends VMInstanceVO> T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException;
<T extends VMInstanceVO> T reboot(T vm, Map<String, Object> params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException;
<T extends VMInstanceVO> T advanceReboot(T vm, Map<String, Object> params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException;
}

View File

@ -42,6 +42,8 @@ import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.NetworkRulesSystemVmCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StopAnswer;
@ -51,9 +53,11 @@ import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
@ -75,6 +79,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.org.Cluster;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
@ -144,6 +149,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager {
@Inject protected GuestOSDao _guestOsDao;
@Inject protected VolumeDao _volsDao;
@Inject protected ConsoleProxyManager _consoleProxyMgr;
@Inject protected ConfigurationManager _configMgr;
@Inject(adapter=DeploymentPlanner.class)
protected Adapters<DeploymentPlanner> _planners;
@ -912,6 +918,10 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager {
@Override
public <T extends VMInstanceVO> boolean remove(T vm, User user, Account caller) {
//expunge the corresponding nics
VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
_networkMgr.expungeNics(profile);
s_logger.trace("Nics of the vm " + vm + " are expunged successfully");
return _vmDao.remove(vm.getId());
}
@ -1104,7 +1114,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager {
}
protected class CleanupTask implements Runnable {
@Override
public void run() {
s_logger.trace("VM Operation Thread Running");
@ -1115,4 +1124,51 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager {
}
}
}
@Override
public <T extends VMInstanceVO> T reboot(T vm, Map<String, Object> params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException {
try {
return advanceReboot(vm, params, caller, account);
} catch (ConcurrentOperationException e) {
throw new CloudRuntimeException("Unable to reboot a VM due to concurrent operation", e);
}
}
@Override
public <T extends VMInstanceVO> T advanceReboot(T vm, Map<String, Object> params, User caller, Account account) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
T rebootedVm = null;
DataCenter dc = _configMgr.getZone(vm.getDataCenterId());
HostPodVO pod = _configMgr.getPod(vm.getPodId());
Host host = _hostDao.findById(vm.getHostId());
Cluster cluster = null;
if (host != null) {
cluster = _configMgr.getCluster(host.getClusterId());
}
DeployDestination dest = new DeployDestination(dc, pod, cluster, host);
ReservationContext ctx = new ReservationContextImpl(null, null, caller, account);
VirtualMachineProfile<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
try {
//prepare all network elements (start domR/dhcp if needed)
_networkMgr.prepare(vmProfile, dest, ctx);
Commands cmds = new Commands(OnError.Revert);
cmds.addCommand(new RebootCommand(vm.getName()));
_agentMgr.send(host.getId(), cmds);
Answer rebootAnswer = cmds.getAnswer(RebootAnswer.class);
if (rebootAnswer != null && rebootAnswer.getResult()) {
rebootedVm = vm;
return rebootedVm;
}
s_logger.info("Unable to reboot VM " + vm + " on " + dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" : rebootAnswer.getDetails()));
} catch (OperationTimedoutException e) {
s_logger.warn("Unable to send the reboot command to host " + dest.getHost() + " for the vm " + vm + " due to operation timeout", e);
throw new CloudRuntimeException("Failed to reboot the vm on host " + dest.getHost());
}
return rebootedVm;
}
}

View File

@ -12,10 +12,13 @@ public interface NicDao extends GenericDao<NicVO, Long> {
List<NicVO> listBy(long instanceId);
List<String> listIpAddressInNetwork(long networkConfigId);
List<NicVO> listIncludingRemovedBy(long instanceId);
List<NicVO> listByNetworkId(long networkId);
NicVO findByInstanceIdAndNetworkId(long networkId, long instanceId);
NicVO findByInstanceIdAndNetworkIdIncludingRemoved(long networkId, long instanceId);
void removeNicsForInstance(long instanceId);
}

View File

@ -49,6 +49,14 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
return listBy(sc);
}
@Override
public List<NicVO> listIncludingRemovedBy(long instanceId) {
SearchCriteria<NicVO> sc = InstanceSearch.create();
sc.setParameters("instance", instanceId);
return listIncludingRemovedBy(sc);
}
@Override
public List<String> listIpAddressInNetwork(long networkId) {
SearchCriteria<String> sc = IpSearch.create();
@ -70,4 +78,12 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
sc.setParameters("instance", instanceId);
return findOneBy(sc);
}
@Override
public NicVO findByInstanceIdAndNetworkIdIncludingRemoved(long networkId, long instanceId) {
SearchCriteria<NicVO> sc = createSearchCriteria();
sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId);
sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId);
return findOneIncludingRemovedBy(sc);
}
}