diff --git a/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java b/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java index 7d1e2389070..d923694a854 100644 --- a/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java +++ b/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java @@ -28,6 +28,7 @@ public class StoragePoolInfo { StoragePoolType poolType; long capacityBytes; long availableBytes; + String name; Map details; protected StoragePoolInfo() { @@ -67,14 +68,34 @@ public class StoragePoolInfo { return host; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setLocalPath(String localPath) { + this.localPath = localPath; + } + public String getLocalPath() { return localPath; } + public void setHostPath(String hostPath) { + this.hostPath = hostPath; + } + public String getHostPath() { return hostPath; } + public void setPoolType(StoragePoolType poolType) { + this.poolType = poolType; + } + public StoragePoolType getPoolType() { return poolType; } diff --git a/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolAnswer.java b/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolAnswer.java index a5f7c53214b..f7a7e1ced06 100644 --- a/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolAnswer.java @@ -19,6 +19,7 @@ package com.cloud.agent.api; +import java.util.List; import java.util.Map; import com.cloud.storage.template.TemplateProp; @@ -28,6 +29,7 @@ public class ModifyStoragePoolAnswer extends Answer { private Map templateInfo; private String localDatastoreName; private String poolType; + private List datastoreClusterChildren; public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map tInfo) { super(cmd); @@ -63,7 +65,6 @@ public class ModifyStoragePoolAnswer extends Answer { return localDatastoreName; } - public String getPoolType() { return poolType; } @@ -71,4 +72,12 @@ public class ModifyStoragePoolAnswer extends Answer { public void setPoolType(String poolType) { this.poolType = poolType; } + + public List getDatastoreClusterChildren() { + return datastoreClusterChildren; + } + + public void setDatastoreClusterChildren(List datastoreClusterChildren) { + this.datastoreClusterChildren = datastoreClusterChildren; + } } diff --git a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java index 3ba45191147..dac6514cc84 100644 --- a/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java +++ b/engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java @@ -22,12 +22,15 @@ import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.ModifyStoragePoolAnswer; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.StoragePoolInfo; import com.cloud.alert.AlertManager; import com.cloud.exception.StorageConflictException; import com.cloud.storage.DataStoreRole; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.dao.StoragePoolTagsDao; import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; @@ -39,7 +42,9 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import javax.inject.Inject; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class DefaultHostListener implements HypervisorHostListener { private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); @@ -55,6 +60,8 @@ public class DefaultHostListener implements HypervisorHostListener { PrimaryDataStoreDao primaryStoreDao; @Inject StoragePoolDetailsDao storagePoolDetailsDao; + @Inject + StoragePoolTagsDao storagePoolTagsDao; @Override public boolean hostAdded(long hostId) { @@ -92,7 +99,52 @@ public class DefaultHostListener implements HypervisorHostListener { } } } + StoragePoolVO poolVO = this.primaryStoreDao.findById(poolId); + updateStoragePoolHostVOAndDetails(poolVO, hostId, mspAnswer); + for (ModifyStoragePoolAnswer childDataStoreAnswer : ((ModifyStoragePoolAnswer) answer).getDatastoreClusterChildren()) { + StoragePoolInfo childStoragePoolInfo = childDataStoreAnswer.getPoolInfo(); + StoragePoolVO dataStoreVO = primaryStoreDao.findPoolByUUID(childStoragePoolInfo.getUuid()); + if (dataStoreVO != null) { + continue; + } + dataStoreVO = new StoragePoolVO(); + dataStoreVO.setStorageProviderName(poolVO.getStorageProviderName()); + dataStoreVO.setHostAddress(childStoragePoolInfo.getHost()); + dataStoreVO.setPoolType(poolVO.getPoolType()); + dataStoreVO.setPath(childStoragePoolInfo.getHostPath()); + dataStoreVO.setPort(poolVO.getPort()); + dataStoreVO.setName(childStoragePoolInfo.getName()); + dataStoreVO.setUuid(childStoragePoolInfo.getUuid()); + dataStoreVO.setDataCenterId(poolVO.getDataCenterId()); + dataStoreVO.setPodId(poolVO.getPodId()); + dataStoreVO.setClusterId(poolVO.getClusterId()); + dataStoreVO.setStatus(StoragePoolStatus.Up); + dataStoreVO.setUserInfo(poolVO.getUserInfo()); + dataStoreVO.setManaged(poolVO.isManaged()); + dataStoreVO.setCapacityIops(poolVO.getCapacityIops()); + dataStoreVO.setCapacityBytes(childDataStoreAnswer.getPoolInfo().getCapacityBytes()); + dataStoreVO.setUsedBytes(childDataStoreAnswer.getPoolInfo().getCapacityBytes() - childDataStoreAnswer.getPoolInfo().getAvailableBytes()); + dataStoreVO.setHypervisor(poolVO.getHypervisor()); + dataStoreVO.setScope(poolVO.getScope()); + + Map details = new HashMap<>(); + if(StringUtils.isNotEmpty(childDataStoreAnswer.getPoolType())) { + details.put("pool_type", childDataStoreAnswer.getPoolType()); + } + + List storageTags = storagePoolTagsDao.getStoragePoolTags(poolId); + storageTags.add("DataStoreCluster-" + poolVO.getUuid()); + primaryStoreDao.persist(dataStoreVO, details, storageTags); + + updateStoragePoolHostVOAndDetails(dataStoreVO, hostId, childDataStoreAnswer); + } + + s_logger.info("Connection established between storage pool " + pool + " and host " + hostId); + return true; + } + + private void updateStoragePoolHostVOAndDetails(StoragePool pool, long hostId, ModifyStoragePoolAnswer mspAnswer) { StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(pool.getId(), hostId); if (poolHost == null) { poolHost = new StoragePoolHostVO(pool.getId(), hostId, mspAnswer.getPoolInfo().getLocalPath().replaceAll("//", "/")); @@ -101,20 +153,17 @@ public class DefaultHostListener implements HypervisorHostListener { poolHost.setLocalPath(mspAnswer.getPoolInfo().getLocalPath().replaceAll("//", "/")); } - StoragePoolVO poolVO = this.primaryStoreDao.findById(poolId); + StoragePoolVO poolVO = this.primaryStoreDao.findById(pool.getId()); poolVO.setUsedBytes(mspAnswer.getPoolInfo().getCapacityBytes() - mspAnswer.getPoolInfo().getAvailableBytes()); poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes()); if(StringUtils.isNotEmpty(mspAnswer.getPoolType())) { - StoragePoolDetailVO poolType = storagePoolDetailsDao.findDetail(poolId, "pool_type"); + StoragePoolDetailVO poolType = storagePoolDetailsDao.findDetail(pool.getId(), "pool_type"); if (poolType == null) { - StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(poolId, "pool_type", mspAnswer.getPoolType(), false); + StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(pool.getId(), "pool_type", mspAnswer.getPoolType(), false); storagePoolDetailsDao.persist(storagePoolDetailVO); } } primaryStoreDao.update(pool.getId(), poolVO); - - s_logger.info("Connection established between storage pool " + pool + " and host " + hostId); - return true; } @Override diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index ffeebc7c5f3..0c5fc48ded1 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -177,6 +177,7 @@ import com.cloud.hypervisor.vmware.mo.HostStorageSystemMO; import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper; import com.cloud.hypervisor.vmware.mo.NetworkDetails; import com.cloud.hypervisor.vmware.mo.TaskMO; +import com.cloud.hypervisor.vmware.mo.StoragepodMO; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.hypervisor.vmware.mo.VirtualMachineDiskInfoBuilder; import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; @@ -4918,11 +4919,43 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa long capacity = 0; long available = 0; + List childDatastoresModifyStoragePoolAnswers = new ArrayList<>(); if (pool.getType() == StoragePoolType.DatastoreCluster) { - StoragePodSummary summary = dsMo.getDatastoreClusterSummary(); - capacity = summary.getCapacity(); - available = summary.getFreeSpace(); + StoragepodMO datastoreClusterMo = new StoragepodMO(getServiceContext(), morDatastore); + StoragePodSummary dsClusterSummary = datastoreClusterMo.getDatastoreClusterSummary(); + capacity = dsClusterSummary.getCapacity(); + available = dsClusterSummary.getFreeSpace(); + + List childDatastoreMors = datastoreClusterMo.getDatastoresInDatastoreCluster(); + for (ManagedObjectReference childDsMor : childDatastoreMors) { + DatastoreMO childDsMo = new DatastoreMO(getServiceContext(), childDsMor); + + Map tInfo = new HashMap<>(); + DatastoreSummary summary = childDsMo.getDatastoreSummary();; + ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, summary.getCapacity(), summary.getFreeSpace(), tInfo); + StoragePoolInfo poolInfo = answer.getPoolInfo(); + poolInfo.setName(summary.getName()); + String datastoreClusterPath = pool.getPath(); + int pathstartPosition = datastoreClusterPath.lastIndexOf('/'); + String datacenterName = datastoreClusterPath.substring(0, pathstartPosition+1); + String childPath = datacenterName + summary.getName(); + poolInfo.setHostPath(childPath); + String uuid = UUID.nameUUIDFromBytes(((pool.getHost() + childPath)).getBytes()).toString(); + poolInfo.setUuid(uuid); + poolInfo.setLocalPath(cmd.LOCAL_PATH_PREFIX + File.separator + uuid); + + answer.setPoolInfo(poolInfo); + answer.setPoolType(summary.getType()); + answer.setLocalDatastoreName(morDatastore.getValue()); + + childDsMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, uuid); + HypervisorHostHelper.createBaseFolderInDatastore(childDsMo, hyperHost); + + childDatastoresModifyStoragePoolAnswers.add(answer); + } } else { + HypervisorHostHelper.createBaseFolderInDatastore(dsMo, hyperHost); + DatastoreSummary summary = dsMo.getDatastoreSummary(); capacity = summary.getCapacity(); available = summary.getFreeSpace(); @@ -4930,6 +4963,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Map tInfo = new HashMap<>(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); + answer.setDatastoreClusterChildren(childDatastoresModifyStoragePoolAnswers); if (cmd.getAdd() && (pool.getType() == StoragePoolType.VMFS || pool.getType() == StoragePoolType.PreSetup) && pool.getType() != StoragePoolType.DatastoreCluster) { answer.setPoolType(dsMo.getDatastoreType()); @@ -5312,14 +5346,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getStorageId()); if (morDs != null) { - DatastoreMO datastoreMo = new DatastoreMO(context, morDs); long capacity = 0; long free = 0; if (cmd.getPooltype() == StoragePoolType.DatastoreCluster) { - StoragePodSummary summary = datastoreMo.getDatastoreClusterSummary(); + StoragepodMO datastoreClusterMo = new StoragepodMO(getServiceContext(), morDs); + StoragePodSummary summary = datastoreClusterMo.getDatastoreClusterSummary(); capacity = summary.getCapacity(); free = summary.getFreeSpace(); } else { + DatastoreMO datastoreMo = new DatastoreMO(context, morDs); DatastoreSummary summary = datastoreMo.getDatastoreSummary(); capacity = summary.getCapacity(); free = summary.getFreeSpace(); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java index 133a412d750..b5955a6d709 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/DatastoreMO.java @@ -33,7 +33,6 @@ import com.vmware.vim25.ObjectSpec; import com.vmware.vim25.PropertyFilterSpec; import com.vmware.vim25.PropertySpec; import com.vmware.vim25.SelectionSpec; -import com.vmware.vim25.StoragePodSummary; import com.vmware.vim25.TraversalSpec; import org.apache.log4j.Logger; @@ -68,10 +67,6 @@ public class DatastoreMO extends BaseMO { return (DatastoreSummary)_context.getVimClient().getDynamicProperty(_mor, "summary"); } - public StoragePodSummary getDatastoreClusterSummary() throws Exception { - return (StoragePodSummary)_context.getVimClient().getDynamicProperty(_mor, "summary"); - } - public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception { return new HostDatastoreBrowserMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "browser")); } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java index 2483ced5cc5..6554440a3e5 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -28,7 +28,6 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import com.cloud.storage.Storage; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.AlreadyExistsFaultMsg; @@ -890,8 +889,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { } } - if (dsMo != null) { - HypervisorHostHelper.createBaseFolder(dsMo, this, "StoragePod".equals(morDatastore.getType()) ? Storage.StoragePoolType.DatastoreCluster: null); + if (dsMo != null && !"StoragePod".equals(morDatastore.getType())) { + HypervisorHostHelper.createBaseFolderInDatastore(dsMo, this); } if (s_logger.isTraceEnabled()) diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 30ee117fe7b..7dcc5c77f5d 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -2088,7 +2088,8 @@ public class HypervisorHostHelper { public static void createBaseFolder(DatastoreMO dsMo, VmwareHypervisorHost hyperHost, StoragePoolType poolType) throws Exception { if (poolType != null && poolType == StoragePoolType.DatastoreCluster) { - List datastoresInCluster = hyperHost.getContext().getVimClient().getDynamicProperty(dsMo.getMor(), "childEntity"); + StoragepodMO storagepodMO = new StoragepodMO(hyperHost.getContext(), dsMo.getMor()); + List datastoresInCluster = storagepodMO.getDatastoresInDatastoreCluster(); for (ManagedObjectReference datastore : datastoresInCluster) { DatastoreMO childDsMo = new DatastoreMO(hyperHost.getContext(), datastore); createBaseFolderInDatastore(childDsMo, hyperHost); @@ -2098,7 +2099,7 @@ public class HypervisorHostHelper { } } - private static void createBaseFolderInDatastore(DatastoreMO dsMo, VmwareHypervisorHost hyperHost) throws Exception { + public static void createBaseFolderInDatastore(DatastoreMO dsMo, VmwareHypervisorHost hyperHost) throws Exception { String dsPath = String.format("[%s]", dsMo.getName()); String folderPath = String.format("[%s] %s", dsMo.getName(), VSPHERE_DATASTORE_BASE_FOLDER); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/StoragepodMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/StoragepodMO.java new file mode 100644 index 00000000000..afa3a022126 --- /dev/null +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/StoragepodMO.java @@ -0,0 +1,48 @@ +// 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.hypervisor.vmware.mo; + +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.StoragePodSummary; +import org.apache.log4j.Logger; + +import java.util.List; + +public class StoragepodMO extends BaseMO { + + private static final Logger LOGGER = Logger.getLogger(StoragepodMO.class); + + public StoragepodMO(VmwareContext context, ManagedObjectReference mor) { + super(context, mor); + } + + public StoragepodMO(VmwareContext context, String morType, String morValue) { + super(context, morType, morValue); + } + + public StoragePodSummary getDatastoreClusterSummary() throws Exception { + return (StoragePodSummary)_context.getVimClient().getDynamicProperty(_mor, "summary"); + } + + public List getDatastoresInDatastoreCluster() throws Exception { + List datastoresInCluster = _context.getVimClient().getDynamicProperty(_mor, "childEntity"); + return datastoresInCluster; + } + +}