Daniel Erez has uploaded a new change for review.

Change subject: core: support Cinder disk removal
......................................................................

core: support Cinder disk removal

* Added 'deleteVolume' method to OpenStackVolumeProviderProxy.
* Added 'deleteDisk' method to CinderBroker.
* Added RemoveCinderDiskCommand/RemoveCinderDiskCallback.

Change-Id: I7a3803072ade96a241e8f71a030360f4168a1b71
Bug-Url: https://bugzilla.redhat.com/1185826
Signed-off-by: Daniel Erez <de...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveDiskCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/CinderBroker.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommand.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommandCallback.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/dal/src/main/resources/bundles/AuditLogMessages.properties
8 files changed, 293 insertions(+), 13 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/35/39135/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveDiskCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveDiskCommand.java
index d124de1..1885dd6 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveDiskCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RemoveDiskCommand.java
@@ -6,6 +6,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 import org.apache.commons.lang.StringUtils;
 import org.ovirt.engine.core.bll.context.CommandContext;
@@ -13,6 +15,7 @@
 import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter;
 import org.ovirt.engine.core.bll.quota.QuotaStorageDependent;
 import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator;
+import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil;
 import org.ovirt.engine.core.bll.utils.PermissionSubject;
 import org.ovirt.engine.core.bll.validator.storage.DiskImagesValidator;
 import org.ovirt.engine.core.bll.validator.storage.DiskValidator;
@@ -47,8 +50,10 @@
 import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.compat.TransactionScopeOption;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dao.BaseDiskDao;
 import org.ovirt.engine.core.dao.DiskDao;
 import org.ovirt.engine.core.dao.DiskImageDAO;
+import org.ovirt.engine.core.dao.DiskImageDynamicDAO;
 import org.ovirt.engine.core.dao.VmDeviceDAO;
 import org.ovirt.engine.core.utils.transaction.TransactionMethod;
 import org.ovirt.engine.core.utils.transaction.TransactionSupport;
@@ -65,6 +70,11 @@
 
     public RemoveDiskCommand(T parameters) {
         this(parameters, null);
+    }
+
+    public RemoveDiskCommand(T parameters, CommandContext commandContext) {
+        super(parameters, commandContext);
+        setStorageDomainId(getParameters().getStorageDomainId());
     }
 
     public RemoveDiskCommand(T parameters, CommandContext commandContext) {
@@ -115,7 +125,8 @@
         // currently, only images have specific checks.
         // In the future, if LUNs get specific checks,
         // or additional storage types are added, other else-if clauses should 
be added.
-        if (getDisk().getDiskStorageType() == DiskStorageType.IMAGE) {
+        if (getDisk().getDiskStorageType() == DiskStorageType.IMAGE ||
+                getDisk().getDiskStorageType() == DiskStorageType.CINDER) {
             return canRemoveDiskBasedOnImageStorageCheck();
         }
 
@@ -278,23 +289,41 @@
         return DbFacade.getInstance().getDiskImageDao();
     }
 
-    protected DiskDao getDiskDao() {
+    public DiskDao getDiskDao() {
         return DbFacade.getInstance().getDiskDao();
     }
 
     @Override
     protected void executeCommand() {
-        if (getDisk().getDiskStorageType() == DiskStorageType.IMAGE) {
-            VdcReturnValueBase vdcReturnValue =
-                    
runInternalActionWithTasksContext(VdcActionType.RemoveImage,
-                            buildRemoveImageParameters(getDiskImage()));
-            if (vdcReturnValue.getSucceeded()) {
-                incrementVmsGeneration();
-                
getReturnValue().getVdsmTaskIdList().addAll(vdcReturnValue.getInternalVdsmTaskIdList());
-                setSucceeded(true);
-            }
-        } else {
-            removeLunDisk();
+        switch (getDisk().getDiskStorageType()) {
+            case IMAGE:
+                VdcReturnValueBase vdcReturnValue =
+                        
runInternalActionWithTasksContext(VdcActionType.RemoveImage,
+                                buildRemoveImageParameters(getDiskImage()));
+                if (vdcReturnValue.getSucceeded()) {
+                    incrementVmsGeneration();
+                    
getReturnValue().getVdsmTaskIdList().addAll(vdcReturnValue.getInternalVdsmTaskIdList());
+                    setSucceeded(true);
+                }
+                break;
+            case LUN:
+                removeLunDisk();
+                break;
+            case CINDER:
+                Future<VdcReturnValueBase> future = 
CommandCoordinatorUtil.executeAsyncCommand(
+                        VdcActionType.RemoveCinderDisk,
+                        new RemoveDiskParameters(getParameters().getDiskId()),
+                        cloneContextAndDetachFromParent());
+                try {
+                    setReturnValue(future.get());
+                    setSucceeded(getReturnValue().getSucceeded());
+                } catch (InterruptedException | ExecutionException e) {
+                    log.error("Error removing Cinder disk '{}': {}",
+                            getDiskImage().getDiskAlias(),
+                            e.getMessage());
+                    log.debug("Exception", e);
+                }
+                break;
         }
     }
 
@@ -349,6 +378,9 @@
             if (getDisk().getDiskStorageType() == DiskStorageType.LUN) {
                 return getSucceeded() ? 
AuditLogType.USER_FINISHED_REMOVE_DISK_NO_DOMAIN
                         : 
AuditLogType.USER_FINISHED_FAILED_REMOVE_DISK_NO_DOMAIN;
+            } else if (getDisk().getDiskStorageType() == 
DiskStorageType.CINDER) {
+                return getSucceeded() ? AuditLogType.USER_REMOVE_DISK_INITIATED
+                        : AuditLogType.USER_FINISHED_FAILED_REMOVE_DISK;
             }
             return getSucceeded() ? AuditLogType.USER_FINISHED_REMOVE_DISK
                     : AuditLogType.USER_FINISHED_FAILED_REMOVE_DISK;
@@ -478,4 +510,12 @@
     @Override
     public void addQuotaPermissionSubject(List<PermissionSubject> 
quotaPermissionList) {
     }
+
+    protected BaseDiskDao getBaseDiskDao() {
+        return getDbFacade().getBaseDiskDao();
+    }
+
+    protected DiskImageDynamicDAO getDiskImageDynamicDAO() {
+        return getDbFacade().getDiskImageDynamicDao();
+    }
 }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java
index fd1f83c..25aacd1 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java
@@ -67,6 +67,10 @@
         return retCinderVolume.getId();
     }
 
+    public void deleteVolume(String volumeId) {
+        getClient(getTenantId()).volumes().delete(volumeId).execute();
+    }
+
     public Volume getVolumeById(String id) {
         return getClient(getTenantId()).volumes().show(id).execute();
     }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/CinderBroker.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/CinderBroker.java
index b9d9290..71b4c45 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/CinderBroker.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/CinderBroker.java
@@ -3,6 +3,7 @@
 import com.woorea.openstack.base.client.OpenStackResponseException;
 import com.woorea.openstack.cinder.model.Volume;
 import com.woorea.openstack.cinder.model.VolumeForCreate;
+import org.apache.commons.httpclient.HttpStatus;
 import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy;
 import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
 import 
org.ovirt.engine.core.common.businessentities.storage.CinderVolumeStatus;
@@ -50,6 +51,33 @@
         });
     }
 
+    public Void deleteDisk(final CinderDisk cinderDisk) {
+        return execute(new Callable<Void>() {
+            @Override
+            public Void call() {
+                proxy.deleteVolume(cinderDisk.getId().toString());
+                return null;
+            }
+        });
+    }
+
+    public boolean isDiskExist(final Guid id) {
+        return execute(new Callable<Boolean>() {
+            @Override
+            public Boolean call() {
+                try {
+                    Volume volume = proxy.getVolumeById(id.toString());
+                    return volume != null;
+                } catch (OpenStackResponseException ex) {
+                    if (ex.getStatus() == HttpStatus.SC_NOT_FOUND) {
+                        return false;
+                    }
+                    throw ex;
+                }
+            }
+        });
+    }
+
     public ImageStatus getDiskStatus(final Guid id) {
         return execute(new Callable<ImageStatus>() {
             @Override
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommand.java
new file mode 100644
index 0000000..3cea3bd
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommand.java
@@ -0,0 +1,119 @@
+package org.ovirt.engine.core.bll.storage;
+
+import org.ovirt.engine.core.bll.ImagesHandler;
+import org.ovirt.engine.core.bll.InternalCommandAttribute;
+import org.ovirt.engine.core.bll.RemoveDiskCommand;
+import org.ovirt.engine.core.bll.context.CommandContext;
+import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback;
+import org.ovirt.engine.core.common.action.RemoveDiskParameters;
+import org.ovirt.engine.core.common.businessentities.VmDeviceId;
+import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
+import org.ovirt.engine.core.common.businessentities.storage.ImageStatus;
+import org.ovirt.engine.core.common.utils.Pair;
+import org.ovirt.engine.core.compat.CommandStatus;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.compat.TransactionScopeOption;
+import org.ovirt.engine.core.dao.ImageDao;
+import org.ovirt.engine.core.utils.transaction.TransactionMethod;
+import org.ovirt.engine.core.utils.transaction.TransactionSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Map;
+
+@InternalCommandAttribute
+public class RemoveCinderDiskCommand<T extends RemoveDiskParameters> extends 
RemoveDiskCommand<T> {
+
+    private static final Logger log = 
LoggerFactory.getLogger(RemoveCinderDiskCommand.class);
+    private CinderBroker cinderBroker;
+    private Guid storageDomainId;
+
+    public RemoveCinderDiskCommand(T parameters) {
+        super(parameters, null);
+    }
+
+    public RemoveCinderDiskCommand(T parameters, CommandContext 
commandContext) {
+        super(parameters, commandContext);
+    }
+
+    @Override
+    public void executeCommand() {
+        CinderDisk disk = (CinderDisk) getDisk();
+        if (disk.getImageStatus() == ImageStatus.ILLEGAL) {
+            // Remove disk from DB
+            setCommandStatus(CommandStatus.SUCCEEDED);
+        }
+        else {
+            // Remove disk from Cinder
+            ImagesHandler.updateImageStatus(disk.getId(), ImageStatus.LOCKED);
+            getCinderBroker().deleteDisk(disk);
+        }
+        persistCommand(getParameters().getParentCommand(), true);
+        getReturnValue().setActionReturnValue(disk.getId());
+        setSucceeded(true);
+    }
+
+    protected void removeDiskFromDb() {
+        final CinderDisk cinderDisk = (CinderDisk) getDisk();
+        TransactionSupport.executeInScope(TransactionScopeOption.Required,
+                new TransactionMethod<Object>() {
+                    @Override
+                    public Object runInTransaction() {
+                        
getDiskImageDynamicDAO().remove(cinderDisk.getImageId());
+                        getImageDao().remove(cinderDisk.getImageId());
+                        // todo: remove snapshot
+                        getBaseDiskDao().remove(cinderDisk.getId());
+                        getVmDeviceDAO().remove(new 
VmDeviceId(cinderDisk.getId(), null));
+                        return null;
+                    }
+                });
+    }
+
+    protected void endSuccessfully() {
+        setSucceeded(true);
+    }
+
+    protected ImageDao getImageDao() {
+        return getDbFacade().getImageDao();
+    }
+
+    @Override
+    public CommandCallback getCallback() {
+        return new RemoveCinderDiskCommandCallback();
+    }
+
+    @Override
+    public boolean canDoAction() {
+        return true;
+    }
+
+    @Override
+    protected Map<String, Pair<String, String>> getExclusiveLocks() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    protected Map<String, Pair<String, String>> getSharedLocks() {
+        return Collections.emptyMap();
+    }
+
+    protected CinderBroker getCinderBroker() {
+        if (cinderBroker == null) {
+            cinderBroker = new CinderBroker(getStorageDomainId(), 
getReturnValue().getExecuteFailedMessages());
+        }
+        return cinderBroker;
+    }
+
+    @Override
+    public Guid getStorageDomainId() {
+        if (storageDomainId == null) {
+            storageDomainId = getCinderDisk().getStorageIds().get(0);
+        }
+        return storageDomainId;
+    }
+
+    private CinderDisk getCinderDisk() {
+        return (CinderDisk) getDisk();
+    }
+}
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommandCallback.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommandCallback.java
new file mode 100644
index 0000000..0c1afa3
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/RemoveCinderDiskCommandCallback.java
@@ -0,0 +1,86 @@
+package org.ovirt.engine.core.bll.storage;
+
+import org.ovirt.engine.core.bll.ImagesHandler;
+import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil;
+import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.action.RemoveDiskParameters;
+import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
+import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
+import org.ovirt.engine.core.common.businessentities.storage.ImageStatus;
+import org.ovirt.engine.core.compat.CommandStatus;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
+
+import java.util.List;
+
+public class RemoveCinderDiskCommandCallback extends 
AbstractCinderDiskCommandCallback<RemoveCinderDiskCommand<RemoveDiskParameters>>
 {
+
+    @Override
+    public void doPolling(Guid cmdId, List<Guid> childCmdIds) {
+        super.doPolling(cmdId, childCmdIds);
+
+        CinderBroker cinderBroker = getCinderBroker();
+        if (!cinderBroker.isDiskExist(getDiskId())) {
+            // Disk has been deleted successfully
+            getCommand().setCommandStatus(CommandStatus.SUCCEEDED);
+            return;
+        }
+
+        ImageStatus imageStatus = cinderBroker.getDiskStatus(getDiskId());
+        DiskImage disk = getDisk();
+        if (imageStatus != null && imageStatus != disk.getImageStatus()) {
+            switch (imageStatus) {
+                case ILLEGAL:
+                    getCommand().getParameters().setShouldBeLogged(true);
+                    getCommand().setCommandStatus(CommandStatus.FAILED);
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public void onFailed(Guid cmdId, List<Guid> childCmdIds) {
+        super.onFailed(cmdId, childCmdIds);
+
+        log.error("Failed deleting disk from Cinder. ID: {}", getDiskId());
+        if (getCommand().getParameters().getShouldBeLogged()) {
+            new AuditLogDirector().log(getCommand(), 
AuditLogType.USER_FINISHED_FAILED_REMOVE_DISK);
+        }
+
+        ImagesHandler.updateImageStatus(getDiskId(), ImageStatus.ILLEGAL);
+        getCommand().endAction();
+        CommandCoordinatorUtil.removeAllCommandsInHierarchy(cmdId);
+    }
+
+    @Override
+    public void onSucceeded(Guid cmdId, List<Guid> childCmdIds) {
+        super.onSucceeded(cmdId, childCmdIds);
+
+        log.info("Disk has been successfully deleted from Cinder. ID: {}", 
getDiskId());
+        if (getCommand().getParameters().getShouldBeLogged()) {
+            new AuditLogDirector().log(getCommand(), 
AuditLogType.USER_FINISHED_REMOVE_DISK);
+        }
+
+        getCommand().removeDiskFromDb();
+        getCommand().endAction();
+        CommandCoordinatorUtil.removeAllCommandsInHierarchy(cmdId);
+    }
+
+    @Override
+    protected Guid getDiskId() {
+        return getCommand().getParameters().getDiskId();
+    }
+
+    @Override
+    protected CinderDisk getDisk() {
+        if (disk == null) {
+            disk = (CinderDisk) getCommand().getDiskDao().get(getDiskId());
+        }
+        return disk;
+    }
+
+    @Override
+    protected CinderBroker getCinderBroker() {
+        return getCommand().getCinderBroker();
+    }
+}
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 3abff17..bffd09d 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
@@ -242,6 +242,7 @@
     USER_FAILED_MOVED_VM_DISK(2009, AuditLogSeverity.ERROR),
     USER_MOVED_VM_DISK_FINISHED_SUCCESS(2010),
     USER_MOVED_VM_DISK_FINISHED_FAILURE(2011, AuditLogSeverity.ERROR),
+    USER_REMOVE_DISK_INITIATED(2038),
     USER_FINISHED_REMOVE_DISK(2014),
     USER_FINISHED_FAILED_REMOVE_DISK(2015, AuditLogSeverity.WARNING),
     USER_FINISHED_REMOVE_DISK_NO_DOMAIN(2012),
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 26796ef..b71fdaf 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
@@ -426,6 +426,7 @@
 
     // Cinder
     AddCinderDisk(3200, ActionGroup.CONFIGURE_VM_STORAGE, false, 
QuotaDependency.NONE),
+    RemoveCinderDisk(3201, QuotaDependency.STORAGE),
 
     // Host Devices
     RefreshHostDevices(4000, ActionGroup.MANIPULATE_HOST, false, 
QuotaDependency.NONE);
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 0121d08c..6dde699 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties
@@ -120,6 +120,7 @@
 USER_FAILED_MOVED_VM_DISK=User ${UserName} failed to move disk ${DiskAlias} to 
domain ${StorageDomainName}.
 USER_MOVED_VM_DISK_FINISHED_SUCCESS=User ${UserName} finished moving disk 
${DiskAlias} to domain ${StorageDomainName}.
 USER_MOVED_VM_DISK_FINISHED_FAILURE=User ${UserName} have failed to move disk 
${DiskAlias} to domain ${StorageDomainName}.
+USER_REMOVE_DISK_INITIATED=Removal of Disk ${DiskAlias} from domain 
${StorageDomainName} was initiated by ${UserName}.
 USER_FINISHED_REMOVE_DISK=Disk ${DiskAlias} was successfully removed from 
domain ${StorageDomainName} (User ${UserName}).
 USER_FINISHED_FAILED_REMOVE_DISK=Failed to remove disk ${DiskAlias} from 
storage domain ${StorageDomainName} (User: ${UserName}).
 USER_FINISHED_REMOVE_DISK_NO_DOMAIN=Disk ${DiskAlias} was successfully removed 
(User ${UserName}).


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I7a3803072ade96a241e8f71a030360f4168a1b71
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Daniel Erez <de...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to