| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| package com.cloud.storage; |
| |
| import java.util.List; |
| |
| import javax.inject.Inject; |
| |
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; |
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; |
| import org.apache.commons.collections.CollectionUtils; |
| |
| import com.cloud.dc.ClusterVO; |
| import com.cloud.dc.dao.ClusterDao; |
| import com.cloud.host.HostVO; |
| import com.cloud.host.dao.HostDao; |
| import com.cloud.hypervisor.Hypervisor; |
| import com.cloud.storage.dao.VolumeDao; |
| import com.cloud.vm.VMInstanceVO; |
| import com.cloud.vm.dao.VMInstanceDao; |
| |
| import org.apache.logging.log4j.Logger; |
| |
| public class StorageUtil { |
| @Inject private ClusterDao clusterDao; |
| @Inject private HostDao hostDao; |
| @Inject private PrimaryDataStoreDao storagePoolDao; |
| @Inject private VMInstanceDao vmInstanceDao; |
| @Inject private VolumeDao volumeDao; |
| |
| public static void traceLogStoragePools(List<StoragePool> poolList, Logger logger, String initialMessage) { |
| if (logger.isTraceEnabled()) { |
| StringBuilder pooltable = new StringBuilder(); |
| pooltable.append(initialMessage); |
| int i = 1; |
| for (StoragePool pool : poolList) { |
| pooltable.append("\nno ").append(i).append(": ").append(pool.getName()).append("/").append(pool.getUuid()); |
| } |
| logger.trace(pooltable.toString()); |
| } |
| } |
| |
| private Long getClusterId(Long hostId) { |
| if (hostId == null) { |
| return null; |
| } |
| |
| HostVO hostVO = hostDao.findById(hostId); |
| |
| if (hostVO == null) { |
| return null; |
| } |
| |
| return hostVO.getClusterId(); |
| } |
| |
| /** |
| * This method relates to managed storage only. CloudStack currently supports managed storage with XenServer, vSphere, and KVM. |
| * With managed storage on XenServer and vSphere, CloudStack needs to use an iSCSI SR (XenServer) or datastore (vSphere) per CloudStack |
| * volume. Since XenServer and vSphere are limited to the hundreds with regards to how many SRs or datastores can be leveraged per |
| * compute cluster, this method is used to check a Global Setting (that specifies the maximum number of SRs or datastores per compute cluster) |
| * against what is being requested. KVM does not apply here because it does not suffer from the same scalability limits as XenServer and |
| * vSphere do. With XenServer and vSphere, each host is configured to see all the SRs/datastores of the cluster. With KVM, each host typically |
| * is only configured to see the managed volumes of the VMs that are currently running on that host. |
| * |
| * If the clusterId is passed in, we use it. Otherwise, we use the hostId. If neither leads to a cluster, we just return true. |
| */ |
| public boolean managedStoragePoolCanScale(StoragePool storagePool, Long clusterId, Long hostId) { |
| if (clusterId == null) { |
| clusterId = getClusterId(hostId); |
| |
| if (clusterId == null) { |
| return true; |
| } |
| } |
| |
| ClusterVO clusterVO = clusterDao.findById(clusterId); |
| |
| if (clusterVO == null) { |
| return true; |
| } |
| |
| Hypervisor.HypervisorType hypervisorType = clusterVO.getHypervisorType(); |
| |
| if (hypervisorType == null) { |
| return true; |
| } |
| |
| if (Hypervisor.HypervisorType.XenServer.equals(hypervisorType) || Hypervisor.HypervisorType.VMware.equals(hypervisorType)) { |
| int maxValue = StorageManager.MaxNumberOfManagedClusteredFileSystems.valueIn(clusterId); |
| |
| return getNumberOfManagedClusteredFileSystemsInComputeCluster(storagePool.getDataCenterId(), clusterId) < maxValue; |
| } |
| |
| return true; |
| } |
| |
| private int getNumberOfManagedClusteredFileSystemsInComputeCluster(long zoneId, long clusterId) { |
| int numberOfManagedClusteredFileSystemsInComputeCluster = 0; |
| |
| List<VolumeVO> volumes = volumeDao.findByDc(zoneId); |
| |
| if (CollectionUtils.isEmpty(volumes)) { |
| return numberOfManagedClusteredFileSystemsInComputeCluster; |
| } |
| |
| for (VolumeVO volume : volumes) { |
| Long instanceId = volume.getInstanceId(); |
| |
| if (instanceId == null) { |
| continue; |
| } |
| |
| VMInstanceVO vmInstanceVO = vmInstanceDao.findById(instanceId); |
| |
| if (vmInstanceVO == null) { |
| continue; |
| } |
| |
| Long vmHostId = vmInstanceVO.getHostId(); |
| |
| if (vmHostId == null) { |
| vmHostId = vmInstanceVO.getLastHostId(); |
| } |
| |
| if (vmHostId == null) { |
| continue; |
| } |
| |
| HostVO vmHostVO = hostDao.findById(vmHostId); |
| |
| if (vmHostVO == null) { |
| continue; |
| } |
| |
| Long vmHostClusterId = vmHostVO.getClusterId(); |
| |
| if (vmHostClusterId != null && vmHostClusterId == clusterId) { |
| StoragePoolVO storagePoolVO = storagePoolDao.findById(volume.getPoolId()); |
| |
| if (storagePoolVO != null && storagePoolVO.isManaged()) { |
| numberOfManagedClusteredFileSystemsInComputeCluster++; |
| } |
| } |
| } |
| |
| return numberOfManagedClusteredFileSystemsInComputeCluster; |
| } |
| } |