Ramesh N has uploaded a new change for review.

Change subject: engine: sync job for gluster disk provisioning
......................................................................

engine: sync job for gluster disk provisioning

  Adding a sync job for gluster Disk Provisioning. It will
monitor all the storage devices in the host and update the
engine database accordingly.

Change-Id: I651bb51873a96d491c5a5f51147cb72be958985a
Signed-off-by: Ramesh Nachimuthu <[email protected]>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJob.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/SyncStorageDevicesCommand.java
A 
backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJobTest.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
M backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
M 
backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
M packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
14 files changed, 544 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/05/39705/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java
index d2ac864..fc4f4a8 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJob.java
@@ -33,6 +33,7 @@
 import org.ovirt.engine.core.dao.gluster.GlusterServerServiceDao;
 import org.ovirt.engine.core.dao.gluster.GlusterServiceDao;
 import org.ovirt.engine.core.dao.gluster.GlusterVolumeDao;
+import org.ovirt.engine.core.dao.gluster.StorageDeviceDao;
 import org.ovirt.engine.core.dao.network.InterfaceDao;
 import org.ovirt.engine.core.utils.lock.EngineLock;
 import org.ovirt.engine.core.utils.lock.LockManager;
@@ -134,6 +135,9 @@
         return DbFacade.getInstance().getGlusterGeoRepDao();
     }
 
+    protected StorageDeviceDao getStorageDeviceDao() {
+        return DbFacade.getInstance().getStorageDeviceDao();
+    }
     /**
      * Acquires a lock on the cluster with given id and locking group {@link 
LockingGroup#GLUSTER}
      *
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java
index 44c76cf..5297ca9 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/GlusterJobsManager.java
@@ -2,6 +2,7 @@
 
 import java.util.concurrent.TimeUnit;
 
+import org.ovirt.engine.core.bll.utils.Injector;
 import org.ovirt.engine.core.common.config.Config;
 import org.ovirt.engine.core.common.config.ConfigValues;
 import org.ovirt.engine.core.common.mode.ApplicationMode;
@@ -72,6 +73,15 @@
                 
getRefreshRate(ConfigValues.GlusterRefreshRateGeoRepDiscoveryInSecs),
                 TimeUnit.SECONDS);
 
+        StorageDeviceSyncJob StorageDeviceSyncJobInstance = 
Injector.get(StorageDeviceSyncJob.class);
+        scheduler.scheduleAFixedDelayJob(StorageDeviceSyncJobInstance,
+                "gluster_storage_device_pool_event",
+                new Class[0],
+                new Class[0],
+                getRefreshRate(ConfigValues.GlusterRefreshRateStorageDevices),
+                getRefreshRate(ConfigValues.GlusterRefreshRateStorageDevices),
+                TimeUnit.SECONDS);
+
         scheduler.scheduleAFixedDelayJob(GlusterGeoRepSyncJob.getInstance(),
                 "gluster_georepstatus_poll_event",
                 new Class[0],
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJob.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJob.java
new file mode 100644
index 0000000..57ae61e
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJob.java
@@ -0,0 +1,186 @@
+package org.ovirt.engine.core.bll.gluster;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.inject.Singleton;
+
+import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import org.ovirt.engine.core.common.businessentities.gluster.StorageDevice;
+import org.ovirt.engine.core.common.gluster.GlusterFeatureSupported;
+import org.ovirt.engine.core.common.utils.Pair;
+import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
+import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
+import org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
+import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class StorageDeviceSyncJob extends GlusterJob {
+    private static final Logger log = 
LoggerFactory.getLogger(StorageDeviceSyncJob.class);
+
+    public void init() {
+        log.info("Gluster Storage Device monitoring has been initialized");
+    }
+
+    @OnTimerMethodAnnotation("gluster_storage_device_pool_event")
+    public void refreshStorageDevices() {
+        // get all clusters
+        List<VDSGroup> clusters = getClusterDao().getAll();
+        // for every cluster that supports disk provisioning
+        for (VDSGroup cluster : clusters) {
+            if (supportsGlusterDiskProvisioning(cluster)) {
+                
refreshStorageDevicesFromServers(getClusterUtils().getAllUpServers(cluster.getId()));
+            }
+        }
+    }
+
+    public void refreshStorageDevicesFromServers(List<VDS> upServers) {
+        List<Callable<Pair<VDS, List<StorageDevice>>>> storageDevicesListCalls 
= new ArrayList<>();
+
+        for (final VDS server : upServers) {
+            storageDevicesListCalls.add(new Callable<Pair<VDS, 
List<StorageDevice>>>() {
+                @Override
+                public Pair<VDS, List<StorageDevice>> call() throws Exception {
+                    List<StorageDevice> storageDevices = 
getStorageDevicesFromServer(server);
+                    return new Pair<VDS, List<StorageDevice>>(server, 
storageDevices);
+                }
+            });
+        }
+
+        if (!storageDevicesListCalls.isEmpty()) {
+            List<Pair<VDS, List<StorageDevice>>> storageDevices = 
ThreadPoolUtil.invokeAll(storageDevicesListCalls);
+            for (Pair<VDS, List<StorageDevice>> pair : storageDevices) {
+                if (pair.getSecond() != null) {
+                    updateStorageDevices(pair.getFirst(), pair.getSecond());
+                }
+            }
+        }
+    }
+
+    private List<StorageDevice> getStorageDevicesFromServer(VDS server) {
+        try {
+            VDSReturnValue returnValue =
+                    runVdsCommand(VDSCommandType.GetStorageDeviceList,
+                            new VdsIdVDSCommandParametersBase(server.getId()));
+            if (returnValue.getSucceeded()) {
+                return (List<StorageDevice>) returnValue.getReturnValue();
+            } else {
+                log.error("VDS error retriving storage device {}", 
returnValue.getVdsError().getMessage());
+                log.debug("VDS Error", returnValue.getVdsError());
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("Exception retriving storage device from vds {}", 
e.getMessage());
+            log.debug("Exception", e);
+            return null;
+        }
+
+    }
+
+    private void updateStorageDevices(VDS vds, List<StorageDevice> 
storageDevicesFromVdsm) {
+        Set<String> deviceUuidsFromVdsm = new HashSet<>();
+        Set<String> deviceNamesFromVdsm = new HashSet<>();
+
+        List<StorageDevice> storageDevicesInDb = 
getStorageDeviceDao().getStorageDevicesInHost(vds.getId());
+        Map<String, StorageDevice> nameToDeviceMap = new HashMap<>();
+        Map<String, StorageDevice> deviceUuidToDeviceMap = new HashMap<>();
+
+        // Make deviceUuid to Device map and deviceName to device map so that 
we can find the
+        // newly added and updated devices without looping over the same list 
again and again.
+        for (StorageDevice storageDevice : storageDevicesInDb) {
+            nameToDeviceMap.put(storageDevice.getName(), storageDevice);
+            if (storageDevice.getDevUuid() != null && 
!storageDevice.getDevUuid().isEmpty()) {
+                deviceUuidToDeviceMap.put(storageDevice.getDevUuid(), 
storageDevice);
+            }
+        }
+
+        List<StorageDevice> storageDevicesToUpdate = new ArrayList<>();
+        List<StorageDevice> storageDevicesToDelete = new ArrayList<>();
+
+        for (StorageDevice storageDevice : storageDevicesFromVdsm) {
+            // Create deviceName and deviceUuid set to use it while finding 
the deleted services.
+            deviceNamesFromVdsm.add(storageDevice.getName());
+            if (storageDevice.getDevUuid() != null) {
+                deviceUuidsFromVdsm.add(storageDevice.getDevUuid());
+            }
+            // If DevUuid is already exits in the DB then its an existing 
devices
+            // Assume device from vdsm doesn't have devUUID, but device name 
already exists in the DB
+            // Following two cases possible:
+            // 1. If device in DB doesn't have a devUUID
+            // update the device if there is a change from vdsm.
+            // 2. If device in DB has devUUID
+            // Though name matches, its two different devices. So treat this 
device as new one.
+            // Device in DB will be updated/removed by some other iteration in 
the loop
+
+            StorageDevice storageDevByDevUuid = 
deviceUuidToDeviceMap.get(storageDevice.getDevUuid());
+            StorageDevice storageDevByName = 
nameToDeviceMap.get(storageDevice.getName());
+            if (storageDevByDevUuid != null) {
+                storageDevice.setId(storageDevByDevUuid.getId());
+                if (!Objects.equals(storageDevByDevUuid, storageDevice)) {
+                    storageDevicesToUpdate.add(storageDevice);
+                }
+            } else if (storageDevByName != null && 
StringUtils.isBlank(storageDevByName.getDevUuid())) {
+                storageDevice.setId(storageDevByName.getId());
+                if (!Objects.equals(storageDevByName, storageDevice)) {
+                    storageDevicesToUpdate.add(storageDevice);
+                }
+            } else {
+                storageDevice.setId(Guid.newGuid());
+                storageDevice.setVdsId(vds.getId());
+                log.debug("detected new storage device '{}' for host '{}'",
+                        storageDevice.getName(),
+                        vds.getName());
+                getStorageDeviceDao().save(storageDevice);
+                
logStorageDeviceMessage(AuditLogType.NEW_STORAGE_DEVICE_DETECTED,
+                        vds,
+                        storageDevice);
+            }
+        }
+
+        for (StorageDevice storageDevice : storageDevicesInDb) {
+            if ((storageDevice.getDevUuid() != null && 
!deviceUuidsFromVdsm.contains(storageDevice.getDevUuid()))
+                    || (storageDevice.getDevUuid() == null && 
!deviceNamesFromVdsm.contains(storageDevice.getName()))) {
+                log.debug("storage device '{}' detected removed for the host 
'{}'",
+                        storageDevice.getName(),
+                        vds.getName());
+                
logStorageDeviceMessage(AuditLogType.STORAGE_DEVICE_REMOVED_FROM_THE_HOST,
+                        vds,
+                        storageDevice);
+                storageDevicesToDelete.add(storageDevice);
+            }
+        }
+
+        if (!storageDevicesToUpdate.isEmpty()) {
+            getStorageDeviceDao().updateAllInBatch(storageDevicesToUpdate);
+        }
+        if (!storageDevicesToDelete.isEmpty()) {
+            getStorageDeviceDao().removeAllInBatch(storageDevicesToDelete);
+        }
+
+    }
+
+    private void logStorageDeviceMessage(AuditLogType logType, VDS vds, final 
StorageDevice device) {
+        logUtil.logAuditMessage(vds.getVdsGroupId(), null, vds,
+                logType, Collections.singletonMap("storageDevice", 
device.getName()));
+    }
+
+    private boolean supportsGlusterDiskProvisioning(VDSGroup cluster) {
+        return cluster.supportsGlusterService()
+                && 
GlusterFeatureSupported.glusterBrickProvisioning(cluster.getcompatibility_version());
+    }
+
+}
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/SyncStorageDevicesCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/SyncStorageDevicesCommand.java
new file mode 100644
index 0000000..da7a4d9
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/gluster/SyncStorageDevicesCommand.java
@@ -0,0 +1,56 @@
+package org.ovirt.engine.core.bll.gluster;
+
+import java.util.Arrays;
+
+import org.ovirt.engine.core.bll.VdsCommand;
+import org.ovirt.engine.core.bll.VdsValidator;
+import org.ovirt.engine.core.bll.utils.Injector;
+import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.action.VdsActionParameters;
+import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import org.ovirt.engine.core.common.errors.VdcBllMessages;
+import org.ovirt.engine.core.common.gluster.GlusterFeatureSupported;
+
+public class SyncStorageDevicesCommand<T extends VdsActionParameters> extends 
VdsCommand<T> {
+
+    public SyncStorageDevicesCommand(T parameters) {
+        super(parameters);
+    }
+
+    @Override
+    protected boolean canDoAction() {
+        VDSGroup cluster = getVdsGroup();
+        if (!cluster.supportsGlusterService()
+                || 
!GlusterFeatureSupported.glusterBrickProvisioning(cluster.getcompatibility_version()))
 {
+            return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_STORAGE_PROVISIONING_NOT_SUPPORTED_BY_CLUSTER);
+        }
+
+        VdsValidator validator = new VdsValidator(getVds());
+        return validate(validator.isUp());
+    }
+
+    @Override
+    protected void setActionMessageParameters() {
+        super.setActionMessageParameters();
+        addCanDoActionMessage(VdcBllMessages.VAR__ACTION__SYNC);
+        addCanDoActionMessage(VdcBllMessages.VAR__TYPE__STORAGE_DEVICE);
+        addCanDoActionMessageVariable("VdsName", getVds().getName());
+    }
+
+    @Override
+    protected void executeCommand() {
+
+        
getStorageDeviceSyncJobInstance().refreshStorageDevicesFromServers(Arrays.asList(getVds()));
+        setSucceeded(true);
+    }
+
+    private StorageDeviceSyncJob getStorageDeviceSyncJobInstance() {
+        return Injector.get(StorageDeviceSyncJob.class);
+    }
+
+    @Override
+    public AuditLogType getAuditLogTypeValue() {
+        return getSucceeded() ? AuditLogType.SYNC_STORAGE_DEVICES_IN_HOST
+                : AuditLogType.SYNC_STORAGE_DEVICES_IN_HOST_FAILED;
+    }
+}
diff --git 
a/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJobTest.java
 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJobTest.java
new file mode 100644
index 0000000..32e38b2
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/test/java/org/ovirt/engine/core/bll/gluster/StorageDeviceSyncJobTest.java
@@ -0,0 +1,232 @@
+package org.ovirt.engine.core.bll.gluster;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.ovirt.engine.core.bll.utils.ClusterUtils;
+import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.businessentities.VDSGroup;
+import org.ovirt.engine.core.common.businessentities.gluster.StorageDevice;
+import org.ovirt.engine.core.common.config.ConfigValues;
+import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
+import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
+import org.ovirt.engine.core.common.vdscommands.VdsIdVDSCommandParametersBase;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.compat.Version;
+import 
org.ovirt.engine.core.dal.dbbroker.auditloghandling.gluster.GlusterAuditLogUtil;
+import org.ovirt.engine.core.dao.VdsDAO;
+import org.ovirt.engine.core.dao.VdsGroupDAO;
+import org.ovirt.engine.core.dao.gluster.StorageDeviceDao;
+import org.ovirt.engine.core.utils.MockConfigRule;
+
+@RunWith(MockitoJUnitRunner.class)
+public class StorageDeviceSyncJobTest {
+    private static final Guid CLUSTER_GUID_3_5 = new 
Guid("CC111111-1111-1111-1111-111111111111");
+    private static final Guid CLUSTER_GUID_3_6 = new 
Guid("CC111111-1111-1111-1111-111111111111");
+
+    private static final Guid HOST_ID_WITH_NEW_DEVICES = new 
Guid("00000000-0000-0000-0000-000000000000");
+    private static final Guid HOST_ID_WITH_DEVICES_DELETED = new 
Guid("00000000-0000-0000-0000-000000000001");
+    private static final Guid HOST_ID_WITH_DEVICES_CHANGED = new 
Guid("00000000-0000-0000-0000-000000000002");
+
+    private static final Guid DEVICE_WITHOUT_ANYCHANGE = new 
Guid("00000000-0000-0000-0000-000000000000");
+    private static final Guid DEVICE_WITH_CHANGE = new 
Guid("00000000-0000-0000-0000-000000000001");
+    private static final Guid DEVICE_WITH_NAME_CHANGE = new 
Guid("00000000-0000-0000-0000-000000000002");
+    private static final Guid DEVICE_WITH_DEVUUID_BUT_NAME_CHANGED = new 
Guid("00000000-0000-0000-0000-000000000003");
+
+    @Mock
+    private StorageDeviceDao storageDeviceDao;
+
+    @Mock
+    private ClusterUtils clusterUtils;
+
+    @Mock
+    private VdsGroupDAO clusterDao;
+
+    @Mock
+    private VdsDAO vdsDao;
+
+    @Spy
+    private StorageDeviceSyncJob syncJob;
+
+    @Mock
+    private GlusterAuditLogUtil logUtil;
+    @ClassRule
+    public static MockConfigRule mcr = new MockConfigRule(
+            mockConfig(ConfigValues.GlusterBrickProvisioningEnabled, 
Version.v3_5.toString(), true),
+            mockConfig(ConfigValues.GlusterBrickProvisioningEnabled, 
Version.v3_4.toString(), false),
+            mockConfig(ConfigValues.DefaultMinThreadPoolSize, 10),
+            mockConfig(ConfigValues.DefaultMaxThreadPoolSize, 20),
+            mockConfig(ConfigValues.DefaultMaxThreadWaitQueueSize, 10)
+            );
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        syncJob.setLogUtil(logUtil);
+        doReturn(storageDeviceDao).when(syncJob).getStorageDeviceDao();
+        doReturn(clusterDao).when(syncJob).getClusterDao();
+        doReturn(clusterUtils).when(syncJob).getClusterUtils();
+        doReturn(getClusters()).when(clusterDao).getAll();
+        doReturn(vdsDao).when(syncJob).getVdsDao();
+        
doReturn(getAllUpServers()).when(clusterUtils).getAllUpServers(CLUSTER_GUID_3_6);
+        
doReturn(getStorageDevices(HOST_ID_WITH_NEW_DEVICES)).when(storageDeviceDao)
+                .getStorageDevicesInHost(HOST_ID_WITH_NEW_DEVICES);
+        
doReturn(getStorageDevices(HOST_ID_WITH_DEVICES_CHANGED)).when(storageDeviceDao)
+                .getStorageDevicesInHost(HOST_ID_WITH_DEVICES_CHANGED);
+        
doReturn(getStorageDevices(HOST_ID_WITH_DEVICES_DELETED)).when(storageDeviceDao)
+                .getStorageDevicesInHost(HOST_ID_WITH_DEVICES_DELETED);
+
+    }
+
+    private List<VDS> getAllUpServers() {
+        VDS vds1 = new VDS();
+        vds1.setId(HOST_ID_WITH_NEW_DEVICES);
+        VDS vds2 = new VDS();
+        vds2.setId(HOST_ID_WITH_DEVICES_CHANGED);
+        VDS vds3 = new VDS();
+        vds3.setId(HOST_ID_WITH_DEVICES_DELETED);
+        return Arrays.asList(vds1, vds2, vds3);
+
+    }
+
+    private Object getStorageDevicesVDSReturnVal(Guid hostId) {
+        VDSReturnValue vdsRetValue = new VDSReturnValue();
+        vdsRetValue.setSucceeded(true);
+        if (HOST_ID_WITH_NEW_DEVICES.equals(hostId)) {
+            vdsRetValue.setReturnValue(Arrays.asList(getStorageDevice("sda", 
null),
+                    getStorageDevice("sdb", null),
+                    getStorageDevice("sdc", null)));
+        } else if (HOST_ID_WITH_DEVICES_CHANGED.equals(hostId)) {
+            List<StorageDevice> devices = new ArrayList<StorageDevice>();
+            devices.add(getStorageDevice("device-without-anychange", 
DEVICE_WITHOUT_ANYCHANGE));
+            devices.add(getStorageDevice("new-device-with-name-change", 
DEVICE_WITH_NAME_CHANGE));
+            StorageDevice device = getStorageDevice("device-with-change", 
DEVICE_WITH_CHANGE);
+            device.setMountPoint("/temp-mount");
+            device.setFsType("XFS");
+            device.setSize(12345678L);
+            devices.add(device);
+            device =
+                    getStorageDevice("device-with-devuuid-but-name-changed-1", 
DEVICE_WITH_DEVUUID_BUT_NAME_CHANGED);
+            device.setDevUuid("123456");
+            devices.add(device);
+            
devices.add(getStorageDevice("device-with-devuuid-but-name-changed", null));
+            vdsRetValue.setReturnValue(devices);
+        }
+        else {
+            vdsRetValue.setReturnValue(Collections.EMPTY_LIST);
+        }
+        return vdsRetValue;
+    }
+
+    private void mockVdsCommand() {
+        
doReturn(getStorageDevicesVDSReturnVal(HOST_ID_WITH_NEW_DEVICES)).when(syncJob)
+                .runVdsCommand(eq(VDSCommandType.GetStorageDeviceList),
+                        argThat(isHostMathces(HOST_ID_WITH_NEW_DEVICES)));
+
+        
doReturn(getStorageDevicesVDSReturnVal(HOST_ID_WITH_DEVICES_CHANGED)).when(syncJob)
+                .runVdsCommand(eq(VDSCommandType.GetStorageDeviceList),
+                        argThat(isHostMathces(HOST_ID_WITH_DEVICES_CHANGED)));
+
+        
doReturn(getStorageDevicesVDSReturnVal(HOST_ID_WITH_DEVICES_DELETED)).when(syncJob)
+                .runVdsCommand(eq(VDSCommandType.GetStorageDeviceList),
+                        argThat(isHostMathces(HOST_ID_WITH_DEVICES_DELETED)));
+
+    }
+
+    private ArgumentMatcher<VdsIdVDSCommandParametersBase> isHostMathces(final 
Guid hostId) {
+        return new ArgumentMatcher<VdsIdVDSCommandParametersBase>() {
+
+            @Override
+            public boolean matches(Object argument) {
+                if (argument instanceof VdsIdVDSCommandParametersBase) {
+                    return hostId.equals(((VdsIdVDSCommandParametersBase) 
argument).getVdsId());
+                }
+
+                return false;
+            }
+        };
+    }
+
+    @Test
+    public void testRefreshStorageDevices() {
+        mockVdsCommand();
+        syncJob.refreshStorageDevices();
+        Mockito.verify(storageDeviceDao, 
times(5)).save(any(StorageDevice.class));
+        Mockito.verify(storageDeviceDao, 
times(2)).removeAllInBatch(any(List.class));
+        Mockito.verify(storageDeviceDao, 
times(1)).updateAllInBatch(any(List.class));
+    }
+
+    private List<VDSGroup> getClusters() {
+        List<VDSGroup> list = new ArrayList<>();
+        list.add(createCluster(Version.v3_4, CLUSTER_GUID_3_5));
+        list.add(createCluster(Version.v3_5, CLUSTER_GUID_3_6));
+        return list;
+    }
+
+    private VDSGroup createCluster(Version v, Guid id) {
+        VDSGroup cluster = new VDSGroup();
+        cluster.setId(id);
+        cluster.setName("cluster");
+        cluster.setGlusterService(true);
+        cluster.setVirtService(false);
+        cluster.setcompatibility_version(v);
+        return cluster;
+    }
+
+    private StorageDevice getStorageDevice(String name, Guid id) {
+        StorageDevice storageDevice = new StorageDevice();
+        storageDevice.setCanCreateBrick(true);
+        storageDevice.setDescription("Test Device" + name);
+        storageDevice.setDevPath("/dev/" + name);
+        storageDevice.setDevType("SCSI");
+        storageDevice.setName(name);
+        storageDevice.setSize(10000L);
+        if (id == null) {
+            storageDevice.setId(Guid.newGuid());
+        } else {
+            storageDevice.setId(id);
+        }
+        return storageDevice;
+    }
+
+    private List<StorageDevice> getStorageDevices(Guid hostId) {
+        if (HOST_ID_WITH_DEVICES_DELETED.equals(hostId)) {
+            return Arrays.asList(getStorageDevice("sda", null),
+                    getStorageDevice("sdb", null),
+                    getStorageDevice("sdc", null));
+        } else if (HOST_ID_WITH_DEVICES_CHANGED.equals(hostId)) {
+            List<StorageDevice> deviceList = new ArrayList<StorageDevice>();
+            deviceList.add(getStorageDevice("device-without-anychange", 
DEVICE_WITHOUT_ANYCHANGE));
+            deviceList.add(getStorageDevice("device-with-change", 
DEVICE_WITH_CHANGE));
+            deviceList.add(getStorageDevice("device-with-name-change", 
DEVICE_WITH_NAME_CHANGE));
+            StorageDevice device =
+                    getStorageDevice("device-with-devuuid-but-name-changed", 
DEVICE_WITH_DEVUUID_BUT_NAME_CHANGED);
+            device.setDevUuid("123456");
+            device.setSize(999999L);
+            deviceList.add(device);
+            return deviceList;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java
index 70a7981..20c2170 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java
@@ -415,6 +415,11 @@
     GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATED(4121),
     GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATE_FAILED(4122, AuditLogSeverity.ERROR),
     GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATE_FAILED_PARTIALLY(4123, 
AuditLogSeverity.ERROR),
+    NEW_STORAGE_DEVICE_DETECTED(4124),
+    STORAGE_DEVICE_REMOVED_FROM_THE_HOST(4125),
+    SYNC_STORAGE_DEVICES_IN_HOST(4126),
+    SYNC_STORAGE_DEVICES_IN_HOST_FAILED(4127),
+
     USER_FORCE_SELECTED_SPM(159),
     USER_VDS_RESTART(41),
     USER_FAILED_VDS_RESTART(107, AuditLogSeverity.ERROR),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java
index 8909659..1a45d4d 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java
@@ -318,6 +318,7 @@
     DeactivateGlusterVolumeSnapshot(1437, 
ActionGroup.MANIPULATE_GLUSTER_VOLUME, QuotaDependency.NONE),
     RestoreGlusterVolumeSnapshot(1438, ActionGroup.MANIPULATE_GLUSTER_VOLUME, 
QuotaDependency.NONE),
     UpdateGlusterVolumeSnapshotConfig(1439, 
ActionGroup.MANIPULATE_GLUSTER_VOLUME, QuotaDependency.NONE),
+    SyncStorageDevices(1440, ActionGroup.MANIPULATE_HOST, 
QuotaDependency.NONE),
 
     // Cluster Policy
     AddClusterPolicy(1450, ActionGroup.EDIT_STORAGE_POOL_CONFIGURATION, false, 
QuotaDependency.NONE),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
index 27cef6c..63a9a51 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
@@ -1301,6 +1301,13 @@
     GlusterRefreshRateLight,
 
     /**
+     * Refresh rate (in seconds) for Storage Devices.
+     */
+    @TypeConverterAttribute(Integer.class)
+    @DefaultValueAttribute("7200")
+    GlusterRefreshRateStorageDevices,
+
+    /**
      * Refresh rate (in seconds) for heavy-weight gluster data i.e. commands 
to fetch such data adds a considerable
      * overhead on the GlusterFS processes.
      */
@@ -1453,6 +1460,10 @@
     @DefaultValueAttribute("true")
     GlusterVolumeSnapshotSupported,
 
+    @TypeConverterAttribute(Boolean.class)
+    @DefaultValueAttribute("true")
+    GlusterBrickProvisioningEnabled,
+
     @TypeConverterAttribute(Integer.class)
     @DefaultValueAttribute("300")
     GlusterRefreshRateSnapshotDiscovery,
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
index 2fb6526..f08f2fe 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
@@ -51,6 +51,7 @@
     VAR__TYPE__GLUSTER_GEOREP_SESSION,
     VAR__TYPE__GLUSTER_GEOREP_CONFIG,
     VAR__TYPE__GLUSTER_VOLUME_SNAPSHOT,
+    VAR__TYPE__STORAGE_DEVICE,
 
     // External Event
     VAR__TYPE__EXTERNAL_EVENT,
@@ -113,6 +114,7 @@
     VAR__ACTION__UPDATE_SLA_POLICY,
     VAR__ACTION__UPDATE_VM_VERSION,
     VAR__ACTION__VOLUME_SNAPSHOT_CONFIG_UPDATE,
+    VAR__ACTION__SYNC,
 
     // Host statuses replacements
     VAR__HOST_STATUS__UP,
@@ -955,6 +957,7 @@
     
ACTION_TYPE_FAILED_GLUSTER_VOLUME_SNAPSHOT_ALREADY_ACTIVATED(ErrorType.CONFLICT),
     
ACTION_TYPE_FAILED_GLUSTER_VOLUME_SNAPSHOT_ALREADY_DEACTIVATED(ErrorType.CONFLICT),
     
GLUSTER_TASKS_NOT_SUPPORTED_FOR_CLUSTER_LEVEL(ErrorType.INCOMPATIBLE_VERSION),
+    
ACTION_TYPE_FAILED_STORAGE_PROVISIONING_NOT_SUPPORTED_BY_CLUSTER(ErrorType.NOT_SUPPORTED),
 
     // OpenStack Glance
     ACTION_TYPE_FAILED_IMAGE_DOWNLOAD_ERROR(ErrorType.BAD_PARAMETERS),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
index faab9c6..d08bcd2 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/gluster/GlusterFeatureSupported.java
@@ -101,4 +101,15 @@
   public static boolean glusterSnapshot(Version version) {
       return supportedInConfig(ConfigValues.GlusterVolumeSnapshotSupported, 
version);
   }
+
+   /**
+   *
+   * @param version
+   *            Compatibility version to check for.
+   * @return <code>true</code> if disk provisioning feature is enabled,
+   *         <code>false</code> if it's not.
+   */
+  public static boolean glusterBrickProvisioning(Version version) {
+        return supportedInConfig(ConfigValues.GlusterBrickProvisioningEnabled, 
version);
+  }
 }
diff --git 
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties 
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
index 7bd5435..c361745 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
@@ -368,6 +368,7 @@
 VAR__ACTION__REMOVE_BRICKS_COMMIT=$action commit removing
 VAR__ACTION__START_PROFILE=$action start profiling
 VAR__ACTION__STOP_PROFILE=$action stop profiling
+VAR__ACTION__SYNC=$action sync
 VAR__ACTION__ENABLE=$action enable
 VAR__ACTION__DISABLE=$action disable
 VAR__ACTION__REFRESH=$action refresh
@@ -1038,6 +1039,7 @@
 VAR__TYPE__GLUSTER_SERVICE=$type Service
 VAR__TYPE__GLUSTER_GEOREP_SESSION=$type Geo-replication session
 VAR__TYPE__GLUSTER_VOLUME_SNAPSHOT=$type Gluster Volume Snapshot
+VAR__TYPE__STORAGE_DEVICE=$type Storage Device
 VALIDATION.GLUSTER.VOLUME.ID.NOT_NULL=Volume ID is required.
 VALIDATION.GLUSTER.VOLUME.CLUSTER_ID.NOT_NULL=Cluster ID is required.
 VALIDATION.GLUSTER.VOLUME.NAME.NOT_NULL=Volume Name is required.
@@ -1157,6 +1159,7 @@
 ACTION_TYPE_FAILED_GLUSTER_VOLUME_SNAPSHOT_ALREADY_ACTIVATED=Cannot ${action} 
${type}. Gluster volume snapshot ${snapname} is already activated.
 ACTION_TYPE_FAILED_GLUSTER_VOLUME_SNAPSHOT_ALREADY_DEACTIVATED=Cannot 
${action} ${type}. Gluster volume snapshot ${snapname} is already de-activated.
 GLUSTER_TASKS_NOT_SUPPORTED_FOR_CLUSTER_LEVEL=Cannot ${action} ${type}. 
Gluster task management is not supported in compatibility version 
${compatibilityVersion}.
+ACTION_TYPE_FAILED_STORAGE_PROVISIONING_NOT_SUPPORTED_BY_CLUSTER=Cannot 
${action} ${type}. The selected cluster doesn't support Storage provisioning.
 
 ACTION_TYPE_FAILED_TAG_ID_REQUIRED=Cannot ${action} ${type}. Tag ID is 
required.
 ACTION_TYPE_FAILED_QOS_OUT_OF_RANGE_VALUES=Cannot ${action} ${type}. Values 
are out of range.
diff --git 
a/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
 
b/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
index 7f2b178..266129e 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
@@ -837,6 +837,10 @@
 GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATED=Updated Gluster volume snapshot 
configuration(s).
 GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATE_FAILED=Failed to update gluster volume 
snapshot configuration(s).
 GLUSTER_VOLUME_SNAPSHOT_CONFIG_UPDATE_FAILED_PARTIALLY=Failed to update 
gluster volume snapshot configuration(s) ${failedSnapshotConfigs}.
+NEW_STORAGE_DEVICE_DETECTED=Found new storage device ${storageDevice} on host 
${VdsName}, and added it to engine DB."
+STORAGE_DEVICE_REMOVED_FROM_THE_HOST=Detected deletion of storage device 
${storageDevice} on host ${VdsName}, and deleting it from engine DB."
+SYNC_STORAGE_DEVICES_IN_HOST=Manually synced the storage devices from host 
${VdsName}
+SYNC_STORAGE_DEVICES_IN_HOST_FAILED=Failed to synced storage devices from host 
${VdsName}
 VDS_UNTRUSTED=Host ${VdsName} was set to non-operational. Host is not trusted 
by the attestation service.
 USER_ADDED_NETWORK_QOS=Network QoS ${QosName} was added. (User: ${UserName})
 USER_FAILED_TO_ADD_NETWORK_QOS=Failed to add Network QoS ${QosName}. (User: 
${UserName})
diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
index dfddda1..c580a7f 100644
--- 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
@@ -1009,6 +1009,9 @@
     @DefaultStringValue("$action commit removing")
     String VAR__ACTION__REMOVE_BRICKS_COMMIT();
 
+    @DefaultStringValue("$action sync")
+    String VAR__ACTION__SYNC();
+
     @DefaultStringValue("$action start profiling")
     String VAR__ACTION__START_PROFILE();
 
@@ -1116,6 +1119,9 @@
 
     @DefaultStringValue("$type Service")
     String VAR__TYPE__GLUSTER_SERVICE();
+
+    @DefaultStringValue("$type Storage Device")
+    String VAR__TYPE__STORAGE_DEVICE();
 
     @DefaultStringValue("Cannot ${action} ${type}. The chosen disk drive 
letter is already in use, please select a free one.")
     String ACTION_TYPE_FAILED_DISK_LETTER_ALREADY_IN_USE();
@@ -3128,6 +3134,9 @@
     @DefaultStringValue("Cannot ${action} ${type}. Gluster task management is 
not supported in compatibility version ${compatibilityVersion}.")
     String GLUSTER_TASKS_NOT_SUPPORTED_FOR_CLUSTER_LEVEL();
 
+    @DefaultStringValue("Cannot ${action} ${type}. The selected cluster 
doesn't support Storage provisioning.")
+    String ACTION_TYPE_FAILED_STORAGE_PROVISIONING_NOT_SUPPORTED_BY_CLUSTER();
+
     @DefaultStringValue("Cannot ${action} ${type}. All three values are needed 
in order to define QoS on each network directions.")
     String ACTION_TYPE_FAILED_NETWORK_QOS_MISSING_VALUES();
 
diff --git a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql 
b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
index 1907c10..54a91ec 100644
--- a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
+++ b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
@@ -167,6 +167,7 @@
 select fn_db_add_config_value('GlusterServicesEnabled', 'false', '3.0');
 select fn_db_add_config_value('GlusterServicesEnabled', 'false', '3.1');
 select fn_db_add_config_value('GlusterServicesEnabled', 'false', '3.2');
+select fn_db_add_config_value('GlusterRefreshRateStorageDevices', '7200', 
'general');
 select fn_db_add_config_value('GlusterSupport', 'false', '3.0');
 select fn_db_add_config_value('GlusterSupportForceCreateVolume', 'false', 
'3.0');
 select fn_db_add_config_value('GlusterSupportForceCreateVolume', 'false', 
'3.1');
@@ -202,6 +203,14 @@
 select fn_db_add_config_value('GlusterRefreshRateGeoRepStatusInSecs', '300', 
'general');
 
 
+-- Gluster Disk Provisioning --
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.0');
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.1');
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.2');
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.3');
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.4');
+select fn_db_add_config_value('GlusterBrickProvisioningEnabled', 'false', 
'3.5');
+
 -- OpenStack related
 select fn_db_add_config_value('KeystoneAuthUrl', '', 'general');
 


-- 
To view, visit https://gerrit.ovirt.org/39705
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I651bb51873a96d491c5a5f51147cb72be958985a
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.5-gluster
Gerrit-Owner: Ramesh N <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to