bug 8242: introducing the concept of work queue for storage; introducing storage states as opposed to using host states; using row locks as opposed to db table locks

status 8242: resolved fixed
This commit is contained in:
abhishek 2011-01-28 13:39:58 -08:00
parent 5199167840
commit 5d18c4c527
17 changed files with 662 additions and 218 deletions

View File

@ -22,6 +22,7 @@ import java.util.Date;
import com.cloud.api.ApiConstants;
import com.cloud.host.Status;
import com.cloud.serializer.Param;
import com.cloud.storage.StoragePoolStatus;
import com.google.gson.annotations.SerializedName;
public class StoragePoolResponse extends BaseResponse {
@ -71,7 +72,7 @@ public class StoragePoolResponse extends BaseResponse {
private String tags;
@SerializedName(ApiConstants.STATE) @Param(description="the state of the storage pool")
private Status state;
private StoragePoolStatus state;
@SerializedName(ApiConstants.JOB_ID) @Param(description="shows the current pending asynchronous job ID. This tag is not returned if no current pending jobs are acting on the storage pool")
private Long jobId;
@ -203,11 +204,11 @@ public class StoragePoolResponse extends BaseResponse {
this.tags = tags;
}
public Status getState() {
public StoragePoolStatus getState() {
return state;
}
public void setState(Status state) {
public void setState(StoragePoolStatus state) {
this.state = state;
}

View File

@ -103,7 +103,7 @@ public interface StoragePool {
/**
* @return the storage pool status
*/
Status getStatus();
StoragePoolStatus getStatus();
int getPort();

View File

@ -0,0 +1,10 @@
package com.cloud.storage;
public enum StoragePoolStatus {
Up,
PrepareForMaintenance,
ErrorInMaintenance,
CancelMaintenance,
Maintenance,
Removed;
}

View File

@ -80,7 +80,7 @@ public class StoragePoolVO implements StoragePool {
@Column(name="status", updatable=true, nullable=false)
@Enumerated(value=EnumType.STRING)
private Status status;
private StoragePoolStatus status;
@Override
public long getId() {
@ -88,7 +88,7 @@ public class StoragePoolVO implements StoragePool {
}
@Override
public Status getStatus() {
public StoragePoolStatus getStatus() {
return status;
}
@ -193,7 +193,7 @@ public class StoragePoolVO implements StoragePool {
this.path = hostPath;
this.port = port;
this.podId = podId;
this.setStatus(Status.Up);
this.setStatus(StoragePoolStatus.Up);
}
public StoragePoolVO(StoragePoolVO that) {
@ -205,10 +205,10 @@ public class StoragePoolVO implements StoragePool {
this.hostAddress = hostAddress;
this.port = port;
this.path = path;
this.setStatus(Status.Up);
this.setStatus(StoragePoolStatus.Up);
}
public void setStatus(Status status)
public void setStatus(StoragePoolStatus status)
{
this.status = status;
}
@ -273,7 +273,7 @@ public class StoragePoolVO implements StoragePool {
}
public boolean isInMaintenance() {
return status == Status.PrepareForMaintenance || status == Status.Maintenance || status == Status.ErrorInMaintenance || removed != null;
return status == StoragePoolStatus.PrepareForMaintenance || status == StoragePoolStatus.Maintenance || status == StoragePoolStatus.ErrorInMaintenance || removed != null;
}
@Override

View File

@ -0,0 +1,100 @@
package com.cloud.storage;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="storage_pool_work")
public class StoragePoolWorkVO {
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPoolId() {
return poolId;
}
public void setPoolId(Long poolId) {
this.poolId = poolId;
}
public boolean isStoppedForMaintenance() {
return stoppedForMaintenance;
}
public void setStoppedForMaintenance(boolean stoppedForMaintenance) {
this.stoppedForMaintenance = stoppedForMaintenance;
}
public boolean isStartedAfterMaintenance() {
return startedAfterMaintenance;
}
public void setStartedAfterMaintenance(boolean startedAfterMaintenance) {
this.startedAfterMaintenance = startedAfterMaintenance;
}
public Long getVmId() {
return vmId;
}
public void setVmId(Long vmId) {
this.vmId = vmId;
}
public Long getManagementServerId() {
return managementServerId;
}
public void setManagementServerId(Long managementServerId) {
this.managementServerId = managementServerId;
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="pool_id")
private Long poolId;
@Column(name="vm_id")
private Long vmId;
@Column(name="stopped_for_maintenance")
private boolean stoppedForMaintenance;
@Column(name="started_after_maintenance")
private boolean startedAfterMaintenance;
@Column(name="mgmt_server_id")
private Long managementServerId;
public StoragePoolWorkVO(long vmId, long poolId, boolean stoppedForMaintenance, boolean startedAfterMaintenance, long mgmtServerId) {
super();
this.vmId = vmId;
this.poolId = poolId;
this.stoppedForMaintenance = stoppedForMaintenance;
this.startedAfterMaintenance = startedAfterMaintenance;
this.managementServerId = mgmtServerId;
}
public StoragePoolWorkVO() {
}
}

View File

@ -106,6 +106,7 @@ import com.cloud.storage.dao.SnapshotPolicyDaoImpl;
import com.cloud.storage.dao.SnapshotScheduleDaoImpl;
import com.cloud.storage.dao.StoragePoolDaoImpl;
import com.cloud.storage.dao.StoragePoolHostDaoImpl;
import com.cloud.storage.dao.StoragePoolWorkDaoImpl;
import com.cloud.storage.dao.UploadDaoImpl;
import com.cloud.storage.dao.VMTemplateDaoImpl;
import com.cloud.storage.dao.VMTemplateHostDaoImpl;
@ -256,6 +257,7 @@ public class DefaultComponentLibrary implements ComponentLibrary {
addDao("GreTunnelDao", GreTunnelDaoImpl.class);
addDao("OvsTunnelDao", OvsTunnelDaoImpl.class);
addDao("OvsTunnelAccountDao", OvsTunnelAccountDaoImpl.class);
addDao("StoragePoolWorkDao", StoragePoolWorkDaoImpl.class);
}
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();

View File

@ -196,6 +196,7 @@ import com.cloud.storage.LaunchPermissionVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.Upload;
@ -4156,9 +4157,9 @@ public class ManagementServerImpl implements ManagementServer {
@Override
public long getPsMaintenanceCount(long podId){
List<StoragePoolVO> poolsInTransition = new ArrayList<StoragePoolVO>();
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.Maintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.PrepareForMaintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(Status.ErrorInMaintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(StoragePoolStatus.Maintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(StoragePoolStatus.PrepareForMaintenance));
poolsInTransition.addAll(_poolDao.listPoolsByStatus(StoragePoolStatus.ErrorInMaintenance));
return poolsInTransition.size();
}
@ -4168,7 +4169,7 @@ public class ManagementServerImpl implements ManagementServer {
VolumeVO rootVolume = _volumeDao.findByInstance(instanceId).get(0);
if(rootVolume!=null){
Status poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
StoragePoolStatus poolStatus = _poolDao.findById(rootVolume.getPoolId()).getStatus();
if(!poolStatus.equals(Status.Up)) {
return false;

View File

@ -75,6 +75,8 @@ import com.cloud.async.AsyncInstanceCreateStatus;
import com.cloud.async.AsyncJobManager;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.cluster.ClusterManagerListener;
import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ResourceCount.ResourceType;
@ -115,6 +117,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.NetworkManager;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.offering.ServiceOffering;
import com.cloud.server.ManagementServer;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.Storage.ImageFormat;
@ -127,6 +130,7 @@ import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.StoragePoolWorkDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
@ -138,6 +142,7 @@ 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;
@ -157,19 +162,26 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = { StorageManager.class, StorageService.class })
public class StorageManagerImpl implements StorageManager, StorageService, Manager {
public class StorageManagerImpl implements StorageManager, StorageService, Manager, ClusterManagerListener {
private static final Logger s_logger = Logger.getLogger(StorageManagerImpl.class);
protected String _name;
@ -212,6 +224,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
@Inject protected ClusterDao _clusterDao;
@Inject protected VirtualNetworkApplianceManager _routerMgr;
@Inject protected UsageEventDao _usageEventDao;
@Inject protected VirtualMachineManager _vmMgr;
@Inject protected DomainRouterDao _domrDao;
@Inject protected SecondaryStorageVmDao _secStrgDao;
@Inject protected StoragePoolWorkDao _storagePoolWorkDao;
@Inject(adapter=StoragePoolAllocator.class)
@ -235,6 +251,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
private int _totalRetries;
private int _pauseInterval;
private final boolean _shouldBeSnapshotCapable = true;
private long _serverId;
public boolean share(VMInstanceVO vm, List<VolumeVO> vols, HostVO host, boolean cancelPreviousShare) throws StorageUnavailableException {
@ -305,7 +322,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
List<StoragePoolVO> pools = _storagePoolDao.listAll();
//if no pools or 1 pool which is in maintenance
if(pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(Status.Maintenance) )){
if(pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(StoragePoolStatus.Maintenance) )){
return false;
}else{
return true;
@ -867,6 +884,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
HostSearch.done();
HostTemplateStatesSearch.done();
_serverId = ((ManagementServer)ComponentLocator.getComponent(ManagementServer.Name)).getId();
return true;
}
@ -1171,7 +1190,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
pool.setPodId(podId);
pool.setName(cmd.getStoragePoolName());
pool.setClusterId(clusterId);
pool.setStatus(Status.Up);
pool.setStatus(StoragePoolStatus.Up);
pool = _storagePoolDao.persist(pool, details);
if (allHosts.isEmpty()) {
return pool;
@ -1297,7 +1316,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
_storagePoolHostDao.deleteStoragePoolHostDetails(host.getHostId(),host.getPoolId());
}
sPool.setUuid(null);
sPool.setStatus(Status.Removed);
sPool.setStatus(StoragePoolStatus.Removed);
_storagePoolDao.update(id, sPool);
_storagePoolDao.remove(id);
deleteHostorPoolStats(id);
@ -1905,148 +1924,211 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
@Override @DB
public synchronized StoragePoolVO preparePrimaryStorageForMaintenance(PreparePrimaryStorageForMaintenanceCmd cmd) throws ServerApiException{
public StoragePoolVO preparePrimaryStorageForMaintenance(PreparePrimaryStorageForMaintenanceCmd cmd) throws ServerApiException{
Long primaryStorageId = cmd.getId();
Long userId = UserContext.current().getCallerUserId();
User user = _userDao.findById(userId);
Account account = UserContext.current().getCaller();
boolean restart = true;
StoragePoolVO primaryStorage = null;
try
{
Transaction.currentTxn();
//1. Get the primary storage record and perform validation check
primaryStorage = _storagePoolDao.acquireInLockTable(primaryStorageId);
if(primaryStorage == null){
String msg = "Unable to obtain lock on the storage pool in preparePrimaryStorageForMaintenance()";
s_logger.error(msg);
throw new ExecutionException(msg);
}
if (!primaryStorage.getStatus().equals(Status.Up) && !primaryStorage.getStatus().equals(Status.ErrorInMaintenance)) {
throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + primaryStorage.getStatus().toString());
}
//set the pool state to prepare for maintenance
primaryStorage.setStatus(Status.PrepareForMaintenance);
_storagePoolDao.persist(primaryStorage);
Transaction txn = Transaction.currentTxn();
txn.start();
//1. Get the primary storage record and perform validation check
primaryStorage = _storagePoolDao.lockRow(primaryStorageId, true);
if(primaryStorage == null){
String msg = "Unable to obtain lock on the storage pool record in preparePrimaryStorageForMaintenance()";
s_logger.error(msg);
throw new ExecutionException(msg);
}
if (!primaryStorage.getStatus().equals(StoragePoolStatus.Up) && !primaryStorage.getStatus().equals(StoragePoolStatus.ErrorInMaintenance)) {
throw new InvalidParameterValueException("Primary storage with id " + primaryStorageId + " is not ready for migration, as the status is:" + primaryStorage.getStatus().toString());
}
//set the pool state to prepare for maintenance
primaryStorage.setStatus(StoragePoolStatus.PrepareForMaintenance);
_storagePoolDao.update(primaryStorageId,primaryStorage);
txn.commit();
//check to see if other ps exist
//if they do, then we can migrate over the system vms to them
//if they dont, then just stop all vms on this one
List<StoragePoolVO> upPools = _storagePoolDao.listPoolsByStatus(Status.Up);
List<StoragePoolVO> upPools = _storagePoolDao.listPoolsByStatus(StoragePoolStatus.Up);
if(upPools == null || upPools.size() == 0) {
restart = false;
}
//2. Get a list of all the volumes within this storage pool
//2. Get a list of all the ROOT volumes within this storage pool
List<VolumeVO> allVolumes = _volsDao.findByPoolId(primaryStorageId);
//3. Each volume has an instance associated with it, stop the instance if running
for(VolumeVO volume : allVolumes)
{
VMInstanceVO vmInstance = _vmInstanceDao.findById(volume.getInstanceId());
if(vmInstance == null) {
//3. Enqueue to the work queue
for(VolumeVO volume : allVolumes)
{
VMInstanceVO vmInstance = _vmInstanceDao.findById(volume.getInstanceId());
if(vmInstance == null) {
continue;
}
//shut down the running vms
if(vmInstance.getState().equals(State.Running) || vmInstance.getState().equals(State.Starting) || vmInstance.getState().equals(State.Stopping))
{
//if the instance is of type consoleproxy, call the console proxy
if(vmInstance.getType().equals(VirtualMachine.Type.ConsoleProxy))
{
//make sure it is not restarted again, update config to set flag to false
_configMgr.updateConfiguration(userId, "consoleproxy.restart", "false");
//call the consoleproxymanager
if(!_consoleProxyMgr.stopProxy(vmInstance.getId()))
{
String errorMsg = "There was an error stopping the console proxy id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
else if(restart)
{
//Restore config val for consoleproxy.restart to true
_configMgr.updateConfiguration(userId, "consoleproxy.restart", "true");
if(_consoleProxyMgr.startProxy(vmInstance.getId())==null)
{
String errorMsg = "There was an error starting the console proxy id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
}
}
//if the instance is of type uservm, call the user vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.User))
{
//create a dummy event
if(!_userVmMgr.stopVirtualMachine(userId, vmInstance.getId()))
{
String errorMsg = "There was an error stopping the user vm id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
}
//if the instance is of type secondary storage vm, call the secondary storage vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.SecondaryStorageVm))
{
if(!_secStorageMgr.stopSecStorageVm(vmInstance.getId()))
{
String errorMsg = "There was an error stopping the ssvm id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
else if(restart)
{
if(_secStorageMgr.startSecStorageVm(vmInstance.getId()) == null)
{
String errorMsg = "There was an error starting the ssvm id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
}
}
//enqueue sp work
if(vmInstance.getState().equals(State.Running) || vmInstance.getState().equals(State.Starting) || vmInstance.getState().equals(State.Stopping)){
//if the instance is of type domain router vm, call the network manager
if(vmInstance.getType().equals(VirtualMachine.Type.DomainRouter))
{
if(_routerMgr.stopRouter(vmInstance.getId()) == null)
{
String errorMsg = "There was an error stopping the domain router id: "+vmInstance.getId()+" ,cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
else if(restart)
{
if(_routerMgr.startRouter(vmInstance.getId()) == null)
{
String errorMsg = "There was an error starting the domain router id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
setPoolStateToError(primaryStorage);
throw new CloudRuntimeException(errorMsg);
}
}
try {
StoragePoolWorkVO work = new StoragePoolWorkVO(vmInstance.getId(),primaryStorageId, false, false, _serverId);
_storagePoolWorkDao.persist(work);
} catch (Exception e) {
if(s_logger.isDebugEnabled())
s_logger.debug("Work record already exists, re-using by re-setting values");
StoragePoolWorkVO work = _storagePoolWorkDao.findByPoolIdAndVmId(primaryStorageId, vmInstance.getId());
work.setStartedAfterMaintenance(false);
work.setStoppedForMaintenance(false);
work.setManagementServerId(_serverId);
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
txn.commit();
txn.close();
//4. Process the queue
List<StoragePoolWorkVO> pendingWork = _storagePoolWorkDao.listPendingWorkForPrepareForMaintenanceByPoolId(primaryStorageId);
for(StoragePoolWorkVO work : pendingWork)
{
//shut down the running vms
VMInstanceVO vmInstance = _vmInstanceDao.findById(work.getVmId());
if(vmInstance == null)
continue;
//if the instance is of type consoleproxy, call the console proxy
if(vmInstance.getType().equals(VirtualMachine.Type.ConsoleProxy))
{
//make sure it is not restarted again, update config to set flag to false
if(!restart) {
_configMgr.updateConfiguration(userId, "consoleproxy.restart", "false");
}
//call the consoleproxymanager
ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(vmInstance.getId());
if(!_vmMgr.advanceStop(consoleProxy, true, user, account))
{
String errorMsg = "There was an error stopping the console proxy id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
if(restart)
{
//Restore config val for consoleproxy.restart to true
_configMgr.updateConfiguration(userId, "consoleproxy.restart", "true");
if(_vmMgr.advanceStart(consoleProxy, null, user, account) == null)
{
String errorMsg = "There was an error starting the console proxy id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
//if the instance is of type uservm, call the user vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.User))
{
UserVmVO userVm = _userVmDao.findById(vmInstance.getId());
if(!_vmMgr.advanceStop(userVm, true, user, account))
{
String errorMsg = "There was an error stopping the user vm id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
//if the instance is of type secondary storage vm, call the secondary storage vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.SecondaryStorageVm))
{
SecondaryStorageVmVO secStrgVm = _secStrgDao.findById(vmInstance.getId());
if(!_vmMgr.advanceStop(secStrgVm, true, user, account))
{
String errorMsg = "There was an error stopping the ssvm id: "+vmInstance.getId()+" ,cannot enable storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
if(restart)
{
if(_vmMgr.advanceStart(secStrgVm, null, user, account) == null)
{
String errorMsg = "There was an error starting the ssvm id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
//if the instance is of type domain router vm, call the network manager
if(vmInstance.getType().equals(VirtualMachine.Type.DomainRouter))
{
DomainRouterVO domR = _domrDao.findById(vmInstance.getId());
if(!_vmMgr.advanceStop(domR, true, user, account))
{
String errorMsg = "There was an error stopping the domain router id: "+vmInstance.getId()+" ,cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
if(restart)
{
if(_vmMgr.advanceStart(domR, null, user, account) == null)
{
String errorMsg = "There was an error starting the domain router id: "+vmInstance.getId()+" on another storage pool, cannot enable primary storage maintenance";
s_logger.warn(errorMsg);
throw new CloudRuntimeException(errorMsg);
} else {
//update work status
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
}
//5. Update the status
primaryStorage.setStatus(Status.Maintenance);
_storagePoolDao.persist(primaryStorage);
return _storagePoolDao.findById(primaryStorageId);
primaryStorage.setStatus(StoragePoolStatus.Maintenance);
_storagePoolDao.update(primaryStorageId,primaryStorage);
return _storagePoolDao.findById(primaryStorageId);
} catch (Exception e) {
if(e instanceof ExecutionException || e instanceof ResourceUnavailableException){
s_logger.error("Exception in enabling primary storage maintenance:",e);
@ -2068,26 +2150,27 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
setPoolStateToError(primaryStorage);
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, e.getMessage());
}finally{
_storagePoolDao.releaseFromLockTable(primaryStorage.getId());
}
}
private void setPoolStateToError(StoragePoolVO primaryStorage) {
primaryStorage.setStatus(Status.ErrorInMaintenance);
_storagePoolDao.persist(primaryStorage);
primaryStorage.setStatus(StoragePoolStatus.ErrorInMaintenance);
_storagePoolDao.update(primaryStorage.getId(),primaryStorage);
}
@Override
@DB
public synchronized StoragePoolVO cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ServerApiException{
public StoragePoolVO cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ServerApiException{
Long primaryStorageId = cmd.getId();
Long userId = UserContext.current().getCallerUserId();
User user = _userDao.findById(userId);
Account account = UserContext.current().getCaller();
StoragePoolVO primaryStorage = null;
try {
Transaction.currentTxn();
Transaction txn = Transaction.currentTxn();
txn.start();
//1. Get the primary storage record and perform validation check
primaryStorage = _storagePoolDao.acquireInLockTable(primaryStorageId);
primaryStorage = _storagePoolDao.lockRow(primaryStorageId, true);
if(primaryStorage == null){
String msg = "Unable to obtain lock on the storage pool in cancelPrimaryStorageForMaintenance()";
@ -2095,82 +2178,111 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
throw new ExecutionException(msg);
}
if (primaryStorage.getStatus().equals(Status.Up) || primaryStorage.getStatus().equals(Status.PrepareForMaintenance)) {
if (primaryStorage.getStatus().equals(StoragePoolStatus.Up) || primaryStorage.getStatus().equals(StoragePoolStatus.PrepareForMaintenance)) {
throw new StorageUnavailableException("Primary storage with id " + primaryStorageId + " is not ready to complete migration, as the status is:" + primaryStorage.getStatus().toString(), primaryStorageId);
}
//set state to cancelmaintenance
primaryStorage.setStatus(Status.CancelMaintenance);
_storagePoolDao.persist(primaryStorage);
primaryStorage.setStatus(StoragePoolStatus.CancelMaintenance);
_storagePoolDao.update(primaryStorageId,primaryStorage);
txn.commit();
txn.close();
//2. Get a list of all the volumes within this storage pool
List<VolumeVO> allVolumes = _volsDao.findByPoolId(primaryStorageId);
//2. Get a list of pending work for this queue
List<StoragePoolWorkVO> pendingWork = _storagePoolWorkDao.listPendingWorkForCancelMaintenanceByPoolId(primaryStorageId);
//3. If the volume is not removed AND not destroyed, start the vm corresponding to it
for(VolumeVO volume: allVolumes)
//3. work through the queue
for(StoragePoolWorkVO work: pendingWork)
{
if((volume.getState() != Volume.State.Destroy) && (volume.getRemoved() == null))
{
VMInstanceVO vmInstance = _vmInstanceDao.findById(volume.getInstanceId());
if(vmInstance.getState().equals(State.Stopping) || vmInstance.getState().equals(State.Stopped))
VMInstanceVO vmInstance = _vmInstanceDao.findById(work.getVmId());
if(vmInstance == null)
continue;
//if the instance is of type consoleproxy, call the console proxy
if(vmInstance.getType().equals(VirtualMachine.Type.ConsoleProxy))
{
ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(vmInstance.getId());
if(_vmMgr.advanceStart(consoleProxy, null, user, account) == null)
{
//if the instance is of type consoleproxy, call the console proxy
if(vmInstance.getType().equals(VirtualMachine.Type.ConsoleProxy))
{
if(_consoleProxyMgr.startProxy(vmInstance.getId()) == null)
{
String msg = "There was an error starting the console proxy id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
}
}
//if the instance is of type ssvm, call the ssvm manager
if(vmInstance.getType().equals(VirtualMachine.Type.SecondaryStorageVm))
{
if(_secStorageMgr.startSecStorageVm(vmInstance.getId()) == null)
{
String msg = "There was an error starting the ssvm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
}
}
//if the instance is of type user vm, call the user vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.User))
{
try {
if(_userVmMgr.startUserVm(vmInstance.getId()) == null)
{
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
}
} catch (StorageUnavailableException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
} catch (InsufficientCapacityException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
} catch (ConcurrentOperationException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
setPoolStateToError(primaryStorage);
throw new ExecutionException(msg);
} catch (ExecutionException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
}
}
String msg = "There was an error starting the console proxy id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
} else {
//update work queue
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
//if the instance is of type ssvm, call the ssvm manager
if(vmInstance.getType().equals(VirtualMachine.Type.SecondaryStorageVm))
{
SecondaryStorageVmVO ssVm = _secStrgDao.findById(vmInstance.getId());
if(_vmMgr.advanceStart(ssVm, null, user, account) == null)
{
String msg = "There was an error starting the ssvm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
}else {
//update work queue
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
//if the instance is of type ssvm, call the ssvm manager
if(vmInstance.getType().equals(VirtualMachine.Type.DomainRouter))
{
DomainRouterVO domR = _domrDao.findById(vmInstance.getId());
if(_vmMgr.advanceStart(domR, null, user, account) == null)
{
String msg = "There was an error starting the domR id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
}else {
//update work queue
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
//if the instance is of type user vm, call the user vm manager
if(vmInstance.getType().equals(VirtualMachine.Type.User))
{
UserVmVO userVm = _userVmDao.findById(vmInstance.getId());
try {
if(_vmMgr.advanceStart(userVm, null, user, account) == null)
{
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg);
throw new ExecutionException(msg);
} else {
//update work queue
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
} catch (StorageUnavailableException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
} catch (InsufficientCapacityException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
} catch (ConcurrentOperationException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
} catch (ExecutionException e) {
String msg = "There was an error starting the user vm id: "+vmInstance.getId()+" on storage pool, cannot complete primary storage maintenance";
s_logger.warn(msg,e);
throw new ExecutionException(msg);
}
}
}
//Restore config val for consoleproxy.restart to true
@ -2187,8 +2299,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
//Change the storage state back to up
primaryStorage.setStatus(Status.Up);
_storagePoolDao.persist(primaryStorage);
primaryStorage.setStatus(StoragePoolStatus.Up);
_storagePoolDao.update(primaryStorageId, primaryStorage);
return primaryStorage;
} catch (Exception e) {
@ -2202,8 +2314,6 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
else{//all other exceptions
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, e.getMessage());
}
}finally{
_storagePoolDao.releaseFromLockTable(primaryStorage.getId());
}
}
@ -2667,5 +2777,33 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
}
}
@Override
public void onManagementNodeJoined(List<ManagementServerHostVO> nodeList, long selfNodeId) {
// TODO Auto-generated method stub
}
@Override
public void onManagementNodeLeft(List<ManagementServerHostVO> nodeList, long selfNodeId) {
for (ManagementServerHostVO vo : nodeList) {
if(vo.getMsid() == _serverId) {
s_logger.info("Cleaning up storage maintenance jobs associated with Management server" + vo.getMsid());
List<Long> poolIds = _storagePoolWorkDao.searchForPoolIdsForPendingWorkJobs(vo.getMsid());
if(poolIds.size() > 0) {
for(Long poolId : poolIds) {
StoragePoolVO pool = _storagePoolDao.findById(poolId);
//check if pool is in an inconsistent state
if(pool != null && (pool.getStatus().equals(StoragePoolStatus.ErrorInMaintenance) || pool.getStatus().equals(StoragePoolStatus.PrepareForMaintenance) || pool.getStatus().equals(StoragePoolStatus.CancelMaintenance))) {
_storagePoolWorkDao.removePendingJobsOnMsRestart(vo.getMsid(), poolId);
pool.setStatus(StoragePoolStatus.ErrorInMaintenance);
_storagePoolDao.update(poolId, pool);
}
}
}
}
}
}
}

View File

@ -39,6 +39,7 @@ import com.cloud.server.StatsCollector;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageStats;
import com.cloud.storage.VMTemplateHostVO;
@ -139,7 +140,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
//by default, all pools are up when successfully added
//don't return the pool if not up (if in maintenance/prepareformaintenance/errorinmaintenance)
if(!pool.getStatus().equals(com.cloud.host.Status.Up))
if(!pool.getStatus().equals(StoragePoolStatus.Up))
return false;
// Check that the pool type is correct

View File

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
import com.cloud.host.Status;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.utils.db.GenericDao;
/**
@ -104,6 +105,5 @@ public interface StoragePoolDao extends GenericDao<StoragePoolVO, Long> {
List<StoragePoolVO> findIfDuplicatePoolsExistByUUID(String uuid);
List<StoragePoolVO> listPoolsByStatus(Status status);
List<StoragePoolVO> listPoolsByStatus(StoragePoolStatus status);
}

View File

@ -31,6 +31,7 @@ import javax.naming.ConfigurationException;
import com.cloud.host.Status;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePoolDetailVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
@ -185,7 +186,7 @@ public class StoragePoolDaoImpl extends GenericDaoBase<StoragePoolVO, Long> imp
}
@Override
public List<StoragePoolVO> listPoolsByStatus(Status status){
public List<StoragePoolVO> listPoolsByStatus(StoragePoolStatus status){
SearchCriteria<StoragePoolVO> sc = StatusSearch.create();
sc.setParameters("status", status);
return listBy(sc);

View File

@ -0,0 +1,39 @@
/**
* Copyright (C) 2010 Cloud.com, 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.storage.dao;
import java.util.List;
import com.cloud.storage.StoragePoolWorkVO;
import com.cloud.utils.db.GenericDao;
/**
* Data Access Object for storage_pool table
*/
public interface StoragePoolWorkDao extends GenericDao<StoragePoolWorkVO, Long> {
List<StoragePoolWorkVO> listPendingWorkForPrepareForMaintenanceByPoolId(long poolId);
List<StoragePoolWorkVO> listPendingWorkForCancelMaintenanceByPoolId(long poolId);
StoragePoolWorkVO findByPoolIdAndVmId(long poolId, long vmId);
void removePendingJobsOnMsRestart(long msId, long poolId);
List<Long> searchForPoolIdsForPendingWorkJobs(long msId);
}

View File

@ -0,0 +1,134 @@
/**
* Copyright (C) 2010 Cloud.com, 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.storage.dao;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import com.cloud.storage.StoragePoolWorkVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value={StoragePoolWorkDao.class}) @DB(txn=false)
public class StoragePoolWorkDaoImpl extends GenericDaoBase<StoragePoolWorkVO, Long> implements StoragePoolWorkDao {
protected final SearchBuilder<StoragePoolWorkVO> PendingWorkForPrepareForMaintenanceSearch;
protected final SearchBuilder<StoragePoolWorkVO> PendingWorkForCancelMaintenanceSearch;
protected final SearchBuilder<StoragePoolWorkVO> PoolAndVmIdSearch;
protected final SearchBuilder<StoragePoolWorkVO> PendingJobsForDeadMs;
private final String FindPoolIds = "SELECT distinct storage_pool_work.pool_id FROM storage_pool_work WHERE mgmt_server_id = ?";
protected StoragePoolWorkDaoImpl() {
PendingWorkForPrepareForMaintenanceSearch = createSearchBuilder();
PendingWorkForPrepareForMaintenanceSearch.and("poolId", PendingWorkForPrepareForMaintenanceSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
PendingWorkForPrepareForMaintenanceSearch.and("stoppedForMaintenance", PendingWorkForPrepareForMaintenanceSearch.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ);
PendingWorkForPrepareForMaintenanceSearch.and("startedAfterMaintenance", PendingWorkForPrepareForMaintenanceSearch.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ);
PendingWorkForPrepareForMaintenanceSearch.done();
PendingWorkForCancelMaintenanceSearch = createSearchBuilder();
PendingWorkForCancelMaintenanceSearch.and("poolId", PendingWorkForCancelMaintenanceSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
PendingWorkForCancelMaintenanceSearch.and("stoppedForMaintenance", PendingWorkForCancelMaintenanceSearch.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ);
PendingWorkForCancelMaintenanceSearch.and("startedAfterMaintenance", PendingWorkForCancelMaintenanceSearch.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ);
PendingWorkForCancelMaintenanceSearch.done();
PoolAndVmIdSearch = createSearchBuilder();
PoolAndVmIdSearch.and("poolId", PoolAndVmIdSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
PoolAndVmIdSearch.and("vmId", PoolAndVmIdSearch.entity().getVmId(), SearchCriteria.Op.EQ);
PoolAndVmIdSearch.done();
PendingJobsForDeadMs = createSearchBuilder();
PendingJobsForDeadMs.and("managementServerId", PendingJobsForDeadMs.entity().getManagementServerId(), SearchCriteria.Op.EQ);
PendingJobsForDeadMs.and("poolId", PendingJobsForDeadMs.entity().getPoolId(), SearchCriteria.Op.EQ);
PendingJobsForDeadMs.and("stoppedForMaintenance", PendingJobsForDeadMs.entity().isStoppedForMaintenance(), SearchCriteria.Op.EQ);
PendingJobsForDeadMs.and("startedAfterMaintenance", PendingJobsForDeadMs.entity().isStartedAfterMaintenance(), SearchCriteria.Op.EQ);
PendingJobsForDeadMs.done();
}
@Override
public List<StoragePoolWorkVO> listPendingWorkForPrepareForMaintenanceByPoolId(long poolId) {
SearchCriteria<StoragePoolWorkVO> sc = PendingWorkForPrepareForMaintenanceSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("stoppedForMaintenance", false);
sc.setParameters("startedAfterMaintenance", false);
return listBy(sc);
}
@Override
public List<StoragePoolWorkVO> listPendingWorkForCancelMaintenanceByPoolId(long poolId) {
SearchCriteria<StoragePoolWorkVO> sc = PendingWorkForCancelMaintenanceSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("stoppedForMaintenance", true);
sc.setParameters("startedAfterMaintenance", false);
return listBy(sc);
}
@Override
public StoragePoolWorkVO findByPoolIdAndVmId(long poolId, long vmId) {
SearchCriteria<StoragePoolWorkVO> sc = PoolAndVmIdSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("vmId", vmId);
return listBy(sc).get(0);
}
@Override
public void removePendingJobsOnMsRestart(long msId, long poolId) {
//hung jobs are those which are stopped, but never started
SearchCriteria<StoragePoolWorkVO> sc = PendingJobsForDeadMs.create();
sc.setParameters("managementServerId", msId);
sc.setParameters("poolId", poolId);
sc.setParameters("stoppedForMaintenance", true);
sc.setParameters("startedAfterMaintenance", false);
remove(sc);
}
@Override
@DB
public List<Long> searchForPoolIdsForPendingWorkJobs(long msId){
StringBuilder sql = new StringBuilder(FindPoolIds);
Transaction txn = Transaction.currentTxn();
PreparedStatement pstmt = null;
try {
pstmt = txn.prepareAutoCloseStatement(sql.toString());
pstmt.setLong(1, msId);
ResultSet rs = pstmt.executeQuery();
List<Long> poolIds = new ArrayList<Long>();
while (rs.next()) {
poolIds.add(rs.getLong("pool_id"));
}
return poolIds;
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to execute " + pstmt.toString(), e);
}
}
}

View File

@ -122,6 +122,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("notDestroyed", Volume.State.Destroy);
sc.setParameters("vType", Volume.VolumeType.ROOT.toString());
return listBy(sc);
}

View File

@ -133,6 +133,11 @@ import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.StorageResourceType;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.VMTemplateHostVO;
@ -1906,7 +1911,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
_accountMgr.checkAccess(owner, domain);
}
//check if we have available pools for vm deployment
List<StoragePoolVO> availablePools = _storagePoolDao.listPoolsByStatus(com.cloud.host.Status.Up);
List<StoragePoolVO> availablePools = _storagePoolDao.listPoolsByStatus(StoragePoolStatus.Up);
if( availablePools == null || availablePools.size() < 1) {
throw new StorageUnavailableException("There are no available pools in the UP state for vm deployment",-1);

View File

@ -559,7 +559,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, StateLi
long vmId = vm.getId();
VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
vm = vmGuru.findById(vm.getId());
Ternary<T, ReservationContext, ItWorkVO> start = changeToStartState(vmGuru, vm, caller, account);
if (start == null) {
return vmGuru.findById(vmId);

View File

@ -1385,4 +1385,15 @@ CREATE TABLE `cloud`.`ovs_work` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`storage_pool_work` (
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id',
`pool_id` bigint unsigned NOT NULL COMMENT 'storage pool associated with the vm',
`vm_id` bigint unsigned NOT NULL COMMENT 'vm identifier',
`stopped_for_maintenance` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'this flag denoted whether the vm was stopped during maintenance',
`started_after_maintenance` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'this flag denoted whether the vm was started after maintenance',
`mgmt_server_id` bigint unsigned NOT NULL COMMENT 'management server id',
PRIMARY KEY (`id`),
UNIQUE (pool_id,vm_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET foreign_key_checks = 1;