mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 11:52:28 +01:00
better expunge and destroy of volumes
This commit is contained in:
parent
7f597e594c
commit
6e6e8ff876
@ -26,6 +26,7 @@ import com.cloud.api.Implementation;
|
||||
import com.cloud.api.Parameter;
|
||||
import com.cloud.api.ServerApiException;
|
||||
import com.cloud.api.response.SuccessResponse;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
|
||||
@Implementation(description="Deletes a detached disk volume.", responseObject=SuccessResponse.class)
|
||||
public class DeleteVolumeCmd extends BaseCmd {
|
||||
@ -63,7 +64,7 @@ public class DeleteVolumeCmd extends BaseCmd {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(){
|
||||
public void execute() throws ConcurrentOperationException {
|
||||
boolean result = _storageService.deleteVolume(this);
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
|
||||
@ -27,6 +27,7 @@ import com.cloud.api.commands.DeletePoolCmd;
|
||||
import com.cloud.api.commands.DeleteVolumeCmd;
|
||||
import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd;
|
||||
import com.cloud.api.commands.UpdateStoragePoolCmd;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
@ -60,7 +61,7 @@ public interface StorageService {
|
||||
*/
|
||||
Volume createVolume(CreateVolumeCmd cmd);
|
||||
|
||||
boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException;
|
||||
boolean deleteVolume(DeleteVolumeCmd cmd) throws ConcurrentOperationException;
|
||||
/**
|
||||
* Delete the storage pool
|
||||
* @param cmd - the command specifying poolId
|
||||
|
||||
@ -38,8 +38,7 @@ public interface Volume extends ControlledEntity, BasedOn {
|
||||
Creating("The volume is being created. getPoolId() should reflect the pool where it is being created."),
|
||||
Ready("The volume is ready to be used."),
|
||||
Used("The volume is used"),
|
||||
Destroy("The volume is set to be desctroyed but can be recovered."),
|
||||
Destroyed("The volume is destroyed. Should be removed.");
|
||||
Destroy("The volume is set to be destroyed but can be recovered.");
|
||||
|
||||
String _description;
|
||||
|
||||
@ -75,17 +74,13 @@ public interface Volume extends ControlledEntity, BasedOn {
|
||||
private final static StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
|
||||
static {
|
||||
s_fsm.addTransition(Allocated, Event.Create, Creating);
|
||||
s_fsm.addTransition(Allocated, Event.Destroy, Destroyed);
|
||||
s_fsm.addTransition(Allocated, Event.Destroy, Destroy);
|
||||
s_fsm.addTransition(Creating, Event.OperationRetry, Creating);
|
||||
s_fsm.addTransition(Creating, Event.OperationFailed, Allocated);
|
||||
s_fsm.addTransition(Creating, Event.OperationSucceeded, Ready);
|
||||
s_fsm.addTransition(Creating, Event.Destroy, Destroy);
|
||||
s_fsm.addTransition(Ready, Event.Destroy, Destroy);
|
||||
s_fsm.addTransition(Ready, Event.Start, Used);
|
||||
s_fsm.addTransition(Destroy, Event.OperationSucceeded, Destroyed);
|
||||
s_fsm.addTransition(Destroy, Event.OperationFailed, Destroy);
|
||||
s_fsm.addTransition(Destroy, Event.OperationRetry, Destroy);
|
||||
s_fsm.addTransition(Destroy, Event.Recover, Ready);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +90,7 @@ public interface Volume extends ControlledEntity, BasedOn {
|
||||
OperationFailed,
|
||||
OperationSucceeded,
|
||||
OperationRetry,
|
||||
Destroy,
|
||||
Recover;
|
||||
Destroy;
|
||||
}
|
||||
|
||||
enum SourceType {
|
||||
|
||||
@ -1557,64 +1557,13 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean destroyProxy(long vmId) {
|
||||
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
|
||||
if (asyncExecutor != null) {
|
||||
AsyncJobVO job = asyncExecutor.getJob();
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy console proxy " + vmId + ", update async job-" + job.getId());
|
||||
}
|
||||
_asyncMgr.updateAsyncJobAttachment(job.getId(), "console_proxy", vmId);
|
||||
}
|
||||
|
||||
ConsoleProxyVO vm = _consoleProxyDao.findById(vmId);
|
||||
if (vm == null || vm.getState() == State.Destroyed) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Unable to find vm or vm is destroyed: " + vmId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Destroying console proxy vm " + vmId);
|
||||
}
|
||||
|
||||
if (!_itMgr.stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, null)) {
|
||||
s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vmId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
List<VolumeVO> vols = null;
|
||||
ConsoleProxyVO proxy = _consoleProxyDao.findById(vmId);
|
||||
try {
|
||||
vols = _volsDao.findByInstance(vmId);
|
||||
if (vols.size() != 0) {
|
||||
_storageMgr.destroy(vm, vols);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
try {
|
||||
txn.start();
|
||||
// release critical system resources used by the VM before we
|
||||
// delete them
|
||||
if (vm.getPublicIpAddress() != null) {
|
||||
// freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId());
|
||||
}
|
||||
vm.setPublicIpAddress(null);
|
||||
|
||||
_consoleProxyDao.remove(vm.getId());
|
||||
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught this error: ", e);
|
||||
txn.rollback();
|
||||
return false;
|
||||
} finally {
|
||||
s_logger.debug("console proxy vm is destroyed : " + vm.getName());
|
||||
}
|
||||
return _itMgr.expunge(proxy, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
|
||||
} catch (ResourceUnavailableException e) {
|
||||
s_logger.warn("Unable to expunge " + proxy, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -44,10 +44,10 @@ import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
@ -108,7 +108,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
_name = name;
|
||||
_isEnabled = _configDao.getValue(Config.OvsNetwork.key()).equalsIgnoreCase("true") ? true : false;
|
||||
_isEnabled = Boolean.parseBoolean(_configDao.getValue(Config.OvsNetwork.key()));
|
||||
_serverId = ((ManagementServer)ComponentLocator.getComponent(ManagementServer.Name)).getId();
|
||||
_executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("OVS"));
|
||||
_cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("OVS-Cleanup"));
|
||||
@ -470,8 +470,9 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (delayMs == null)
|
||||
delayMs = new Long(100l);
|
||||
if (delayMs == null) {
|
||||
delayMs = new Long(100l);
|
||||
}
|
||||
|
||||
for (Long vmId: affectedVms) {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
@ -613,14 +614,14 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
||||
@Override
|
||||
public void UserVmCheckAndCreateTunnel(Commands cmds,
|
||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) throws GreTunnelException {
|
||||
CheckAndCreateTunnel((VMInstanceVO)profile.getVirtualMachine(), dest);
|
||||
CheckAndCreateTunnel(profile.getVirtualMachine(), dest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void RouterCheckAndCreateTunnel(Commands cmds,
|
||||
VirtualMachineProfile<DomainRouterVO> profile,
|
||||
DeployDestination dest) throws GreTunnelException {
|
||||
CheckAndCreateTunnel((VMInstanceVO)profile.getVirtualMachine(), dest);
|
||||
CheckAndCreateTunnel(profile.getVirtualMachine(), dest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -348,51 +348,12 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Attempting to destroy router " + routerId);
|
||||
}
|
||||
|
||||
DomainRouterVO router = _routerDao.acquireInLockTable(routerId);
|
||||
|
||||
|
||||
DomainRouterVO router = _routerDao.findById(routerId);
|
||||
if (router == null) {
|
||||
s_logger.debug("Unable to acquire lock on router " + routerId);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (router.getState() == State.Destroyed || router.getState() == State.Expunging || router.getRemoved() != null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Unable to find router or router is destroyed: " + routerId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stopRouterInternal(router.getId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
router = _routerDao.findById(routerId);
|
||||
if (!_itMgr.stateTransitTo(router, VirtualMachine.Event.DestroyRequested, router.getHostId())) {
|
||||
s_logger.debug("VM " + router.toString() + " is not in a state to be destroyed.");
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Release lock on router " + routerId + " for stop");
|
||||
}
|
||||
_routerDao.releaseFromLockTable(routerId);
|
||||
}
|
||||
|
||||
router.setPublicIpAddress(null);
|
||||
router.setVlanDbId(null);
|
||||
_routerDao.update(router.getId(), router);
|
||||
_routerDao.remove(router.getId());
|
||||
|
||||
List<VolumeVO> vols = _volsDao.findByInstance(routerId);
|
||||
_storageMgr.destroy(router, vols);
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Successfully destroyed router: " + routerId);
|
||||
}
|
||||
|
||||
return true;
|
||||
return _itMgr.expunge(router, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -81,14 +81,6 @@ public interface StorageManager extends Manager {
|
||||
*/
|
||||
List<VolumeVO> unshare(VMInstanceVO vm, HostVO host);
|
||||
|
||||
/**
|
||||
* destroy the storage volumes of a certain vm.
|
||||
*
|
||||
* @param vm vm to destroy.
|
||||
* @param vols volumes to remove from storage pool
|
||||
*/
|
||||
void destroy(VMInstanceVO vm, List<VolumeVO> vols);
|
||||
|
||||
/**
|
||||
* Creates volumes for a particular VM.
|
||||
* @param account account to create volumes for.
|
||||
@ -205,7 +197,7 @@ public interface StorageManager extends Manager {
|
||||
* Marks the specified volume as destroyed in the management server database. The expunge thread will delete the volume from its storage pool.
|
||||
* @param volume
|
||||
*/
|
||||
void destroyVolume(VolumeVO volume);
|
||||
void destroyVolume(VolumeVO volume) throws ConcurrentOperationException;
|
||||
|
||||
/** Create capacity entries in the op capacity table
|
||||
* @param storagePool
|
||||
@ -282,5 +274,5 @@ public interface StorageManager extends Manager {
|
||||
|
||||
void release(VirtualMachineProfile<? extends VMInstanceVO> profile);
|
||||
|
||||
void cleanupVolumes(Long vmId);
|
||||
void cleanupVolumes(long vmId) throws ConcurrentOperationException;
|
||||
}
|
||||
|
||||
@ -114,7 +114,6 @@ import com.cloud.host.dao.DetailsDao;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.VirtualNetworkApplianceService;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
@ -141,7 +140,6 @@ import com.cloud.storage.snapshot.SnapshotScheduler;
|
||||
import com.cloud.template.TemplateManager;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
@ -874,7 +872,11 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
s_logger.debug(e.getMessage());
|
||||
}
|
||||
if (rootCreated != null) {
|
||||
destroyVolume(rootCreated);
|
||||
try {
|
||||
destroyVolume(rootCreated);
|
||||
} catch (Exception e1) {
|
||||
s_logger.warn("Unable to mark a volume as destroyed: " + rootCreated, e1);
|
||||
}
|
||||
}
|
||||
throw new CloudRuntimeException("Unable to create volumes for " + vm, e);
|
||||
}
|
||||
@ -953,55 +955,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(VMInstanceVO vm, List<VolumeVO> vols) {
|
||||
if (s_logger.isDebugEnabled() && vm != null) {
|
||||
s_logger.debug("Destroying volumes of " + vm.toString());
|
||||
}
|
||||
|
||||
for (VolumeVO vol : vols) {
|
||||
_volsDao.detachVolume(vol.getId());
|
||||
_volsDao.destroyVolume(vol.getId());
|
||||
|
||||
// First delete the entries in the snapshot_policy and
|
||||
// snapshot_schedule table for the volume.
|
||||
// They should not get executed after the volume is destroyed.
|
||||
_snapshotMgr.deletePoliciesForVolume(vol.getId());
|
||||
|
||||
String volumePath = vol.getPath();
|
||||
Long poolId = vol.getPoolId();
|
||||
if (poolId != null && volumePath != null && !volumePath.trim().isEmpty()) {
|
||||
Answer answer = null;
|
||||
StoragePoolVO pool = _storagePoolDao.findById(poolId);
|
||||
String vmName = null;
|
||||
if (vm != null) {
|
||||
vmName = vm.getInstanceName();
|
||||
}
|
||||
final DestroyCommand cmd = new DestroyCommand(pool, vol, vmName);
|
||||
boolean removed = false;
|
||||
List<StoragePoolHostVO> poolhosts = _storagePoolHostDao.listByPoolId(poolId);
|
||||
for (StoragePoolHostVO poolhost : poolhosts) {
|
||||
answer = _agentMgr.easySend(poolhost.getHostId(), cmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
_volsDao.remove(vol.getId());
|
||||
} else {
|
||||
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_STORAGE_MISC, vol.getDataCenterId(), vol.getPodId(),
|
||||
"Storage cleanup required for storage pool: " + pool.getName(), "Volume folder: " + vol.getFolder() + ", Volume Path: " + vol.getPath() + ", Volume id: " +vol.getId()+ ", Volume Name: " +vol.getName()+ ", Storage PoolId: " +vol.getPoolId());
|
||||
s_logger.warn("destroy volume " + vol.getFolder() + " : " + vol.getPath() + " failed for Volume id : " +vol.getId()+ " Volume Name: " +vol.getName()+ " Storage PoolId : " +vol.getPoolId());
|
||||
}
|
||||
} else {
|
||||
_volsDao.remove(vol.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_name = name;
|
||||
@ -1597,13 +1550,13 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
String destPrimaryStorageVolumePath = cvAnswer.getVolumePath();
|
||||
String destPrimaryStorageVolumeFolder = cvAnswer.getVolumeFolder();
|
||||
|
||||
// Delete the volume on the source storage pool
|
||||
final DestroyCommand cmd = new DestroyCommand(srcPool, volume, null);
|
||||
Answer destroyAnswer = _agentMgr.easySend(sourceHostId, cmd);
|
||||
|
||||
if (destroyAnswer == null || !destroyAnswer.getResult()) {
|
||||
throw new CloudRuntimeException("Failed to delete the volume from the source primary storage pool.");
|
||||
try {
|
||||
destroyVolume(volume);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
s_logger.warn("Concurrent Operation", e);
|
||||
}
|
||||
|
||||
expungeVolume(volume);
|
||||
|
||||
volume.setPath(destPrimaryStorageVolumePath);
|
||||
volume.setFolder(destPrimaryStorageVolumeFolder);
|
||||
@ -1849,16 +1802,14 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void destroyVolume(VolumeVO volume) {
|
||||
public void destroyVolume(VolumeVO volume) throws ConcurrentOperationException {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
|
||||
Long volumeId = volume.getId();
|
||||
_volsDao.destroyVolume(volumeId);
|
||||
|
||||
_volsDao.update(volume, Volume.Event.Destroy);
|
||||
long volumeId = volume.getId();
|
||||
|
||||
EventUtils.saveEvent(User.UID_SYSTEM, volume.getAccountId(), EventTypes.EVENT_VOLUME_DELETE, "Volume " +volume.getName()+ " deleted");
|
||||
|
||||
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), null, null , null);
|
||||
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volumeId, volume.getName(), null, null , null);
|
||||
_usageEventDao.persist(usageEvent);
|
||||
|
||||
// Delete the recurring snapshot policies for this volume.
|
||||
@ -1994,24 +1945,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected class StorageGarbageCollector implements Runnable {
|
||||
|
||||
public StorageGarbageCollector() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
s_logger.info("Storage Garbage Collection Thread is running.");
|
||||
|
||||
cleanupStorage(true);
|
||||
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught the following Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupStorage(boolean recurring) {
|
||||
GlobalLock scanLock = GlobalLock.getInternLock(this.getClass().getName());
|
||||
@ -2083,19 +2016,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
}
|
||||
|
||||
List<VolumeVO> vols = _volsDao.listRemovedButNotDestroyed();
|
||||
List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed();
|
||||
for (VolumeVO vol : vols) {
|
||||
try {
|
||||
Long poolId = vol.getPoolId();
|
||||
Answer answer = null;
|
||||
StoragePoolVO pool = _storagePoolDao.findById(poolId);
|
||||
final DestroyCommand cmd = new DestroyCommand(pool, vol, null);
|
||||
answer = sendToPool(pool, cmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
s_logger.debug("Destroyed " + vol);
|
||||
vol.setDestroyed(true);
|
||||
_volsDao.update(vol.getId(), vol);
|
||||
}
|
||||
expungeVolume(vol);
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Unable to destroy " + vol.getId(), e);
|
||||
}
|
||||
@ -2470,7 +2394,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteVolume(DeleteVolumeCmd cmd) throws InvalidParameterValueException {
|
||||
public boolean deleteVolume(DeleteVolumeCmd cmd) throws ConcurrentOperationException {
|
||||
Account account = UserContext.current().getCaller();
|
||||
Long volumeId = cmd.getId();
|
||||
|
||||
@ -2513,20 +2437,13 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
}
|
||||
|
||||
// Check that the volume is not already destroyed
|
||||
if (volume.getDestroyed()) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that is not already destroyed.");
|
||||
if (volume.getState() != Volume.State.Destroy) {
|
||||
destroyVolume(volume);
|
||||
}
|
||||
|
||||
try {
|
||||
// Destroy the volume
|
||||
destroyVolume(volume);
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Error destroying volume:"+e);
|
||||
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error destroying volume:"+e);
|
||||
}
|
||||
expungeVolume(volume);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private boolean validateVolumeSizeRange(long size) throws InvalidParameterValueException {
|
||||
@ -2800,41 +2717,90 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
|
||||
//add code here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupVolumes(Long vmId) {
|
||||
VMInstanceVO vm = _vmInstanceDao.findById(vmId);
|
||||
List<VolumeVO> volumesForVm = _volsDao.findByInstance(vmId);
|
||||
for(VolumeVO vol : volumesForVm){
|
||||
if(vol.getVolumeType().equals(VolumeType.ROOT)){
|
||||
if(vol.getState() != Volume.State.Destroyed) {
|
||||
assert(vol.getState() == Volume.State.Destroy);
|
||||
String volumePath = vol.getPath();
|
||||
Long poolId = vol.getPoolId();
|
||||
if (poolId != null && volumePath != null && !volumePath.trim().isEmpty()) {
|
||||
Answer answer = null;
|
||||
StoragePoolVO pool = _storagePoolDao.findById(poolId);
|
||||
|
||||
final DestroyCommand cmd = new DestroyCommand(pool, vol, vm.getName());
|
||||
List<StoragePoolHostVO> poolhosts = _storagePoolHostDao.listByPoolId(poolId);
|
||||
for (StoragePoolHostVO poolhost : poolhosts) {
|
||||
answer = _agentMgr.easySend(poolhost.getHostId(), cmd);
|
||||
if (answer != null && answer.getResult()) {
|
||||
try {
|
||||
_volsDao.update(vol, Volume.Event.OperationSucceeded);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
s_logger.warn("Unable to update volume state. vm: " + vmId + ", vol: " + vol.getId() + " due to ConcurrentOperationException");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
destroyVolume(vol);
|
||||
public void expungeVolume(VolumeVO vol) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Expunging " + vol);
|
||||
}
|
||||
String vmName = null;
|
||||
if (vol.getVolumeType() == VolumeType.ROOT && vol.getInstanceId() != null) {
|
||||
VirtualMachine vm = _vmInstanceDao.findById(vol.getInstanceId());
|
||||
vmName = vm.getInstanceName();
|
||||
}
|
||||
|
||||
String volumePath = vol.getPath();
|
||||
Long poolId = vol.getPoolId();
|
||||
if (poolId == null || volumePath == null || volumePath.trim().isEmpty()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Marking volume that was never created as destroyed: " + vol);
|
||||
}
|
||||
_volsDao.remove(vol.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
StoragePoolVO pool = _storagePoolDao.findById(poolId);
|
||||
if (pool == null) {
|
||||
s_logger.debug("Removing volume as storage pool is gone: " + poolId);
|
||||
_volsDao.remove(vol.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyCommand cmd = new DestroyCommand(pool, vol, vmName);
|
||||
Answer answer = this.sendToPool(pool, cmd);
|
||||
|
||||
if (answer != null && answer.getResult()) {
|
||||
_volsDao.remove(vol.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume successfully expunged from " + poolId);
|
||||
}
|
||||
} else {
|
||||
s_logger.info("Will retry delete of " + vol + " from " + poolId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public void cleanupVolumes(long vmId) throws ConcurrentOperationException {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Cleaning storage for vm: " + vmId);
|
||||
}
|
||||
List<VolumeVO> volumesForVm = _volsDao.findByInstance(vmId);
|
||||
List<VolumeVO> toBeExpunged = new ArrayList<VolumeVO>();
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
for (VolumeVO vol : volumesForVm) {
|
||||
if (vol.getVolumeType().equals(VolumeType.ROOT)) {
|
||||
destroyVolume(vol);
|
||||
toBeExpunged.add(vol);
|
||||
} else {
|
||||
//data volume
|
||||
_volsDao.detachVolume(vol.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Detaching " + vol);
|
||||
}
|
||||
_volsDao.detachVolume(vol.getId());
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
|
||||
for (VolumeVO expunge : toBeExpunged) {
|
||||
expungeVolume(expunge);
|
||||
}
|
||||
}
|
||||
|
||||
protected class StorageGarbageCollector implements Runnable {
|
||||
|
||||
public StorageGarbageCollector() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
s_logger.trace("Storage Garbage Collection Thread is running.");
|
||||
|
||||
cleanupStorage(true);
|
||||
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught the following Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -36,14 +36,10 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long> {
|
||||
List<VolumeVO> findByDetachedDestroyed();
|
||||
List<VolumeVO> findByAccountAndPod(long accountId, long podId);
|
||||
List<VolumeVO> findByTemplateAndZone(long templateId, long zoneId);
|
||||
List<Long> findVMInstancesByStorageHost(long hostId, Volume.MirrorState mState);
|
||||
List<VolumeVO> findStrandedMirrorVolumes();
|
||||
List<Long> findVmsStoredOnHost(long hostId);
|
||||
void deleteVolumesByInstance(long instanceId);
|
||||
void attachVolume(long volumeId, long vmId, long deviceId);
|
||||
void detachVolume(long volumeId);
|
||||
void destroyVolume(long volumeId);
|
||||
void recoverVolume(long volumeId);
|
||||
boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId);
|
||||
List<VolumeVO> listRemovedButNotDestroyed();
|
||||
List<VolumeVO> findCreatedByInstance(long id);
|
||||
@ -59,4 +55,6 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long> {
|
||||
*/
|
||||
boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException;
|
||||
HypervisorType getHypervisorType(long volumeId);
|
||||
|
||||
List<VolumeVO> listVolumesToBeDestroyed();
|
||||
}
|
||||
|
||||
@ -32,8 +32,6 @@ import com.cloud.async.AsyncInstanceCreateStatus;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.Volume.MirrorState;
|
||||
import com.cloud.storage.Volume.VolumeType;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.utils.Pair;
|
||||
@ -53,22 +51,14 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
||||
public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements VolumeDao {
|
||||
private static final Logger s_logger = Logger.getLogger(VolumeDaoImpl.class);
|
||||
protected final SearchBuilder<VolumeVO> DetachedAccountIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> AccountIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> AccountPodSearch;
|
||||
protected final SearchBuilder<VolumeVO> TemplateZoneSearch;
|
||||
protected final GenericSearchBuilder<VolumeVO, SumCount> TotalSizeByPoolSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceAndTypeSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceIdDestroyedSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceIdCreatedSearch;
|
||||
protected final SearchBuilder<VolumeVO> DetachedDestroyedSearch;
|
||||
protected final SearchBuilder<VolumeVO> MirrorSearch;
|
||||
protected final GenericSearchBuilder<VolumeVO, Long> ActiveTemplateSearch;
|
||||
protected final SearchBuilder<VolumeVO> RemovedButNotDestroyedSearch;
|
||||
protected final SearchBuilder<VolumeVO> PoolIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceAndDeviceIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceStatesSearch;
|
||||
protected final SearchBuilder<VolumeVO> IdStateSearch;
|
||||
|
||||
protected final SearchBuilder<VolumeVO> AllFieldsSearch;
|
||||
|
||||
protected final Attribute _stateAttr;
|
||||
|
||||
@ -116,7 +106,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByAccount(long accountId) {
|
||||
SearchCriteria<VolumeVO> sc = AccountIdSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
sc.setParameters("destroyed", false);
|
||||
return listBy(sc);
|
||||
@ -124,14 +114,14 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByInstance(long id) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceIdSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", id);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId){
|
||||
SearchCriteria<VolumeVO> sc = InstanceAndDeviceIdSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", instanceId);
|
||||
sc.setParameters("deviceId", deviceId);
|
||||
return listBy(sc);
|
||||
@ -139,14 +129,14 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByPoolId(long poolId) {
|
||||
SearchCriteria<VolumeVO> sc = PoolIdSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("poolId", poolId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findCreatedByInstance(long id) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceIdCreatedSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", id);
|
||||
sc.setParameters("status", AsyncInstanceCreateStatus.Created);
|
||||
sc.setParameters("destroyed", false);
|
||||
@ -164,7 +154,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByInstanceAndType(long id, VolumeType vType) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceAndTypeSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", id);
|
||||
sc.setParameters("vType", vType.toString());
|
||||
return listBy(sc);
|
||||
@ -172,7 +162,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByInstanceIdDestroyed(long vmId) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceIdDestroyedSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", vmId);
|
||||
sc.setParameters("destroyed", true);
|
||||
return listIncludingRemovedBy(sc);
|
||||
@ -187,8 +177,8 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByAccountAndPod(long accountId, long podId) {
|
||||
SearchCriteria<VolumeVO> sc = AccountPodSearch.create();
|
||||
sc.setParameters("account", accountId);
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
sc.setParameters("pod", podId);
|
||||
sc.setParameters("destroyed", false);
|
||||
sc.setParameters("status", AsyncInstanceCreateStatus.Created);
|
||||
@ -205,38 +195,6 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
return listIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override @DB
|
||||
public List<Long> findVMInstancesByStorageHost(long hostId, Volume.MirrorState mirrState) {
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
PreparedStatement pstmt = null;
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
|
||||
try {
|
||||
String sql = SELECT_VM_SQL;
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, hostId);
|
||||
pstmt.setString(2, mirrState.toString());
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
result.add(rs.getLong(1));
|
||||
}
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new CloudRuntimeException("DB Exception on: " + SELECT_VM_SQL, e);
|
||||
} catch (Throwable e) {
|
||||
throw new CloudRuntimeException("Caught: " + SELECT_VM_SQL, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findStrandedMirrorVolumes() {
|
||||
SearchCriteria<VolumeVO> sc = MirrorSearch.create();
|
||||
sc.setParameters("mirrorState", MirrorState.ACTIVE.toString());
|
||||
|
||||
return listIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyVolumeActivelyUsingTemplateOnPool(long templateId, long poolId) {
|
||||
SearchCriteria<Long> sc = ActiveTemplateSearch.create();
|
||||
@ -251,7 +209,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
|
||||
@Override
|
||||
public void deleteVolumesByInstance(long instanceId) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceIdSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("instanceId", instanceId);
|
||||
expunge(sc);
|
||||
}
|
||||
@ -276,34 +234,6 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
update(volumeId, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyVolume(long volumeId) {
|
||||
VolumeVO volume = createForUpdate(volumeId);
|
||||
volume.setDestroyed(true);
|
||||
|
||||
Volume.State oldState = volume.getState();
|
||||
Volume.State newState = oldState.getNextState(Event.Destroy);
|
||||
|
||||
assert newState != null : "Event "+ Event.Destroy + " cannot happen from " + oldState;
|
||||
volume.setState(newState);
|
||||
|
||||
update(volumeId, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recoverVolume(long volumeId) {
|
||||
VolumeVO volume = createForUpdate(volumeId);
|
||||
volume.setDestroyed(false);
|
||||
|
||||
Volume.State oldState = volume.getState();
|
||||
Volume.State newState = oldState.getNextState(Event.Recover);
|
||||
|
||||
assert newState != null : "Event "+ Event.Recover + " cannot happen from " + oldState;
|
||||
volume.setState(newState);
|
||||
|
||||
update(volumeId, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException {
|
||||
Volume.State oldState = vol.getState();
|
||||
@ -314,7 +244,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
UpdateBuilder builder = getUpdateBuilder(vol);
|
||||
builder.set(vol, _stateAttr, newState);
|
||||
|
||||
SearchCriteria<VolumeVO> sc = IdStateSearch.create();
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("id", vol.getId());
|
||||
sc.setParameters("state", oldState);
|
||||
|
||||
@ -325,6 +255,8 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
}
|
||||
return rows == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public HypervisorType getHypervisorType(long volumeId) {
|
||||
/*lookup from cluster of pool*/
|
||||
@ -336,8 +268,9 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
pstmt = txn.prepareAutoCloseStatement(sql);
|
||||
pstmt.setLong(1, volumeId);
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
if (rs.next())
|
||||
return HypervisorType.getType(rs.getString(1));
|
||||
if (rs.next()) {
|
||||
return HypervisorType.getType(rs.getString(1));
|
||||
}
|
||||
return HypervisorType.None;
|
||||
} catch (SQLException e) {
|
||||
throw new CloudRuntimeException("DB Exception on: " + SELECT_HYPERTYPE_FROM_VOLUME, e);
|
||||
@ -347,98 +280,59 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
}
|
||||
|
||||
protected VolumeDaoImpl() {
|
||||
AccountIdSearch = createSearchBuilder();
|
||||
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountIdSearch.and("destroyed", AccountIdSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
AccountIdSearch.done();
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ);
|
||||
AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getDestroyed(), Op.EQ);
|
||||
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ);
|
||||
AllFieldsSearch.and("pod", AllFieldsSearch.entity().getPodId(), Op.EQ);
|
||||
AllFieldsSearch.and("status", AllFieldsSearch.entity().getStatus(), Op.EQ);
|
||||
AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getInstanceId(), Op.EQ);
|
||||
AllFieldsSearch.and("deviceId", AllFieldsSearch.entity().getDeviceId(), Op.EQ);
|
||||
AllFieldsSearch.and("poolId", AllFieldsSearch.entity().getPoolId(), Op.EQ);
|
||||
AllFieldsSearch.and("vType", AllFieldsSearch.entity().getVolumeType(), Op.EQ);
|
||||
AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
|
||||
DetachedAccountIdSearch = createSearchBuilder();
|
||||
DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), SearchCriteria.Op.NULL);
|
||||
DetachedAccountIdSearch.and("accountId", DetachedAccountIdSearch.entity().getAccountId(), Op.EQ);
|
||||
DetachedAccountIdSearch.and("destroyed", DetachedAccountIdSearch.entity().getDestroyed(), Op.EQ);
|
||||
DetachedAccountIdSearch.and("instanceId", DetachedAccountIdSearch.entity().getInstanceId(), Op.NULL);
|
||||
DetachedAccountIdSearch.done();
|
||||
|
||||
AccountPodSearch = createSearchBuilder();
|
||||
AccountPodSearch.and("account", AccountPodSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
AccountPodSearch.and("pod", AccountPodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
|
||||
AccountPodSearch.and("destroyed", AccountPodSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
AccountPodSearch.and("status", AccountPodSearch.entity().getStatus(), SearchCriteria.Op.EQ);
|
||||
AccountPodSearch.done();
|
||||
|
||||
TemplateZoneSearch = createSearchBuilder();
|
||||
TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
|
||||
TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||
TemplateZoneSearch.and("template", TemplateZoneSearch.entity().getTemplateId(), Op.EQ);
|
||||
TemplateZoneSearch.and("zone", TemplateZoneSearch.entity().getDataCenterId(), Op.EQ);
|
||||
TemplateZoneSearch.done();
|
||||
|
||||
TotalSizeByPoolSearch = createSearchBuilder(SumCount.class);
|
||||
TotalSizeByPoolSearch.select("sum", Func.SUM, TotalSizeByPoolSearch.entity().getSize());
|
||||
TotalSizeByPoolSearch.select("count", Func.COUNT, (Object[])null);
|
||||
TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
|
||||
TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
TotalSizeByPoolSearch.and("poolId", TotalSizeByPoolSearch.entity().getPoolId(), Op.EQ);
|
||||
TotalSizeByPoolSearch.and("removed", TotalSizeByPoolSearch.entity().getRemoved(), Op.NULL);
|
||||
TotalSizeByPoolSearch.done();
|
||||
|
||||
|
||||
InstanceIdCreatedSearch = createSearchBuilder();
|
||||
InstanceIdCreatedSearch.and("instanceId", InstanceIdCreatedSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceIdCreatedSearch.and("status", InstanceIdCreatedSearch.entity().getStatus(), SearchCriteria.Op.EQ);
|
||||
InstanceIdCreatedSearch.and("destroyed", InstanceIdCreatedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
InstanceIdCreatedSearch.done();
|
||||
|
||||
InstanceIdSearch = createSearchBuilder();
|
||||
InstanceIdSearch.and("instanceId", InstanceIdSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceIdSearch.done();
|
||||
|
||||
InstanceAndDeviceIdSearch = createSearchBuilder();
|
||||
InstanceAndDeviceIdSearch.and("instanceId", InstanceAndDeviceIdSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceAndDeviceIdSearch.and("deviceId", InstanceAndDeviceIdSearch.entity().getDeviceId(), SearchCriteria.Op.EQ);
|
||||
InstanceAndDeviceIdSearch.done();
|
||||
|
||||
PoolIdSearch = createSearchBuilder();
|
||||
PoolIdSearch.and("poolId", PoolIdSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
|
||||
PoolIdSearch.done();
|
||||
|
||||
InstanceAndTypeSearch= createSearchBuilder();
|
||||
InstanceAndTypeSearch.and("instanceId", InstanceAndTypeSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceAndTypeSearch.and("vType", InstanceAndTypeSearch.entity().getVolumeType(), SearchCriteria.Op.EQ);
|
||||
InstanceAndTypeSearch.done();
|
||||
|
||||
InstanceIdDestroyedSearch = createSearchBuilder();
|
||||
InstanceIdDestroyedSearch.and("instanceId", InstanceIdDestroyedSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceIdDestroyedSearch.and("destroyed", InstanceIdDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
InstanceIdDestroyedSearch.done();
|
||||
|
||||
DetachedDestroyedSearch = createSearchBuilder();
|
||||
DetachedDestroyedSearch.and("instanceId", DetachedDestroyedSearch.entity().getInstanceId(), SearchCriteria.Op.NULL);
|
||||
DetachedDestroyedSearch.and("destroyed", DetachedDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
DetachedDestroyedSearch.and("instanceId", DetachedDestroyedSearch.entity().getInstanceId(), Op.NULL);
|
||||
DetachedDestroyedSearch.and("destroyed", DetachedDestroyedSearch.entity().getDestroyed(), Op.EQ);
|
||||
DetachedDestroyedSearch.done();
|
||||
|
||||
MirrorSearch = createSearchBuilder();
|
||||
MirrorSearch.and("mirrorVolume", MirrorSearch.entity().getMirrorVolume(), Op.NULL);
|
||||
MirrorSearch.and("mirrorState", MirrorSearch.entity().getMirrorState(), Op.EQ);
|
||||
MirrorSearch.done();
|
||||
|
||||
ActiveTemplateSearch = createSearchBuilder(Long.class);
|
||||
ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
|
||||
ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
|
||||
ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||
ActiveTemplateSearch.and("pool", ActiveTemplateSearch.entity().getPoolId(), Op.EQ);
|
||||
ActiveTemplateSearch.and("template", ActiveTemplateSearch.entity().getTemplateId(), Op.EQ);
|
||||
ActiveTemplateSearch.and("removed", ActiveTemplateSearch.entity().getRemoved(), Op.NULL);
|
||||
ActiveTemplateSearch.select(null, Func.COUNT, null);
|
||||
ActiveTemplateSearch.done();
|
||||
|
||||
RemovedButNotDestroyedSearch = createSearchBuilder();
|
||||
RemovedButNotDestroyedSearch.and("destroyed", RemovedButNotDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
RemovedButNotDestroyedSearch.and("removed", RemovedButNotDestroyedSearch.entity().getRemoved(), SearchCriteria.Op.NNULL);
|
||||
RemovedButNotDestroyedSearch.and("destroyed", RemovedButNotDestroyedSearch.entity().getDestroyed(), Op.EQ);
|
||||
RemovedButNotDestroyedSearch.and("removed", RemovedButNotDestroyedSearch.entity().getRemoved(), Op.NNULL);
|
||||
RemovedButNotDestroyedSearch.done();
|
||||
|
||||
InstanceStatesSearch = createSearchBuilder();
|
||||
InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), SearchCriteria.Op.IN);
|
||||
InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), Op.EQ);
|
||||
InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), Op.IN);
|
||||
InstanceStatesSearch.done();
|
||||
|
||||
IdStateSearch = createSearchBuilder();
|
||||
IdStateSearch.and("id", IdStateSearch.entity().getId(), SearchCriteria.Op.EQ);
|
||||
IdStateSearch.and("state", IdStateSearch.entity().getState(), SearchCriteria.Op.EQ);
|
||||
IdStateSearch.done();
|
||||
|
||||
_stateAttr = _allAttributes.get("state");
|
||||
assert _stateAttr != null : "Couldn't get the state attribute";
|
||||
}
|
||||
@ -458,4 +352,12 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
public SumCount() {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> listVolumesToBeDestroyed() {
|
||||
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("state", Volume.State.Destroy);
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1109,68 +1109,15 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean destroySecStorageVm(long vmId) {
|
||||
AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor();
|
||||
if (asyncExecutor != null) {
|
||||
AsyncJobVO job = asyncExecutor.getJob();
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy secondary storage vm " + vmId + ", update async job-" + job.getId());
|
||||
}
|
||||
_asyncMgr.updateAsyncJobAttachment(job.getId(), "secstorage_vm", vmId);
|
||||
SecondaryStorageVmVO ssvm = _secStorageVmDao.findById(vmId);
|
||||
|
||||
try {
|
||||
return _itMgr.expunge(ssvm, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
|
||||
} catch (ResourceUnavailableException e) {
|
||||
s_logger.warn("Unable to expunge " + ssvm, e);
|
||||
return false;
|
||||
}
|
||||
|
||||
SecondaryStorageVmVO vm = _secStorageVmDao.findById(vmId);
|
||||
if (vm == null || vm.getState() == State.Destroyed) {
|
||||
String msg = "Unable to find vm or vm is destroyed: " + vmId;
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Destroying secondary storage vm vm " + vmId);
|
||||
}
|
||||
|
||||
if (! _itMgr.stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, null)) {
|
||||
String msg = "Unable to destroy the vm because it is not in the correct state: " + vmId;
|
||||
s_logger.debug(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
List<VolumeVO> vols = null;
|
||||
try {
|
||||
vols = _volsDao.findByInstance(vmId);
|
||||
if (vols.size() != 0) {
|
||||
_storageMgr.destroy(vm, vols);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
try {
|
||||
txn.start();
|
||||
// release critical system resources used by the VM before we
|
||||
// delete them
|
||||
if (vm.getPublicIpAddress() != null) {
|
||||
freePublicIpAddress(vm.getPublicIpAddress(), vm.getDataCenterId(), vm.getPodId());
|
||||
}
|
||||
vm.setPublicIpAddress(null);
|
||||
|
||||
_secStorageVmDao.remove(vm.getId());
|
||||
|
||||
txn.commit();
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Caught this error: ", e);
|
||||
txn.rollback();
|
||||
return false;
|
||||
} finally {
|
||||
s_logger.debug("secondary storage vm vm is destroyed : "
|
||||
+ vm.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DB
|
||||
|
||||
@ -37,12 +37,12 @@ public class ItWorkDaoImpl extends GenericDaoBase<ItWorkVO, String> implements I
|
||||
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("instance", AllFieldsSearch.entity().getInstanceId(), Op.EQ);
|
||||
AllFieldsSearch.and("op", AllFieldsSearch.entity().getState(), Op.EQ);
|
||||
AllFieldsSearch.and("op", AllFieldsSearch.entity().getType(), Op.EQ);
|
||||
AllFieldsSearch.and("step", AllFieldsSearch.entity().getStep(), Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
|
||||
CleanupSearch = createSearchBuilder();
|
||||
CleanupSearch.and("step", CleanupSearch.entity().getState(), Op.IN);
|
||||
CleanupSearch.and("step", CleanupSearch.entity().getType(), Op.IN);
|
||||
CleanupSearch.and("time", CleanupSearch.entity().getUpdatedAt(), Op.LT);
|
||||
CleanupSearch.done();
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ public class ItWorkVO {
|
||||
@Column(name="thread")
|
||||
String threadName;
|
||||
|
||||
@Column(name="state")
|
||||
@Column(name="step")
|
||||
Step step;
|
||||
|
||||
@Column(name="updated_at")
|
||||
@ -121,11 +121,11 @@ public class ItWorkVO {
|
||||
return managementServerId;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
public State getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setState(State type) {
|
||||
public void setType(State type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@ -137,8 +137,8 @@ public class ItWorkVO {
|
||||
return step;
|
||||
}
|
||||
|
||||
public void setStep(Step state) {
|
||||
this.step = state;
|
||||
public void setStep(Step step) {
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
public long getUpdatedAt() {
|
||||
|
||||
@ -1027,13 +1027,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
||||
// Recover the VM's disks
|
||||
List<VolumeVO> volumes = _volsDao.findByInstanceIdDestroyed(vmId);
|
||||
for (VolumeVO volume : volumes) {
|
||||
_volsDao.recoverVolume(volume.getId());
|
||||
// Create an event
|
||||
Long templateId = volume.getTemplateId();
|
||||
Long diskOfferingId = volume.getDiskOfferingId();
|
||||
long sizeMB = volume.getSize()/(1024*1024);
|
||||
StoragePoolVO pool = _storagePoolDao.findById(volume.getPoolId());
|
||||
EventUtils.saveEvent(User.UID_SYSTEM, volume.getAccountId(), EventTypes.EVENT_VOLUME_CREATE, "Created volume: "+ volume.getName() +" with size: " + sizeMB + " MB in pool: " + pool.getName());
|
||||
|
||||
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, templateId , sizeMB);
|
||||
_usageEventDao.persist(usageEvent);
|
||||
|
||||
@ -98,11 +98,11 @@ DROP TABLE IF EXISTS `cloud`.`host_tags`;
|
||||
CREATE TABLE `cloud`.`op_it_work` (
|
||||
`id` char(40) COMMENT 'id',
|
||||
`mgmt_server_id` bigint unsigned COMMENT 'management server id',
|
||||
`created_on` bigint unsigned NOT NULL COMMENT 'when was this work detail created',
|
||||
`created_at` bigint unsigned NOT NULL COMMENT 'when was this work detail created',
|
||||
`thread` varchar(255) NOT NULL COMMENT 'thread name',
|
||||
`type` char(32) NOT NULL COMMENT 'type of work',
|
||||
`state` char(32) NOT NULL COMMENT 'state',
|
||||
`updated_on` bigint unsigned NOT NULL COMMENT 'time it was taken over',
|
||||
`step` char(32) NOT NULL COMMENT 'state',
|
||||
`updated_at` bigint unsigned NOT NULL COMMENT 'time it was taken over',
|
||||
`instance_id` bigint unsigned NOT NULL COMMENT 'vm instance',
|
||||
`resource_type` char(32) COMMENT 'type of resource being worked on',
|
||||
`resource_id` bigint unsigned COMMENT 'resource id being worked on',
|
||||
@ -677,7 +677,7 @@ CREATE TABLE `cloud`.`user_ip_address` (
|
||||
INDEX `i_user_ip_address__source_nat`(`source_nat`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE VIEW `cloud`.`user_ip_address_view` AS SELECT INET_NTOA(user_ip_address.public_ip_address) as public_ip_address, user_ip_address.data_center_id, user_ip_address.account_id, user_ip_address.domain_id, user_ip_address.source_nat, user_ip_address.allocated, user_ip_address.vlan_db_id, user_ip_address.one_to_one_nat, user_ip_address.state, user_ip_address.mac_address, user_ip_address.network_id as associated_network_id from user_ip_address;
|
||||
CREATE VIEW `cloud`.`user_ip_address_view` AS SELECT INET_NTOA(user_ip_address.public_ip_address) as ip_address, user_ip_address.data_center_id, user_ip_address.account_id, user_ip_address.domain_id, user_ip_address.source_nat, user_ip_address.allocated, user_ip_address.vlan_db_id, user_ip_address.one_to_one_nat, user_ip_address.state, user_ip_address.mac_address, user_ip_address.network_id as associated_network_id from user_ip_address;
|
||||
|
||||
CREATE TABLE `cloud`.`user_statistics` (
|
||||
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user