This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch 4.15
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.15 by this push:
     new 32e3bbd  VMware Datastore Cluster primary storage pool synchronisation 
(#4871)
32e3bbd is described below

commit 32e3bbdcc57874bc4914fb50e9c66adea7668f06
Author: Harikrishna <[email protected]>
AuthorDate: Fri May 7 16:30:54 2021 +0530

    VMware Datastore Cluster primary storage pool synchronisation (#4871)
    
    Datastore cluster as a primary storage support is already there. But if any 
changes at vCenter to datastore cluster like addition/removal of datastore is 
not synchronised with CloudStack directly. It needs removal of primary storage 
from CloudStack and add it again to CloudStack.
    
    Here synchronisation of datastore cluster is fixed without need to remove 
or add the datastore cluster.
    1. A new API is introduced syncStoragePool which takes datastore cluster 
storage pool UUID as the parameter. This API checks if there any changes in the 
datastore cluster and updates management server accordingly.
    2. During synchronisation if a new child datastore is found in datastore 
cluster, then management server will create a new child storage pool in 
database under the datastore cluster. If the new child storage pool is already 
added as an individual storage pool then the existing storage pool entry will 
be converted to child storage pool (instead of creating a new storage pool 
entry)
    3. During synchronisaton if the existing child datastore in CloudStack is 
found to be removed on vCenter then management server removes that child 
datastore from datastore cluster and makes it an individual storage pool.
    The above behaviour is on par with the vCenter behaviour when adding and 
removing child datastore.
---
 api/src/main/java/com/cloud/event/EventTypes.java  |   1 +
 .../java/com/cloud/storage/StorageService.java     |   3 +
 .../command/admin/storage/SyncStoragePoolCmd.java  |  97 ++++++++
 .../cloud/storage/resource/StorageProcessor.java   |   5 +-
 .../StorageSubsystemCommandHandlerBase.java        |   5 +-
 .../storage/command/SyncVolumePathAnswer.java      |  49 ++++
 .../storage/command/SyncVolumePathCommand.java     |  49 ++++
 .../java/com/cloud/storage/StorageManager.java     |   3 +
 .../com/cloud/storage/dao/StoragePoolHostDao.java  |   2 +
 .../cloud/storage/dao/StoragePoolHostDaoImpl.java  |  31 ++-
 .../storage/datastore/db/PrimaryDataStoreDao.java  |   2 +
 .../datastore/db/PrimaryDataStoreDaoImpl.java      |   8 +
 .../datastore/provider/DefaultHostListener.java    |  46 +---
 .../kvm/storage/KVMStorageProcessor.java           |   9 +-
 .../ovm3/resources/Ovm3StorageProcessor.java       |  11 +-
 .../cloud/resource/SimulatorStorageProcessor.java  |   8 +-
 .../hypervisor/vmware/resource/VmwareResource.java |   6 +-
 .../storage/resource/VmwareStorageProcessor.java   |  81 ++++++-
 .../resource/XenServerStorageProcessor.java        |   9 +-
 .../resource/Xenserver625StorageProcessor.java     |   9 +-
 .../com/cloud/server/ManagementServerImpl.java     |   2 +
 .../java/com/cloud/storage/StorageManagerImpl.java | 267 ++++++++++++++++++++-
 .../cloud/storage/StoragePoolAutomationImpl.java   |  11 +
 tools/apidoc/gen_toc.py                            |   1 +
 24 files changed, 658 insertions(+), 57 deletions(-)

diff --git a/api/src/main/java/com/cloud/event/EventTypes.java 
b/api/src/main/java/com/cloud/event/EventTypes.java
index ebe7590..025d9e9 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -374,6 +374,7 @@ public class EventTypes {
     // Primary storage pool
     public static final String EVENT_ENABLE_PRIMARY_STORAGE = "ENABLE.PS";
     public static final String EVENT_DISABLE_PRIMARY_STORAGE = "DISABLE.PS";
+    public static final String EVENT_SYNC_STORAGE_POOL = "SYNC.STORAGE.POOL";
 
     // VPN
     public static final String EVENT_REMOTE_ACCESS_VPN_CREATE = 
"VPN.REMOTE.ACCESS.CREATE";
diff --git a/api/src/main/java/com/cloud/storage/StorageService.java 
b/api/src/main/java/com/cloud/storage/StorageService.java
index 207fc8f..4b18739 100644
--- a/api/src/main/java/com/cloud/storage/StorageService.java
+++ b/api/src/main/java/com/cloud/storage/StorageService.java
@@ -27,6 +27,7 @@ import 
org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
 import 
org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd;
 
 import com.cloud.exception.DiscoveryException;
 import com.cloud.exception.InsufficientCapacityException;
@@ -104,4 +105,6 @@ public interface StorageService {
 
     ImageStore updateImageStoreStatus(Long id, Boolean readonly);
 
+    StoragePool syncStoragePool(SyncStoragePoolCmd cmd);
+
 }
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java
 
b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java
new file mode 100644
index 0000000..9761e33
--- /dev/null
+++ 
b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java
@@ -0,0 +1,97 @@
+// 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 org.apache.cloudstack.api.command.admin.storage;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.storage.StoragePool;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.context.CallContext;
+
+import java.util.logging.Logger;
+
+@APICommand(name = SyncStoragePoolCmd.APINAME,
+        description = "Sync storage pool with management server (currently 
supported for Datastore Cluster in VMware and syncs the datastores in it)",
+        responseObject = StoragePoolResponse.class,
+        requestHasSensitiveInfo = false,
+        responseHasSensitiveInfo = false,
+        since = "4.15.1",
+        authorized = {RoleType.Admin}
+        )
+public class SyncStoragePoolCmd extends BaseAsyncCmd {
+
+    public static final String APINAME = "syncStoragePool";
+    public static final Logger LOGGER = 
Logger.getLogger(SyncStoragePoolCmd.class.getName());
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = 
StoragePoolResponse.class, required = true, description = "Storage pool id")
+    private Long poolId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getPoolId() {
+        return poolId;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SYNC_STORAGE_POOL;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Attempting to synchronise storage pool with management server";
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException, 
InsufficientCapacityException, ServerApiException, 
ConcurrentOperationException, ResourceAllocationException, 
NetworkRuleConflictException {
+        StoragePool result = _storageService.syncStoragePool(this);
+        if (result != null) {
+            StoragePoolResponse response = 
_responseGenerator.createStoragePoolResponse(result);
+            response.setResponseName("storagepool");
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed 
to synchronise storage pool");
+        }
+    }
+
+    @Override
+    public String getCommandName() {
+        return APINAME.toLowerCase() + BaseAsyncCmd.RESPONSE_SUFFIX;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return CallContext.current().getCallingAccountId();
+    }
+}
diff --git 
a/core/src/main/java/com/cloud/storage/resource/StorageProcessor.java 
b/core/src/main/java/com/cloud/storage/resource/StorageProcessor.java
index d86a1a6..b7cd5b8 100644
--- a/core/src/main/java/com/cloud/storage/resource/StorageProcessor.java
+++ b/core/src/main/java/com/cloud/storage/resource/StorageProcessor.java
@@ -30,6 +30,7 @@ import org.apache.cloudstack.storage.command.ForgetObjectCmd;
 import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 
 import com.cloud.agent.api.Answer;
 
@@ -81,5 +82,7 @@ public interface StorageProcessor {
 
     Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd);
 
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd);
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd);
+
+    public Answer syncVolumePath(SyncVolumePathCommand cmd);
 }
diff --git 
a/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
 
b/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
index 910eb3d..22281e6 100644
--- 
a/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
+++ 
b/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
@@ -34,6 +34,7 @@ import 
org.apache.cloudstack.storage.command.IntroduceObjectCmd;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
 import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
@@ -73,7 +74,9 @@ public class StorageSubsystemCommandHandlerBase implements 
StorageSubsystemComma
         } else if (command instanceof DirectDownloadCommand) {
             return 
processor.handleDownloadTemplateToPrimaryStorage((DirectDownloadCommand) 
command);
         } else if (command instanceof 
CheckDataStoreStoragePolicyComplainceCommand) {
-            return 
processor.CheckDataStoreStoragePolicyComplaince((CheckDataStoreStoragePolicyComplainceCommand)
 command);
+            return 
processor.checkDataStoreStoragePolicyCompliance((CheckDataStoreStoragePolicyComplainceCommand)
 command);
+        } else if (command instanceof SyncVolumePathCommand) {
+            return processor.syncVolumePath((SyncVolumePathCommand) command);
         }
 
         return new Answer((Command)command, false, "not implemented yet");
diff --git 
a/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathAnswer.java
 
b/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathAnswer.java
new file mode 100644
index 0000000..7560f7d
--- /dev/null
+++ 
b/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathAnswer.java
@@ -0,0 +1,49 @@
+//
+// 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 org.apache.cloudstack.storage.command;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DiskTO;
+
+public class SyncVolumePathAnswer extends Answer {
+    private DiskTO disk;
+
+    public SyncVolumePathAnswer() {
+        super(null);
+    }
+
+    public SyncVolumePathAnswer(DiskTO disk) {
+        super(null);
+        setDisk(disk);
+    }
+
+    public SyncVolumePathAnswer(String errMsg) {
+        super(null, false, errMsg);
+    }
+
+    public DiskTO getDisk() {
+        return disk;
+    }
+
+    public void setDisk(DiskTO disk) {
+        this.disk = disk;
+    }
+
+}
diff --git 
a/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathCommand.java
 
b/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathCommand.java
new file mode 100644
index 0000000..e655da4
--- /dev/null
+++ 
b/core/src/main/java/org/apache/cloudstack/storage/command/SyncVolumePathCommand.java
@@ -0,0 +1,49 @@
+//
+// 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 org.apache.cloudstack.storage.command;
+
+import com.cloud.agent.api.to.DiskTO;
+
+public class SyncVolumePathCommand extends StorageSubSystemCommand {
+
+    private DiskTO disk;
+
+    public SyncVolumePathCommand(final DiskTO disk) {
+        super();
+        this.disk = disk;
+    }
+
+    public DiskTO getDisk() {
+        return disk;
+    }
+
+    public void setDisk(final DiskTO disk) {
+        this.disk = disk;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    @Override
+    public void setExecuteInSequence(boolean inSeq) {
+
+    }
+}
diff --git 
a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java 
b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
index 7455f22..8cf1143 100644
--- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
@@ -19,6 +19,7 @@ package com.cloud.storage;
 import java.math.BigDecimal;
 import java.util.List;
 
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import 
org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
 import org.apache.cloudstack.framework.config.ConfigKey;
@@ -240,4 +241,6 @@ public interface StorageManager extends StorageService {
 
     boolean isStoragePoolDatastoreClusterParent(StoragePool pool);
 
+    void syncDatastoreClusterStoragePool(long datastoreClusterPoolId, 
List<ModifyStoragePoolAnswer> childDatastoreAnswerList, long hostId);
+
 }
diff --git 
a/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDao.java 
b/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDao.java
index 8dd10a7..b099a6d 100644
--- a/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDao.java
+++ b/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDao.java
@@ -32,6 +32,8 @@ public interface StoragePoolHostDao extends 
GenericDao<StoragePoolHostVO, Long>
 
     List<StoragePoolHostVO> listByHostStatus(long poolId, Status hostStatus);
 
+    List<Long> findHostsConnectedToPools(List<Long> poolIds);
+
     List<Pair<Long, Integer>> getDatacenterStoragePoolHostInfo(long dcId, 
boolean sharedOnly);
 
     public void deletePrimaryRecordsForHost(long hostId);
diff --git 
a/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDaoImpl.java 
b/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDaoImpl.java
index 2b7b0f7..9c5ddeb 100644
--- 
a/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDaoImpl.java
+++ 
b/engine/schema/src/main/java/com/cloud/storage/dao/StoragePoolHostDaoImpl.java
@@ -21,7 +21,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
-
+import java.util.stream.Collectors;
 
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
@@ -44,6 +44,8 @@ public class StoragePoolHostDaoImpl extends 
GenericDaoBase<StoragePoolHostVO, Lo
 
     protected static final String HOST_FOR_POOL_SEARCH = "SELECT * FROM 
storage_pool_host_ref ph,  host h where  ph.host_id = h.id and ph.pool_id=? and 
h.status=? ";
 
+    protected static final String HOSTS_FOR_POOLS_SEARCH = "SELECT 
DISTINCT(ph.host_id) FROM storage_pool_host_ref ph, host h WHERE ph.host_id = 
h.id AND h.status = 'Up' AND resource_state = 'Enabled' AND ph.pool_id IN (?)";
+
     protected static final String STORAGE_POOL_HOST_INFO = "SELECT 
p.data_center_id,  count(ph.host_id) " + " FROM storage_pool p, 
storage_pool_host_ref ph "
         + " WHERE p.id = ph.pool_id AND p.data_center_id = ? " + " GROUP by 
p.data_center_id";
 
@@ -122,6 +124,33 @@ public class StoragePoolHostDaoImpl extends 
GenericDaoBase<StoragePoolHostVO, Lo
     }
 
     @Override
+    public List<Long> findHostsConnectedToPools(List<Long> poolIds) {
+        List<Long> hosts = new ArrayList<Long>();
+        if (poolIds == null || poolIds.isEmpty()) {
+            return hosts;
+        }
+
+        String poolIdsInStr = poolIds.stream().map(poolId -> 
String.valueOf(poolId)).collect(Collectors.joining(",", "(", ")"));
+        String sql = HOSTS_FOR_POOLS_SEARCH.replace("(?)", poolIdsInStr);
+
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+        try(PreparedStatement pstmt = txn.prepareStatement(sql);) {
+            try(ResultSet rs = pstmt.executeQuery();) {
+                while (rs.next()) {
+                    long hostId = rs.getLong(1); // host_id column
+                    hosts.add(hostId);
+                }
+            } catch (SQLException e) {
+                s_logger.warn(String.format("Unable to retrieve hosts from 
pools [%s] due to [%s].", poolIdsInStr, e.getMessage()));
+            }
+        } catch (Exception e) {
+            s_logger.warn(String.format("Unable to retrieve hosts from pools 
[%s] due to [%s].", poolIdsInStr, e.getMessage()));
+        }
+
+        return hosts;
+    }
+
+    @Override
     public List<Pair<Long, Integer>> getDatacenterStoragePoolHostInfo(long 
dcId, boolean sharedOnly) {
         ArrayList<Pair<Long, Integer>> l = new ArrayList<Pair<Long, 
Integer>>();
         String sql = sharedOnly ? SHARED_STORAGE_POOL_HOST_INFO : 
STORAGE_POOL_HOST_INFO;
diff --git 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
index 3375c6f..f56fdb8 100644
--- 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
+++ 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
@@ -130,4 +130,6 @@ public interface PrimaryDataStoreDao extends 
GenericDao<StoragePoolVO, Long> {
 
     Integer countAll();
 
+    List<StoragePoolVO> findPoolsByStorageType(String storageType);
+
 }
diff --git 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
index dfe1a69..6b07ef9 100644
--- 
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
+++ 
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
@@ -93,6 +93,7 @@ public class PrimaryDataStoreDaoImpl extends 
GenericDaoBase<StoragePoolVO, Long>
         AllFieldSearch.and("podId", AllFieldSearch.entity().getPodId(), Op.EQ);
         AllFieldSearch.and("clusterId", 
AllFieldSearch.entity().getClusterId(), Op.EQ);
         AllFieldSearch.and("storage_provider_name", 
AllFieldSearch.entity().getStorageProviderName(), Op.EQ);
+        AllFieldSearch.and("poolType", AllFieldSearch.entity().getPoolType(), 
Op.EQ);
         AllFieldSearch.done();
 
         DcPodSearch = createSearchBuilder();
@@ -581,4 +582,11 @@ public class PrimaryDataStoreDaoImpl extends 
GenericDaoBase<StoragePoolVO, Long>
         sc.setParameters("status", StoragePoolStatus.Up);
         return listBy(sc);
     }
+
+    @Override
+    public List<StoragePoolVO> findPoolsByStorageType(String storageType) {
+        SearchCriteria<StoragePoolVO> sc = AllFieldSearch.create();
+        sc.setParameters("poolType", storageType);
+        return listBy(sc);
+    }
 }
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 cb4ff74..eb2262f 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,16 +22,14 @@ 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.Storage;
 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.storage.StorageManager;
 import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import 
org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
@@ -43,9 +41,7 @@ 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);
@@ -62,7 +58,7 @@ public class DefaultHostListener implements 
HypervisorHostListener {
     @Inject
     StoragePoolDetailsDao storagePoolDetailsDao;
     @Inject
-    StoragePoolTagsDao storagePoolTagsDao;
+    StorageManager storageManager;
 
     @Override
     public boolean hostAdded(long hostId) {
@@ -104,43 +100,7 @@ public class DefaultHostListener implements 
HypervisorHostListener {
         updateStoragePoolHostVOAndDetails(poolVO, hostId, mspAnswer);
 
         if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {
-            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(Storage.StoragePoolType.PreSetup);
-                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());
-                dataStoreVO.setParent(poolVO.getId());
-
-                Map<String, String> details = new HashMap<>();
-                if(StringUtils.isNotEmpty(childDataStoreAnswer.getPoolType())) 
{
-                    details.put("pool_type", 
childDataStoreAnswer.getPoolType());
-                }
-
-                List<String> storageTags = 
storagePoolTagsDao.getStoragePoolTags(poolId);
-                primaryStoreDao.persist(dataStoreVO, details, storageTags);
-
-                updateStoragePoolHostVOAndDetails(dataStoreVO, hostId, 
childDataStoreAnswer);
-            }
+            storageManager.syncDatastoreClusterStoragePool(poolId, 
((ModifyStoragePoolAnswer) answer).getDatastoreClusterChildren(), hostId);
         }
 
         s_logger.info("Connection established between storage pool " + pool + 
" and host " + hostId);
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index a395575..a12bcd0 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -60,6 +60,7 @@ import 
org.apache.cloudstack.storage.command.ResignatureAnswer;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
@@ -1838,8 +1839,14 @@ public class KVMStorageProcessor implements 
StorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
         s_logger.info("'CheckDataStoreStoragePolicyComplainceCommand' not 
currently applicable for KVMStorageProcessor");
         return new Answer(cmd,false,"Not currently applicable for 
KVMStorageProcessor");
     }
+
+    @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
+        s_logger.info("SyncVolumePathCommand not currently applicable for 
KVMStorageProcessor");
+        return new Answer(cmd, false, "Not currently applicable for 
KVMStorageProcessor");
+    }
 }
diff --git 
a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
 
b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
index dd58bb5..f30df5d 100644
--- 
a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
+++ 
b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
@@ -35,8 +35,9 @@ import org.apache.cloudstack.storage.command.ForgetObjectCmd;
 import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
 import org.apache.cloudstack.storage.command.ResignatureAnswer;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
-import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
@@ -828,12 +829,18 @@ public class Ovm3StorageProcessor implements 
StorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
         LOGGER.info("'CheckDataStoreStoragePolicyComplainceCommand' not 
applicable used for Ovm3StorageProcessor");
         return new Answer(cmd,false,"Not applicable used for 
Ovm3StorageProcessor");
     }
 
     @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
+        LOGGER.info("SyncVolumePathCommand not currently applicable for 
Ovm3StorageProcessor");
+        return new Answer(cmd, false, "Not currently applicable for 
Ovm3StorageProcessor");
+    }
+
+    @Override
     public Answer copyVolumeFromPrimaryToPrimary(CopyCommand cmd) {
         return null;
     }
diff --git 
a/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorStorageProcessor.java
 
b/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorStorageProcessor.java
index 16579bc..8c8815c 100644
--- 
a/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorStorageProcessor.java
+++ 
b/plugins/hypervisors/simulator/src/main/java/com/cloud/resource/SimulatorStorageProcessor.java
@@ -41,6 +41,7 @@ import 
org.apache.cloudstack.storage.command.ResignatureAnswer;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
@@ -272,7 +273,12 @@ public class SimulatorStorageProcessor implements 
StorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+        return new Answer(cmd, true, null);
+    }
+
+    @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
         return new Answer(cmd, true, null);
     }
 }
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 3136608..b5bfa98 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
@@ -5272,10 +5272,12 @@ public class VmwareResource implements 
StoragePoolResource, ServerResource, Vmwa
                     String datacenterName = datastoreClusterPath.substring(0, 
pathstartPosition+1);
                     String childPath = datacenterName + summary.getName();
                     poolInfo.setHostPath(childPath);
-                    String uuid = UUID.nameUUIDFromBytes(((pool.getHost() + 
childPath)).getBytes()).toString();
+                    String uuid = 
childDsMo.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID);
+                    if (uuid == null) {
+                        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());
diff --git 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
index b06c1be..eb6251a 100644
--- 
a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ 
b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -50,6 +50,8 @@ import 
org.apache.cloudstack.storage.command.ResignatureAnswer;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathAnswer;
 import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
@@ -3892,7 +3894,7 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
         String primaryStorageNameLabel = cmd.getStoragePool().getUuid();
         String storagePolicyId = cmd.getStoragePolicyId();
         VmwareContext context = hostService.getServiceContext(cmd);
@@ -3962,4 +3964,81 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
             throw new CloudRuntimeException(msg, e);
         }
     }
+
+    @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
+        DiskTO disk = cmd.getDisk();
+        VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
+        DataStoreTO primaryStore = volumeTO.getDataStore();
+        String volumePath = volumeTO.getPath();
+        String vmName = volumeTO.getVmName();
+
+        boolean datastoreChangeObserved = false;
+        boolean volumePathChangeObserved = false;
+        String chainInfo = null;
+        try {
+            VmwareContext context = hostService.getServiceContext(null);
+            VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, 
null);
+            VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+            if (vmMo == null) {
+                vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+                if (vmMo == null) {
+                    String msg = "Unable to find the VM to execute 
SyncVolumePathCommand, vmName: " + vmName;
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                }
+            }
+
+            String datastoreUUID = primaryStore.getUuid();
+            if (disk.getDetails().get(DiskTO.PROTOCOL_TYPE) != null && 
disk.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster"))
 {
+                VirtualMachineDiskInfo matchingExistingDisk = 
getMatchingExistingDisk(hyperHost, context, vmMo, disk);
+                VirtualMachineDiskInfoBuilder diskInfoBuilder = 
vmMo.getDiskInfoBuilder();
+                if (diskInfoBuilder != null && matchingExistingDisk != null) {
+                    String[] diskChain = matchingExistingDisk.getDiskChain();
+                    assert (diskChain.length > 0);
+                    DatastoreFile file = new DatastoreFile(diskChain[0]);
+                    if (!file.getFileBaseName().equalsIgnoreCase(volumePath)) {
+                        if (s_logger.isInfoEnabled())
+                            s_logger.info("Detected disk-chain top file change 
on volume: " + volumeTO.getId() + " " + volumePath + " -> " + 
file.getFileBaseName());
+                        volumePathChangeObserved = true;
+                        volumePath = file.getFileBaseName();
+                        volumeTO.setPath(volumePath);
+                        chainInfo = _gson.toJson(matchingExistingDisk);
+                    }
+
+                    DatastoreMO diskDatastoreMofromVM = 
getDiskDatastoreMofromVM(hyperHost, context, vmMo, disk, diskInfoBuilder);
+                    if (diskDatastoreMofromVM != null) {
+                        String actualPoolUuid = 
diskDatastoreMofromVM.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID);
+                        if 
(!actualPoolUuid.equalsIgnoreCase(primaryStore.getUuid())) {
+                            s_logger.warn(String.format("Volume %s found to be 
in a different storage pool %s", volumePath, actualPoolUuid));
+                            datastoreChangeObserved = true;
+                            datastoreUUID = actualPoolUuid;
+                            chainInfo = _gson.toJson(matchingExistingDisk);
+                        }
+                    }
+                }
+            }
+
+            SyncVolumePathAnswer answer = new SyncVolumePathAnswer(disk);
+            if (datastoreChangeObserved) {
+                answer.setContextParam("datastoreName", datastoreUUID);
+            }
+            if (volumePathChangeObserved) {
+                answer.setContextParam("volumePath", volumePath);
+            }
+            if (chainInfo != null && !chainInfo.isEmpty()) {
+                answer.setContextParam("chainInfo", chainInfo);
+            }
+
+            return answer;
+        }  catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, 
invalidate VMware session context");
+
+                hostService.invalidateServiceContext(null);
+            }
+
+            return new SyncVolumePathAnswer("Failed to process 
SyncVolumePathCommand due to " + e.getMessage());
+        }
+    }
 }
diff --git 
a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
 
b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
index b3fce78..a035eac 100644
--- 
a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
+++ 
b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/XenServerStorageProcessor.java
@@ -50,6 +50,7 @@ import 
org.apache.cloudstack.storage.command.ResignatureAnswer;
 import org.apache.cloudstack.storage.command.ResignatureCommand;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
 import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
@@ -217,12 +218,18 @@ public class XenServerStorageProcessor implements 
StorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
         s_logger.info("'CheckDataStoreStoragePolicyComplainceCommand' not 
applicable used for XenServerStorageProcessor");
         return new Answer(cmd,false,"Not applicable used for 
XenServerStorageProcessor");
     }
 
     @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
+        s_logger.info("SyncVolumePathCommand not currently applicable for 
XenServerStorageProcessor");
+        return new Answer(cmd, false, "Not currently applicable for 
XenServerStorageProcessor");
+    }
+
+    @Override
     public AttachAnswer attachIso(final AttachCommand cmd) {
         final DiskTO disk = cmd.getDisk();
         final DataTO data = disk.getData();
diff --git 
a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
 
b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
index 97a4efa..7e2c701 100644
--- 
a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
+++ 
b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/Xenserver625StorageProcessor.java
@@ -30,6 +30,7 @@ import java.util.UUID;
 import 
org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
@@ -915,12 +916,18 @@ public class Xenserver625StorageProcessor extends 
XenServerStorageProcessor {
     }
 
     @Override
-    public Answer 
CheckDataStoreStoragePolicyComplaince(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
+    public Answer 
checkDataStoreStoragePolicyCompliance(CheckDataStoreStoragePolicyComplainceCommand
 cmd) {
         s_logger.info("'CheckDataStoreStoragePolicyComplainceCommand' not 
applicable used for XenServerStorageProcessor");
         return new Answer(cmd,false,"Not applicable used for 
XenServerStorageProcessor");
     }
 
     @Override
+    public Answer syncVolumePath(SyncVolumePathCommand cmd) {
+        s_logger.info("SyncVolumePathCommand not currently applicable for 
XenServerStorageProcessor");
+        return new Answer(cmd, false, "Not currently applicable for 
XenServerStorageProcessor");
+    }
+
+    @Override
     public Answer copyVolumeFromPrimaryToSecondary(final CopyCommand cmd) {
         final Connection conn = hypervisorResource.getConnection();
         final VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java 
b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index 080dadc..44024e7 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -204,6 +204,7 @@ import 
org.apache.cloudstack.api.command.admin.storage.PreparePrimaryStorageForM
 import 
org.apache.cloudstack.api.command.admin.storage.UpdateCloudToUseObjectStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.UpdateImageStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd;
 import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd;
 import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd;
 import org.apache.cloudstack.api.command.admin.systemvm.DestroySystemVmCmd;
@@ -3015,6 +3016,7 @@ public class ManagementServerImpl extends ManagerBase 
implements ManagementServe
         cmdList.add(FindStoragePoolsForMigrationCmd.class);
         cmdList.add(PreparePrimaryStorageForMaintenanceCmd.class);
         cmdList.add(UpdateStoragePoolCmd.class);
+        cmdList.add(SyncStoragePoolCmd.class);
         cmdList.add(UpdateImageStoreCmd.class);
         cmdList.add(DestroySystemVmCmd.class);
         cmdList.add(ListSystemVMsCmd.class);
diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java 
b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
index 33f6d7b..2e22003 100644
--- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
@@ -32,6 +32,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
+import java.util.LinkedHashSet;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -52,6 +54,7 @@ import 
org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd;
 import 
org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd;
 import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd;
+import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -90,6 +93,8 @@ import org.apache.cloudstack.management.ManagementServerHost;
 import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
 import 
org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand;
 import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.command.SyncVolumePathAnswer;
+import org.apache.cloudstack.storage.command.SyncVolumePathCommand;
 import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
 import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
 import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
@@ -104,6 +109,7 @@ import 
org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
 import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -114,6 +120,8 @@ import com.cloud.agent.api.DeleteStoragePoolCommand;
 import com.cloud.agent.api.StoragePoolInfo;
 import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
 import com.cloud.agent.manager.Commands;
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.dao.TemplateJoinDao;
@@ -1552,14 +1560,14 @@ public class StorageManagerImpl extends ManagerBase 
implements StorageManager, C
             if (primaryStorage.getStatus() == 
StoragePoolStatus.PrepareForMaintenance) {
                 throw new CloudRuntimeException(String.format("There is 
already a job running for preparation for maintenance of the storage pool %s", 
primaryStorage.getUuid()));
             }
-            handlePrepareDatastoreCluserMaintenance(lifeCycle, 
primaryStorageId);
+            handlePrepareDatastoreClusterMaintenance(lifeCycle, 
primaryStorageId);
         }
         lifeCycle.maintain(store);
 
         return 
(PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(primaryStorage.getId(), 
DataStoreRole.Primary);
     }
 
-    private void handlePrepareDatastoreCluserMaintenance(DataStoreLifeCycle 
lifeCycle, Long primaryStorageId) {
+    private void handlePrepareDatastoreClusterMaintenance(DataStoreLifeCycle 
lifeCycle, Long primaryStorageId) {
         StoragePoolVO datastoreCluster = 
_storagePoolDao.findById(primaryStorageId);
         datastoreCluster.setStatus(StoragePoolStatus.PrepareForMaintenance);
         _storagePoolDao.update(datastoreCluster.getId(), datastoreCluster);
@@ -1633,6 +1641,261 @@ public class StorageManagerImpl extends ManagerBase 
implements StorageManager, C
         return 
(PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(primaryStorage.getId(), 
DataStoreRole.Primary);
     }
 
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_SYNC_STORAGE_POOL, 
eventDescription = "synchronising storage pool with management server", async = 
true)
+    public StoragePool syncStoragePool(SyncStoragePoolCmd cmd) {
+        Long poolId = cmd.getPoolId();
+        StoragePoolVO pool = _storagePoolDao.findById(poolId);
+
+        if (pool == null) {
+            String msg = String.format("Unable to obtain lock on the storage 
pool record while syncing storage pool [%s] with management server", 
pool.getUuid());
+            s_logger.error(msg);
+            throw new InvalidParameterValueException(msg);
+        }
+
+        if (!pool.getPoolType().equals(StoragePoolType.DatastoreCluster)) {
+            throw new InvalidParameterValueException("SyncStoragePool API is 
currently supported only for storage type of datastore cluster");
+        }
+
+        if (!pool.getStatus().equals(StoragePoolStatus.Up)) {
+            throw new InvalidParameterValueException(String.format("Primary 
storage with id %s is not ready for syncing, as the status is %s", 
pool.getUuid(), pool.getStatus().toString()));
+        }
+
+        // find the host
+        List<Long> poolIds = new ArrayList<>();
+        poolIds.add(poolId);
+        List<Long> hosts = 
_storagePoolHostDao.findHostsConnectedToPools(poolIds);
+        if (hosts.size() > 0) {
+            Long hostId = hosts.get(0);
+            ModifyStoragePoolCommand modifyStoragePoolCommand = new 
ModifyStoragePoolCommand(true, pool);
+            final Answer answer = _agentMgr.easySend(hostId, 
modifyStoragePoolCommand);
+
+            if (answer == null) {
+                throw new CloudRuntimeException(String.format("Unable to get 
an answer to the modify storage pool command %s", pool.getUuid()));
+            }
+
+            if (!answer.getResult()) {
+                throw new CloudRuntimeException(String.format("Unable to 
process ModifyStoragePoolCommand for pool %s on the host %s due to ", 
pool.getUuid(), hostId, answer.getDetails()));
+            }
+
+            assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now 
why won't you actually return the ModifyStoragePoolAnswer when it's 
ModifyStoragePoolCommand? Pool=" +
+                    pool.getId() + "Host=" + hostId;
+            ModifyStoragePoolAnswer mspAnswer = (ModifyStoragePoolAnswer) 
answer;
+            StoragePoolVO poolVO = _storagePoolDao.findById(poolId);
+            updateStoragePoolHostVOAndBytes(poolVO, hostId, mspAnswer);
+            validateChildDatastoresToBeAddedInUpState(poolVO, 
mspAnswer.getDatastoreClusterChildren());
+            syncDatastoreClusterStoragePool(poolId, 
mspAnswer.getDatastoreClusterChildren(), hostId);
+            for (ModifyStoragePoolAnswer childDataStoreAnswer : 
mspAnswer.getDatastoreClusterChildren()) {
+                StoragePoolInfo childStoragePoolInfo = 
childDataStoreAnswer.getPoolInfo();
+                StoragePoolVO dataStoreVO = 
_storagePoolDao.findPoolByUUID(childStoragePoolInfo.getUuid());
+                for (Long host : hosts) {
+                    updateStoragePoolHostVOAndBytes(dataStoreVO, host, 
childDataStoreAnswer);
+                }
+            }
+
+        } else {
+            throw new CloudRuntimeException(String.format("Unable to sync 
storage pool [%s] as there no connected hosts to the storage pool", 
pool.getUuid()));
+        }
+        return (PrimaryDataStoreInfo) _dataStoreMgr.getDataStore(pool.getId(), 
DataStoreRole.Primary);
+    }
+
+    public void syncDatastoreClusterStoragePool(long datastoreClusterPoolId, 
List<ModifyStoragePoolAnswer> childDatastoreAnswerList, long hostId) {
+        StoragePoolVO datastoreClusterPool = 
_storagePoolDao.findById(datastoreClusterPoolId);
+        List<String> storageTags = 
_storagePoolTagsDao.getStoragePoolTags(datastoreClusterPoolId);
+        List<StoragePoolVO> childDatastores = 
_storagePoolDao.listChildStoragePoolsInDatastoreCluster(datastoreClusterPoolId);
+        Set<String> childDatastoreUUIDs = new HashSet<>();
+        for (StoragePoolVO childDatastore : childDatastores) {
+            childDatastoreUUIDs.add(childDatastore.getUuid());
+        }
+
+        for (ModifyStoragePoolAnswer childDataStoreAnswer : 
childDatastoreAnswerList) {
+            StoragePoolInfo childStoragePoolInfo = 
childDataStoreAnswer.getPoolInfo();
+            StoragePoolVO dataStoreVO = 
_storagePoolDao.findPoolByUUID(childStoragePoolInfo.getUuid());
+            if (dataStoreVO == null && 
childDataStoreAnswer.getPoolType().equalsIgnoreCase("NFS")) {
+                List<StoragePoolVO> nfsStoragePools = 
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem.toString());
+                for (StoragePoolVO storagePool : nfsStoragePools) {
+                    String storagePoolUUID = storagePool.getUuid();
+                    if 
(childStoragePoolInfo.getName().equalsIgnoreCase(storagePoolUUID.replaceAll("-",
 ""))) {
+                        dataStoreVO = storagePool;
+                        break;
+                    }
+                }
+            }
+            if (dataStoreVO != null) {
+                if (dataStoreVO.getParent() != datastoreClusterPoolId) {
+                    s_logger.debug(String.format("Storage pool %s with uuid %s 
is found to be under datastore cluster %s at vCenter, " +
+                                    "so moving the storage pool to be a child 
storage pool under the datastore cluster in CloudStack management server",
+                            childStoragePoolInfo.getName(), 
childStoragePoolInfo.getUuid(), datastoreClusterPool.getName()));
+                    dataStoreVO.setParent(datastoreClusterPoolId);
+                    _storagePoolDao.update(dataStoreVO.getId(), dataStoreVO);
+                    if (CollectionUtils.isNotEmpty(storageTags)) {
+                        
storageTags.addAll(_storagePoolTagsDao.getStoragePoolTags(dataStoreVO.getId()));
+                    } else {
+                        storageTags = 
_storagePoolTagsDao.getStoragePoolTags(dataStoreVO.getId());
+                    }
+                    if (CollectionUtils.isNotEmpty(storageTags)) {
+                        Set<String> set = new LinkedHashSet<>(storageTags);
+                        storageTags.clear();
+                        storageTags.addAll(set);
+                        if (s_logger.isDebugEnabled()) {
+                            s_logger.debug("Updating Storage Pool Tags to :" + 
storageTags);
+                        }
+                        _storagePoolTagsDao.persist(dataStoreVO.getId(), 
storageTags);
+                    }
+                } else {
+                    // This is to find datastores which are removed from 
datastore cluster.
+                    // The final set childDatastoreUUIDs contains the UUIDs of 
child datastores which needs to be removed from datastore cluster
+                    childDatastoreUUIDs.remove(childStoragePoolInfo.getUuid());
+                }
+            } else {
+                dataStoreVO = createChildDatastoreVO(datastoreClusterPool, 
childDataStoreAnswer);
+            }
+            updateStoragePoolHostVOAndBytes(dataStoreVO, hostId, 
childDataStoreAnswer);
+        }
+
+        handleRemoveChildStoragePoolFromDatastoreCluster(childDatastoreUUIDs);
+    }
+
+    private void validateChildDatastoresToBeAddedInUpState(StoragePoolVO 
datastoreClusterPool, List<ModifyStoragePoolAnswer> childDatastoreAnswerList) {
+        for (ModifyStoragePoolAnswer childDataStoreAnswer : 
childDatastoreAnswerList) {
+            StoragePoolInfo childStoragePoolInfo = 
childDataStoreAnswer.getPoolInfo();
+            StoragePoolVO dataStoreVO = 
_storagePoolDao.findPoolByUUID(childStoragePoolInfo.getUuid());
+            if (dataStoreVO == null && 
childDataStoreAnswer.getPoolType().equalsIgnoreCase("NFS")) {
+                List<StoragePoolVO> nfsStoragePools = 
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem.toString());
+                for (StoragePoolVO storagePool : nfsStoragePools) {
+                    String storagePoolUUID = storagePool.getUuid();
+                    if 
(childStoragePoolInfo.getName().equalsIgnoreCase(storagePoolUUID.replaceAll("-",
 ""))) {
+                          dataStoreVO = storagePool;
+                          break;
+                    }
+                }
+            }
+            if (dataStoreVO != null && 
!dataStoreVO.getStatus().equals(StoragePoolStatus.Up)) {
+                String msg = String.format("Cannot synchronise datastore 
cluster %s because primary storage with id %s is not ready for syncing, " +
+                        "as the status is %s", datastoreClusterPool.getUuid(), 
dataStoreVO.getUuid(), dataStoreVO.getStatus().toString());
+                throw new CloudRuntimeException(msg);
+            }
+        }
+    }
+
+    private StoragePoolVO createChildDatastoreVO(StoragePoolVO 
datastoreClusterPool, ModifyStoragePoolAnswer childDataStoreAnswer) {
+        StoragePoolInfo childStoragePoolInfo = 
childDataStoreAnswer.getPoolInfo();
+        List<String> storageTags = 
_storagePoolTagsDao.getStoragePoolTags(datastoreClusterPool.getId());
+
+        StoragePoolVO dataStoreVO = new StoragePoolVO();
+        
dataStoreVO.setStorageProviderName(datastoreClusterPool.getStorageProviderName());
+        dataStoreVO.setHostAddress(childStoragePoolInfo.getHost());
+        dataStoreVO.setPoolType(Storage.StoragePoolType.PreSetup);
+        dataStoreVO.setPath(childStoragePoolInfo.getHostPath());
+        dataStoreVO.setPort(datastoreClusterPool.getPort());
+        dataStoreVO.setName(childStoragePoolInfo.getName());
+        dataStoreVO.setUuid(childStoragePoolInfo.getUuid());
+        dataStoreVO.setDataCenterId(datastoreClusterPool.getDataCenterId());
+        dataStoreVO.setPodId(datastoreClusterPool.getPodId());
+        dataStoreVO.setClusterId(datastoreClusterPool.getClusterId());
+        dataStoreVO.setStatus(StoragePoolStatus.Up);
+        dataStoreVO.setUserInfo(datastoreClusterPool.getUserInfo());
+        dataStoreVO.setManaged(datastoreClusterPool.isManaged());
+        dataStoreVO.setCapacityIops(datastoreClusterPool.getCapacityIops());
+        
dataStoreVO.setCapacityBytes(childDataStoreAnswer.getPoolInfo().getCapacityBytes());
+        
dataStoreVO.setUsedBytes(childDataStoreAnswer.getPoolInfo().getCapacityBytes() 
- childDataStoreAnswer.getPoolInfo().getAvailableBytes());
+        dataStoreVO.setHypervisor(datastoreClusterPool.getHypervisor());
+        dataStoreVO.setScope(datastoreClusterPool.getScope());
+        dataStoreVO.setParent(datastoreClusterPool.getId());
+
+        Map<String, String> details = new HashMap<>();
+        
if(org.apache.commons.lang.StringUtils.isNotEmpty(childDataStoreAnswer.getPoolType()))
 {
+            details.put("pool_type", childDataStoreAnswer.getPoolType());
+        }
+        _storagePoolDao.persist(dataStoreVO, details, storageTags);
+        return dataStoreVO;
+    }
+
+    private void handleRemoveChildStoragePoolFromDatastoreCluster(Set<String> 
childDatastoreUUIDs) {
+
+        for (String childDatastoreUUID : childDatastoreUUIDs) {
+            StoragePoolVO dataStoreVO = 
_storagePoolDao.findPoolByUUID(childDatastoreUUID);
+            List<VolumeVO> allVolumes = 
_volumeDao.findByPoolId(dataStoreVO.getId());
+            allVolumes.removeIf(volumeVO -> volumeVO.getInstanceId() == null);
+            allVolumes.removeIf(volumeVO -> volumeVO.getState() != 
Volume.State.Ready);
+            for (VolumeVO volume : allVolumes) {
+                VMInstanceVO vmInstance = 
_vmInstanceDao.findById(volume.getInstanceId());
+                if (vmInstance == null) {
+                    continue;
+                }
+                long volumeId = volume.getId();
+                Long hostId = vmInstance.getHostId();
+                if (hostId == null) {
+                    hostId = vmInstance.getLastHostId();
+                }
+                HostVO hostVO = _hostDao.findById(hostId);
+
+                // Prepare for the syncvolumepath command
+                DataTO volTO = volFactory.getVolume(volume.getId()).getTO();
+                DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), 
volume.getPath(), volume.getVolumeType());
+                Map<String, String> details = new HashMap<String, String>();
+                details.put(DiskTO.PROTOCOL_TYPE, 
Storage.StoragePoolType.DatastoreCluster.toString());
+                disk.setDetails(details);
+
+                s_logger.debug(String.format("Attempting to process 
SyncVolumePathCommand for the volume %d on the host %d with state %s", 
volumeId, hostId, hostVO.getResourceState()));
+                SyncVolumePathCommand cmd = new SyncVolumePathCommand(disk);
+                final Answer answer = _agentMgr.easySend(hostId, cmd);
+                // validate answer
+                if (answer == null) {
+                    throw new CloudRuntimeException("Unable to get an answer 
to the SyncVolumePath command for volume " + volumeId);
+                }
+                if (!answer.getResult()) {
+                    throw new CloudRuntimeException("Unable to process 
SyncVolumePathCommand for the volume" + volumeId + " to the host " + hostId + " 
due to " + answer.getDetails());
+                }
+                assert (answer instanceof SyncVolumePathAnswer) : "Well, now 
why won't you actually return the SyncVolumePathAnswer when it's 
SyncVolumePathCommand? volume=" +
+                        volume.getUuid() + "Host=" + hostId;
+
+                // check for the changed details of volume and update database
+                VolumeVO volumeVO = _volumeDao.findById(volumeId);
+                String datastoreName = answer.getContextParam("datastoreName");
+                if (datastoreName != null) {
+                    StoragePoolVO storagePoolVO = 
_storagePoolDao.findByUuid(datastoreName);
+                    if (storagePoolVO != null) {
+                        volumeVO.setPoolId(storagePoolVO.getId());
+                    } else {
+                        s_logger.warn(String.format("Unable to find datastore 
%s while updating the new datastore of the volume %d", datastoreName, 
volumeId));
+                    }
+                }
+
+                String volumePath = answer.getContextParam("volumePath");
+                if (volumePath != null) {
+                    volumeVO.setPath(volumePath);
+                }
+
+                String chainInfo = answer.getContextParam("chainInfo");
+                if (chainInfo != null) {
+                    volumeVO.setChainInfo(chainInfo);
+                }
+
+                _volumeDao.update(volumeVO.getId(), volumeVO);
+            }
+            dataStoreVO.setParent(0L);
+            _storagePoolDao.update(dataStoreVO.getId(), dataStoreVO);
+        }
+
+    }
+
+    private void updateStoragePoolHostVOAndBytes(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("//", "/"));
+            _storagePoolHostDao.persist(poolHost);
+        } else {
+            
poolHost.setLocalPath(mspAnswer.getPoolInfo().getLocalPath().replaceAll("//", 
"/"));
+        }
+
+        StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId());
+        poolVO.setUsedBytes(mspAnswer.getPoolInfo().getCapacityBytes() - 
mspAnswer.getPoolInfo().getAvailableBytes());
+        poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes());
+
+        _storagePoolDao.update(pool.getId(), poolVO);
+    }
+
     protected class StorageGarbageCollector extends ManagedContextRunnable {
 
         public StorageGarbageCollector() {
diff --git 
a/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java 
b/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java
index 3e8822e..772b947 100644
--- a/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java
+++ b/server/src/main/java/com/cloud/storage/StoragePoolAutomationImpl.java
@@ -35,6 +35,7 @@ import org.springframework.stereotype.Component;
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
 import com.cloud.alert.AlertManager;
 import com.cloud.host.HostVO;
 import com.cloud.host.Status;
@@ -100,6 +101,8 @@ public class StoragePoolAutomationImpl implements 
StoragePoolAutomation {
     ManagementServer server;
     @Inject
     DataStoreProviderManager providerMgr;
+    @Inject
+    StorageManager storageManager;
 
     @Override
     public boolean maintain(DataStore store) {
@@ -162,6 +165,10 @@ public class StoragePoolAutomationImpl implements 
StoragePoolAutomation {
                     if (s_logger.isDebugEnabled()) {
                         s_logger.debug("ModifyStoragePool false succeeded");
                     }
+                    if (pool.getPoolType() == 
Storage.StoragePoolType.DatastoreCluster) {
+                        s_logger.debug(String.format("Started synchronising 
datastore cluster storage pool %s with vCenter", pool.getUuid()));
+                        
storageManager.syncDatastoreClusterStoragePool(pool.getId(), 
((ModifyStoragePoolAnswer) answer).getDatastoreClusterChildren(), host.getId());
+                    }
                 }
             }
             // check to see if other ps exist
@@ -323,6 +330,10 @@ public class StoragePoolAutomationImpl implements 
StoragePoolAutomation {
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug("ModifyStoragePool add succeeded");
                 }
+                if (pool.getPoolType() == 
Storage.StoragePoolType.DatastoreCluster) {
+                    s_logger.debug(String.format("Started synchronising 
datastore cluster storage pool %s with vCenter", pool.getUuid()));
+                    
storageManager.syncDatastoreClusterStoragePool(pool.getId(), 
((ModifyStoragePoolAnswer) answer).getDatastoreClusterChildren(), host.getId());
+                }
             }
         }
 
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index 0b0702a..f3bb57a 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -95,6 +95,7 @@ known_categories = {
     'StorageMaintenance': 'Storage Pool',
     'StoragePool': 'Storage Pool',
     'StorageProvider': 'Storage Pool',
+    'syncStoragePool': 'Storage Pool',
     'SecurityGroup': 'Security Group',
     'SSH': 'SSH',
     'register': 'Registration',

Reply via email to