@Override public List<StoragePoolVO> findPoolsByTags( long dcId, long podId, Long clusterId, String[] tags, Boolean shared) { List<StoragePoolVO> storagePools = null; if (tags == null || tags.length == 0) { storagePools = listBy(dcId, podId, clusterId); } else { Map<String, String> details = tagsToDetails(tags); storagePools = findPoolsByDetails(dcId, podId, clusterId, details); } if (shared == null) { return storagePools; } else { List<StoragePoolVO> filteredStoragePools = new ArrayList<StoragePoolVO>(storagePools); for (StoragePoolVO pool : storagePools) { if (shared != pool.isShared()) { filteredStoragePools.remove(pool); } } return filteredStoragePools; } }
@Override @DB public StoragePoolVO persist(StoragePoolVO pool, Map<String, String> details) { Transaction txn = Transaction.currentTxn(); txn.start(); pool = super.persist(pool); if (details != null) { for (Map.Entry<String, String> detail : details.entrySet()) { StoragePoolDetailVO vo = new StoragePoolDetailVO(pool.getId(), detail.getKey(), detail.getValue()); _detailsDao.persist(vo); } } txn.commit(); return pool; }
@Override public String reserveVirtualMachine( VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) throws InsufficientCapacityException, ResourceUnavailableException { // call planner and get the deployDestination. // load vm instance and offerings and call virtualMachineManagerImpl // FIXME: profile should work on VirtualMachineEntity VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); VirtualMachineProfileImpl<VMInstanceVO> vmProfile = new VirtualMachineProfileImpl<VMInstanceVO>(vm); DataCenterDeployment plan = new DataCenterDeployment( vm.getDataCenterId(), vm.getPodIdToDeployIn(), null, null, null, null); if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) { plan = new DataCenterDeployment( planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId()); } List<VolumeVO> vols = _volsDao.findReadyRootVolumesByInstance(vm.getId()); if (!vols.isEmpty()) { VolumeVO vol = vols.get(0); StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId()); if (!pool.isInMaintenance()) { long rootVolDcId = pool.getDataCenterId(); Long rootVolPodId = pool.getPodId(); Long rootVolClusterId = pool.getClusterId(); if (planToDeploy != null && planToDeploy.getDataCenterId() != 0) { Long clusterIdSpecified = planToDeploy.getClusterId(); if (clusterIdSpecified != null && rootVolClusterId != null) { if (rootVolClusterId.longValue() != clusterIdSpecified.longValue()) { // cannot satisfy the plan passed in to the // planner throw new ResourceUnavailableException( "Root volume is ready in different cluster, Deployment plan provided cannot be satisfied, unable to create a deployment for " + vm, Cluster.class, clusterIdSpecified); } } plan = new DataCenterDeployment( planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, null); } else { plan = new DataCenterDeployment( rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, null); } } } DeploymentPlanner planner = ComponentContext.getComponent(plannerToUse); DeployDestination dest = null; if (planner.canHandle(vmProfile, plan, exclude)) { dest = planner.plan(vmProfile, plan, exclude); } if (dest != null) { // save destination with VMEntityVO VMReservationVO vmReservation = new VMReservationVO( vm.getId(), dest.getDataCenter().getId(), dest.getPod().getId(), dest.getCluster().getId(), dest.getHost().getId()); Map<Long, Long> volumeReservationMap = new HashMap<Long, Long>(); for (Volume vo : dest.getStorageForDisks().keySet()) { volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId()); } vmReservation.setVolumeReservation(volumeReservationMap); vmEntityVO.setVmReservation(vmReservation); _vmEntityDao.persist(vmEntityVO); return vmReservation.getUuid(); } else { throw new InsufficientServerCapacityException( "Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } }
@Override public void run() { try { SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria(); sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.Storage.toString()); ConcurrentHashMap<Long, StorageStats> storageStats = new ConcurrentHashMap<Long, StorageStats>(); List<HostVO> hosts = _hostDao.search(sc, null); for (HostVO host : hosts) { GetStorageStatsCommand command = new GetStorageStatsCommand(host.getGuid()); Answer answer = _agentMgr.easySend(host.getId(), command); if (answer != null && answer.getResult()) { storageStats.put(host.getId(), (StorageStats) answer); } } sc = _hostDao.createSearchCriteria(); sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage.toString()); hosts = _hostDao.search(sc, null); for (HostVO host : hosts) { GetStorageStatsCommand command = new GetStorageStatsCommand(host.getGuid()); Answer answer = _agentMgr.easySend(host.getId(), command); if (answer != null && answer.getResult()) { storageStats.put(host.getId(), (StorageStats) answer); } } _storageStats = storageStats; ConcurrentHashMap<Long, StorageStats> storagePoolStats = new ConcurrentHashMap<Long, StorageStats>(); List<StoragePoolVO> storagePools = _storagePoolDao.listAll(); for (StoragePoolVO pool : storagePools) { GetStorageStatsCommand command = new GetStorageStatsCommand(pool.getUuid(), pool.getPoolType(), pool.getPath()); Answer answer = _storageManager.sendToPool(pool, command); if (answer != null && answer.getResult()) { storagePoolStats.put(pool.getId(), (StorageStats) answer); } } _storagePoolStats = storagePoolStats; // a list to store the new capacity entries that will be committed once everything is // calculated List<CapacityVO> newCapacities = new ArrayList<CapacityVO>(); // Updating the storage entries and creating new ones if they dont exist. Transaction txn = Transaction.open(Transaction.CLOUD_DB); try { if (s_logger.isTraceEnabled()) { s_logger.trace("recalculating system storage capacity"); } txn.start(); for (Long hostId : storageStats.keySet()) { StorageStats stats = storageStats.get(hostId); short capacityType = -1; HostVO host = _hostDao.findById(hostId); host.setTotalSize(stats.getCapacityBytes()); _hostDao.update(host.getId(), host); SearchCriteria<CapacityVO> capacitySC = _capacityDao.createSearchCriteria(); capacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId); capacitySC.addAnd("dataCenterId", SearchCriteria.Op.EQ, host.getDataCenterId()); if (Host.Type.SecondaryStorage.equals(host.getType())) { capacityType = CapacityVO.CAPACITY_TYPE_SECONDARY_STORAGE; } else if (Host.Type.Storage.equals(host.getType())) { capacityType = CapacityVO.CAPACITY_TYPE_STORAGE; } if (-1 != capacityType) { capacitySC.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType); List<CapacityVO> capacities = _capacityDao.search(capacitySC, null); if (capacities.size() == 0) { // Create a new one CapacityVO capacity = new CapacityVO( host.getId(), host.getDataCenterId(), host.getPodId(), stats.getByteUsed(), stats.getCapacityBytes(), capacityType); _capacityDao.persist(capacity); } else { // Update if it already exists. CapacityVO capacity = capacities.get(0); capacity.setUsedCapacity(stats.getByteUsed()); capacity.setTotalCapacity(stats.getCapacityBytes()); _capacityDao.update(capacity.getId(), capacity); } } } // End of for txn.commit(); } catch (Exception ex) { txn.rollback(); s_logger.error("Unable to start transaction for storage capacity update"); } finally { txn.close(); } for (Long poolId : storagePoolStats.keySet()) { StorageStats stats = storagePoolStats.get(poolId); StoragePoolVO pool = _storagePoolDao.findById(poolId); if (pool == null) { continue; } pool.setCapacityBytes(stats.getCapacityBytes()); long available = stats.getCapacityBytes() - stats.getByteUsed(); if (available < 0) { available = 0; } pool.setAvailableBytes(available); _storagePoolDao.update(pool.getId(), pool); _storageManager.createCapacityEntry(pool, 0L); } } catch (Throwable t) { s_logger.error("Error trying to retrieve storage stats", t); } }
@Override public void updateCapacity(long id, long capacity) { StoragePoolVO pool = createForUpdate(id); pool.setCapacityBytes(capacity); update(id, pool); }
@Override public void updateAvailable(long id, long available) { StoragePoolVO pool = createForUpdate(id); pool.setAvailableBytes(available); update(id, pool); }
@Override @DB public void recalculateCapacity() { // FIXME: the right way to do this is to register a listener (see RouterStatsListener, // VMSyncListener) // for the vm sync state. The listener model has connects/disconnects to keep things in // sync much better // than this model right now, so when a VM is started, we update the amount allocated, // and when a VM // is stopped we updated the amount allocated, and when VM sync reports a changed state, // we update // the amount allocated. Hopefully it's limited to 3 entry points and will keep the // amount allocated // per host accurate. try { if (s_logger.isDebugEnabled()) { s_logger.debug("recalculating system capacity"); s_logger.debug("Executing cpu/ram capacity update"); } // Calculate CPU and RAM capacities // get all hosts...even if they are not in 'UP' state List<HostVO> hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing); for (HostVO host : hosts) { _capacityMgr.updateCapacityForHost(host); } if (s_logger.isDebugEnabled()) { s_logger.debug("Done executing cpu/ram capacity update"); s_logger.debug("Executing storage capacity update"); } // Calculate storage pool capacity List<StoragePoolVO> storagePools = _storagePoolDao.listAll(); for (StoragePoolVO pool : storagePools) { long disk = 0l; Pair<Long, Long> sizes = _volumeDao.getCountAndTotalByPool(pool.getId()); disk = sizes.second(); if (pool.isShared()) { _storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, disk); } else { _storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, disk); } } if (s_logger.isDebugEnabled()) { s_logger.debug("Done executing storage capacity update"); s_logger.debug("Executing capacity updates public ip and Vlans"); } List<DataCenterVO> datacenters = _dcDao.listAll(); for (DataCenterVO datacenter : datacenters) { long dcId = datacenter.getId(); // NOTE // What happens if we have multiple vlans? Dashboard currently shows stats // with no filter based on a vlan // ideal way would be to remove out the vlan param, and filter only on dcId // implementing the same // Calculate new Public IP capacity for Virtual Network if (datacenter.getNetworkType() == NetworkType.Advanced) { createOrUpdateIpCapacity(dcId, null, CapacityVO.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP); } // Calculate new Public IP capacity for Direct Attached Network createOrUpdateIpCapacity(dcId, null, CapacityVO.CAPACITY_TYPE_DIRECT_ATTACHED_PUBLIC_IP); if (datacenter.getNetworkType() == NetworkType.Advanced) { // Calculate VLAN's capacity createOrUpdateVlanCapacity(dcId); } } if (s_logger.isDebugEnabled()) { s_logger.debug("Done capacity updates for public ip and Vlans"); s_logger.debug("Executing capacity updates for private ip"); } // Calculate new Private IP capacity List<HostPodVO> pods = _podDao.listAll(); for (HostPodVO pod : pods) { long podId = pod.getId(); long dcId = pod.getDataCenterId(); createOrUpdateIpCapacity(dcId, podId, CapacityVO.CAPACITY_TYPE_PRIVATE_IP); } if (s_logger.isDebugEnabled()) { s_logger.debug("Done executing capacity updates for private ip"); s_logger.debug("Done recalculating system capacity"); } } catch (Throwable t) { s_logger.error("Caught exception in recalculating capacity", t); } }