use of com.cloud.storage.datastore.db.StoragePoolVO in project cosmic by MissionCriticalCloud.
the class StoragePoolAutomationImpl method maintain.
@Override
public boolean maintain(final DataStore store) {
final Long userId = CallContext.current().getCallingUserId();
final User user = _userDao.findById(userId);
final Account account = CallContext.current().getCallingAccount();
final StoragePoolVO pool = primaryDataStoreDao.findById(store.getId());
try {
List<StoragePoolVO> spes = null;
// if the storage is ZONE wide then we pass podid and cluster id as null as they will be empty for ZWPS
if (pool.getScope() == ScopeType.ZONE) {
spes = primaryDataStoreDao.listBy(pool.getDataCenterId(), null, null, ScopeType.ZONE);
} else {
spes = primaryDataStoreDao.listBy(pool.getDataCenterId(), pool.getPodId(), pool.getClusterId(), ScopeType.CLUSTER);
}
for (final StoragePoolVO sp : spes) {
if (sp.getStatus() == StoragePoolStatus.PrepareForMaintenance) {
throw new CloudRuntimeException("Only one storage pool in a cluster can be in PrepareForMaintenance mode, " + sp.getId() + " is already in PrepareForMaintenance mode ");
}
}
final StoragePool storagePool = (StoragePool) store;
// Handeling the Zone wide and cluster wide primay storage
List<HostVO> hosts = new ArrayList<>();
// TODO: if it's zone wide, this code will list a lot of hosts in the zone, which may cause performance/OOM issue.
if (pool.getScope().equals(ScopeType.ZONE)) {
if (HypervisorType.Any.equals(pool.getHypervisor())) {
hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZone(pool.getDataCenterId());
} else {
hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(pool.getHypervisor(), pool.getDataCenterId());
}
} else {
hosts = _resourceMgr.listHostsInClusterByStatus(pool.getClusterId(), Status.Up);
}
if (hosts == null || hosts.size() == 0) {
pool.setStatus(StoragePoolStatus.Maintenance);
primaryDataStoreDao.update(pool.getId(), pool);
return true;
} else {
// set the pool state to prepare for maintenance
pool.setStatus(StoragePoolStatus.PrepareForMaintenance);
primaryDataStoreDao.update(pool.getId(), pool);
}
// remove heartbeat
for (final HostVO host : hosts) {
final ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(false, storagePool);
final Answer answer = agentMgr.easySend(host.getId(), cmd);
if (answer == null || !answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("ModifyStoragePool false failed due to " + ((answer == null) ? "answer null" : answer.getDetails()));
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("ModifyStoragePool false succeeded");
}
}
}
// 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
final List<StoragePoolVO> upPools = primaryDataStoreDao.listByStatusInZone(pool.getDataCenterId(), StoragePoolStatus.Up);
boolean restart = true;
if (upPools == null || upPools.size() == 0) {
restart = false;
}
// 2. Get a list of all the ROOT volumes within this storage pool
final List<VolumeVO> allVolumes = volumeDao.findByPoolId(pool.getId());
// 3. Enqueue to the work queue
for (final VolumeVO volume : allVolumes) {
final VMInstanceVO vmInstance = vmDao.findById(volume.getInstanceId());
if (vmInstance == null) {
continue;
}
// enqueue sp work
if (vmInstance.getState().equals(State.Running) || vmInstance.getState().equals(State.Starting) || vmInstance.getState().equals(State.Stopping)) {
try {
final StoragePoolWorkVO work = new StoragePoolWorkVO(vmInstance.getId(), pool.getId(), false, false, server.getId());
_storagePoolWorkDao.persist(work);
} catch (final Exception e) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Work record already exists, re-using by re-setting values");
}
final StoragePoolWorkVO work = _storagePoolWorkDao.findByPoolIdAndVmId(pool.getId(), vmInstance.getId());
work.setStartedAfterMaintenance(false);
work.setStoppedForMaintenance(false);
work.setManagementServerId(server.getId());
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
// 4. Process the queue
final List<StoragePoolWorkVO> pendingWork = _storagePoolWorkDao.listPendingWorkForPrepareForMaintenanceByPoolId(pool.getId());
for (final StoragePoolWorkVO work : pendingWork) {
// shut down the running vms
final VMInstanceVO vmInstance = vmDao.findById(work.getVmId());
if (vmInstance == null) {
continue;
}
// proxy
if (vmInstance.getType().equals(VirtualMachine.Type.ConsoleProxy)) {
// call the consoleproxymanager
final ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(vmInstance.getId());
vmMgr.advanceStop(consoleProxy.getUuid(), false);
// update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
if (restart) {
vmMgr.advanceStart(consoleProxy.getUuid(), null, null);
// 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() == VirtualMachine.Type.User) {
final UserVmVO userVm = userVmDao.findById(vmInstance.getId());
vmMgr.advanceStop(userVm.getUuid(), false);
// update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
// secondary storage vm manager
if (vmInstance.getType().equals(VirtualMachine.Type.SecondaryStorageVm)) {
final SecondaryStorageVmVO secStrgVm = _secStrgDao.findById(vmInstance.getId());
vmMgr.advanceStop(secStrgVm.getUuid(), false);
// update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
if (restart) {
vmMgr.advanceStart(secStrgVm.getUuid(), null, null);
// update work status
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
// manager
if (vmInstance.getType().equals(VirtualMachine.Type.DomainRouter)) {
final DomainRouterVO domR = _domrDao.findById(vmInstance.getId());
vmMgr.advanceStop(domR.getUuid(), false);
// update work status
work.setStoppedForMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
if (restart) {
vmMgr.advanceStart(domR.getUuid(), null, null);
// update work status
work.setStartedAfterMaintenance(true);
_storagePoolWorkDao.update(work.getId(), work);
}
}
}
} catch (final Exception e) {
s_logger.error("Exception in enabling primary storage maintenance:", e);
pool.setStatus(StoragePoolStatus.ErrorInMaintenance);
primaryDataStoreDao.update(pool.getId(), pool);
throw new CloudRuntimeException(e.getMessage());
}
return true;
}
use of com.cloud.storage.datastore.db.StoragePoolVO in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method orchestrateResizeVolume.
private VolumeVO orchestrateResizeVolume(final long volumeId, final long currentSize, final long newSize, final Long newMinIops, final Long newMaxIops, final Long newDiskOfferingId, final boolean shrinkOk) {
VolumeVO volume = _volsDao.findById(volumeId);
final UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
/*
* get a list of hosts to send the commands to, try the system the
* associated vm is running on first, then the last known place it ran.
* If not attached to a userVm, we pass 'none' and resizevolume.sh is ok
* with that since it only needs the vm name to live resize
*/
long[] hosts = null;
String instanceName = "none";
if (userVm != null) {
instanceName = userVm.getInstanceName();
if (userVm.getHostId() != null) {
hosts = new long[] { userVm.getHostId() };
} else if (userVm.getLastHostId() != null) {
hosts = new long[] { userVm.getLastHostId() };
}
final String errorMsg = "The VM must be stopped or the disk detached in order to resize with the XenServer Hypervisor.";
final StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
if (storagePool.isManaged() && storagePool.getHypervisor() == HypervisorType.Any && hosts != null && hosts.length > 0) {
final HostVO host = _hostDao.findById(hosts[0]);
if (currentSize != newSize && host.getHypervisorType() == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) {
throw new InvalidParameterValueException(errorMsg);
}
}
/* Xen only works offline, SR does not support VDI.resizeOnline */
if (currentSize != newSize && _volsDao.getHypervisorType(volume.getId()) == HypervisorType.XenServer && !userVm.getState().equals(State.Stopped)) {
throw new InvalidParameterValueException(errorMsg);
}
}
final ResizeVolumePayload payload = new ResizeVolumePayload(newSize, newMinIops, newMaxIops, shrinkOk, instanceName, hosts);
try {
final VolumeInfo vol = volFactory.getVolume(volume.getId());
vol.addPayload(payload);
final StoragePoolVO storagePool = _storagePoolDao.findById(vol.getPoolId());
// needs to tell the hypervisor to resize the disk
if (storagePool.isManaged() && currentSize != newSize) {
if (hosts != null && hosts.length > 0) {
volService.resizeVolumeOnHypervisor(volumeId, newSize, hosts[0], instanceName);
}
volume.setSize(newSize);
_volsDao.update(volume.getId(), volume);
}
// this call to resize has a different impact depending on whether the
// underlying primary storage is managed or not
// if managed, this is the chance for the plug-in to change IOPS value, if applicable
// if not managed, this is the chance for the plug-in to talk to the hypervisor layer
// to change the size of the disk
final AsyncCallFuture<VolumeApiResult> future = volService.resize(vol);
final VolumeApiResult result = future.get();
if (result.isFailed()) {
s_logger.warn("Failed to resize the volume " + volume);
String details = "";
if (result.getResult() != null && !result.getResult().isEmpty()) {
details = result.getResult();
}
throw new CloudRuntimeException(details);
}
volume = _volsDao.findById(volume.getId());
if (newDiskOfferingId != null) {
volume.setDiskOfferingId(newDiskOfferingId);
}
if (currentSize != newSize) {
volume.setSize(newSize);
}
_volsDao.update(volume.getId(), volume);
/* Update resource count for the account on primary storage resource */
if (!shrinkOk) {
_resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplayVolume(), new Long(newSize - currentSize));
} else {
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.primary_storage, volume.isDisplayVolume(), new Long(currentSize - newSize));
}
return volume;
} catch (final InterruptedException e) {
s_logger.warn("failed get resize volume result", e);
throw new CloudRuntimeException(e.getMessage());
} catch (final ExecutionException e) {
s_logger.warn("failed get resize volume result", e);
throw new CloudRuntimeException(e.getMessage());
} catch (final Exception e) {
s_logger.warn("failed get resize volume result", e);
throw new CloudRuntimeException(e.getMessage());
}
}
use of com.cloud.storage.datastore.db.StoragePoolVO in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method orchestrateDetachVolumeFromVM.
private Volume orchestrateDetachVolumeFromVM(final long vmId, final long volumeId) {
final Volume volume = _volsDao.findById(volumeId);
final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
String errorMsg = "Failed to detach volume " + volume.getName() + " from VM " + vm.getHostName();
boolean sendCommand = vm.getState() == State.Running;
final Long hostId = vm.getHostId();
HostVO host = null;
final StoragePoolVO volumePool = _storagePoolDao.findByIdIncludingRemoved(volume.getPoolId());
if (hostId != null) {
host = _hostDao.findById(hostId);
if (host != null && host.getHypervisorType() == HypervisorType.XenServer && volumePool != null && volumePool.isManaged()) {
sendCommand = true;
}
}
Answer answer = null;
if (sendCommand) {
final DataTO volTO = volFactory.getVolume(volume.getId()).getTO();
final DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getPath(), volume.getVolumeType());
final DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName());
cmd.setManaged(volumePool.isManaged());
cmd.setStorageHost(volumePool.getHostAddress());
cmd.setStoragePort(volumePool.getPort());
cmd.set_iScsiName(volume.get_iScsiName());
try {
answer = _agentMgr.send(hostId, cmd);
} catch (final Exception e) {
throw new CloudRuntimeException(errorMsg + " due to: " + e.getMessage());
}
}
if (!sendCommand || answer != null && answer.getResult()) {
// Mark the volume as detached
_volsDao.detachVolume(volume.getId());
// volume.getPoolId() should be null if the VM we are detaching the disk from has never been started before
final DataStore dataStore = volume.getPoolId() != null ? dataStoreMgr.getDataStore(volume.getPoolId(), DataStoreRole.Primary) : null;
volService.revokeAccess(volFactory.getVolume(volume.getId()), host, dataStore);
return _volsDao.findById(volumeId);
} else {
if (answer != null) {
final String details = answer.getDetails();
if (details != null && !details.isEmpty()) {
errorMsg += "; " + details;
}
}
throw new CloudRuntimeException(errorMsg);
}
}
use of com.cloud.storage.datastore.db.StoragePoolVO in project cosmic by MissionCriticalCloud.
the class VolumeApiServiceImpl method attachVolumeToVM.
public Volume attachVolumeToVM(final Long vmId, final Long volumeId, final Long deviceId) {
final Account caller = CallContext.current().getCallingAccount();
// Check that the volume ID is valid
final VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
// Check that the volume is a data volume
if (volumeToAttach == null || !(volumeToAttach.getVolumeType() == Volume.Type.DATADISK || volumeToAttach.getVolumeType() == Volume.Type.ROOT)) {
throw new InvalidParameterValueException("Please specify a volume with the valid type: " + Volume.Type.ROOT.toString() + " or " + Volume.Type.DATADISK.toString());
}
// Check that the volume is not currently attached to any VM
if (volumeToAttach.getInstanceId() != null) {
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
}
// Check that the volume is not destroyed
if (volumeToAttach.getState() == Volume.State.Destroy) {
throw new InvalidParameterValueException("Please specify a volume that is not destroyed.");
}
// Check that the virtual machine ID is valid and it's a user vm
final UserVmVO vm = _userVmDao.findById(vmId);
if (vm == null || vm.getType() != VirtualMachine.Type.User) {
throw new InvalidParameterValueException("Please specify a valid User VM.");
}
// Check that the VM is in the correct state
if (vm.getState() != State.Running && vm.getState() != State.Stopped) {
throw new InvalidParameterValueException("Please specify a VM that is either running or stopped.");
}
// Check that the VM and the volume are in the same zone
if (vm.getDataCenterId() != volumeToAttach.getDataCenterId()) {
throw new InvalidParameterValueException("Please specify a VM that is in the same zone as the volume.");
}
// Check that the device ID is valid
if (deviceId != null) {
// validate ROOT volume type
if (deviceId.longValue() == 0) {
validateRootVolumeDetachAttach(_volsDao.findById(volumeToAttach.getId()), vm);
// vm shouldn't have any volume with deviceId 0
if (!_volsDao.findByInstanceAndDeviceId(vm.getId(), 0).isEmpty()) {
throw new InvalidParameterValueException("Vm already has root volume attached to it");
}
// volume can't be in Uploaded state
if (volumeToAttach.getState() == Volume.State.Uploaded) {
throw new InvalidParameterValueException("No support for Root volume attach in state " + Volume.State.Uploaded);
}
}
}
// that supported by hypervisor
if (deviceId == null || deviceId.longValue() != 0) {
final List<VolumeVO> existingDataVolumes = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
final int maxDataVolumesSupported = getMaxDataVolumesSupported(vm);
if (existingDataVolumes.size() >= maxDataVolumesSupported) {
throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxDataVolumesSupported + "). Please specify another" + " VM.");
}
}
// If local storage is disabled then attaching a volume with local disk
// offering not allowed
final DataCenterVO dataCenter = _dcDao.findById(volumeToAttach.getDataCenterId());
if (!dataCenter.isLocalStorageEnabled()) {
final DiskOfferingVO diskOffering = _diskOfferingDao.findById(volumeToAttach.getDiskOfferingId());
if (diskOffering.getUseLocalStorage()) {
throw new InvalidParameterValueException("Zone is not configured to use local storage but volume's disk offering " + diskOffering.getName() + " uses it");
}
}
// if target VM has associated VM snapshots
final List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
if (vmSnapshots.size() > 0) {
throw new InvalidParameterValueException("Unable to attach volume, please specify a VM that does not have VM snapshots");
}
// permission check
_accountMgr.checkAccess(caller, null, true, volumeToAttach, vm);
if (!(Volume.State.Allocated.equals(volumeToAttach.getState()) || Volume.State.Ready.equals(volumeToAttach.getState()) || Volume.State.Uploaded.equals(volumeToAttach.getState()))) {
throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or in Uploaded state");
}
final Account owner = _accountDao.findById(volumeToAttach.getAccountId());
if (!(volumeToAttach.getState() == Volume.State.Allocated || volumeToAttach.getState() == Volume.State.Ready)) {
try {
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumeToAttach.getSize());
} catch (final ResourceAllocationException e) {
s_logger.error("primary storage resource limit check failed", e);
throw new InvalidParameterValueException(e.getMessage());
}
}
final HypervisorType rootDiskHyperType = vm.getHypervisorType();
final HypervisorType volumeToAttachHyperType = _volsDao.getHypervisorType(volumeToAttach.getId());
final StoragePoolVO volumeToAttachStoragePool = _storagePoolDao.findById(volumeToAttach.getPoolId());
// only perform this check if the volume's storage pool is not null and not managed
if (volumeToAttachStoragePool != null && !volumeToAttachStoragePool.isManaged()) {
if (volumeToAttachHyperType != HypervisorType.None && rootDiskHyperType != volumeToAttachHyperType) {
throw new InvalidParameterValueException("Can't attach a volume created by: " + volumeToAttachHyperType + " to a " + rootDiskHyperType + " vm");
}
}
final AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
if (asyncExecutionContext != null) {
final AsyncJob job = asyncExecutionContext.getJob();
if (s_logger.isInfoEnabled()) {
s_logger.info("Trying to attaching volume " + volumeId + " to vm instance:" + vm.getId() + ", update async job-" + job.getId() + " progress status");
}
_jobMgr.updateAsyncJobAttachment(job.getId(), "Volume", volumeId);
}
final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
// avoid re-entrance
final VmWorkJobVO placeHolder;
placeHolder = createPlaceHolderWork(vmId);
try {
return orchestrateAttachVolumeToVM(vmId, volumeId, deviceId);
} finally {
_workJobDao.expunge(placeHolder.getId());
}
} else {
final Outcome<Volume> outcome = attachVolumeToVmThroughJobQueue(vmId, volumeId, deviceId);
Volume vol = null;
try {
outcome.get();
} catch (final InterruptedException e) {
throw new RuntimeException("Operation is interrupted", e);
} catch (final java.util.concurrent.ExecutionException e) {
throw new RuntimeException("Execution excetion", e);
}
final Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
if (jobResult != null) {
if (jobResult instanceof ConcurrentOperationException) {
throw (ConcurrentOperationException) jobResult;
} else if (jobResult instanceof InvalidParameterValueException) {
throw (InvalidParameterValueException) jobResult;
} else if (jobResult instanceof RuntimeException) {
throw (RuntimeException) jobResult;
} else if (jobResult instanceof Throwable) {
throw new RuntimeException("Unexpected exception", (Throwable) jobResult);
} else if (jobResult instanceof Long) {
vol = _volsDao.findById((Long) jobResult);
}
}
return vol;
}
}
use of com.cloud.storage.datastore.db.StoragePoolVO in project cosmic by MissionCriticalCloud.
the class StorageManagerImpl method isLocalStorageActiveOnHost.
@Override
public boolean isLocalStorageActiveOnHost(final Long hostId) {
final List<StoragePoolHostVO> storagePoolHostRefs = _storagePoolHostDao.listByHostId(hostId);
for (final StoragePoolHostVO storagePoolHostRef : storagePoolHostRefs) {
final StoragePoolVO PrimaryDataStoreVO = _storagePoolDao.findById(storagePoolHostRef.getPoolId());
if (PrimaryDataStoreVO.getPoolType() == StoragePoolType.LVM || PrimaryDataStoreVO.getPoolType() == StoragePoolType.EXT) {
final SearchBuilder<VolumeVO> volumeSB = _volsDao.createSearchBuilder();
volumeSB.and("poolId", volumeSB.entity().getPoolId(), SearchCriteria.Op.EQ);
volumeSB.and("removed", volumeSB.entity().getRemoved(), SearchCriteria.Op.NULL);
volumeSB.and("state", volumeSB.entity().getState(), SearchCriteria.Op.NIN);
final SearchBuilder<VMInstanceVO> activeVmSB = _vmInstanceDao.createSearchBuilder();
activeVmSB.and("state", activeVmSB.entity().getState(), SearchCriteria.Op.IN);
volumeSB.join("activeVmSB", activeVmSB, volumeSB.entity().getInstanceId(), activeVmSB.entity().getId(), JoinBuilder.JoinType.INNER);
final SearchCriteria<VolumeVO> volumeSC = volumeSB.create();
volumeSC.setParameters("poolId", PrimaryDataStoreVO.getId());
volumeSC.setParameters("state", Volume.State.Expunging, Volume.State.Destroy);
volumeSC.setJoinParameters("activeVmSB", "state", State.Starting, State.Running, State.Stopping, State.Migrating);
final List<VolumeVO> volumes = _volsDao.search(volumeSC, null);
if (volumes.size() > 0) {
return true;
}
}
}
return false;
}
Aggregations