Daniel Erez has uploaded a new change for review. Change subject: core: cinder integration ......................................................................
core: cinder integration WIP. Will be divided to separate patches. This patch includes: * add disk_storage_type column to base_disks - Adding 'disk_storage_type' column to 'base_disks' table to differentiate between Image/Lun/Cinder. - Updating values for existing disks: 0 - images, 1 - DirectLUNs. * add disk_storage_type to DB views and functions - Adding 'disk_storage_type' to relevant views and functions: all_disks_including_snapshots/InsertBaseDisk/UpdateBaseDisk. * add disk_storage_type to mapper - Added 'disk_storage_type' to BaseDiskDaoDbFacadeImpl. * adding CinderDisk business entity - Added CinderDisk entity to represent a Disk managed by Cinder. - Added required CinderConnectionInfo entity which contains relevant information for volume location (e.g. ceph rbd path). * add Cinder to DiskStorageType enum * add CinderDiskRowMapper * add openstack_volume provider - Adding 'OPENSTACK_VOLUME' provider - a new provider for Cinder. * adding cinder StorageType - Adding CINDER to StorageType enum. * adding volume StorageDomainType - Adding Volume to StorageDomainType enum (for Cinder domains). * add OpenStackVolumeProviderProxy - Added OpenStackVolumeProviderProxy for communicating with Cinder client API. * AddDisk - support CinderDisk * RemoveDisk - support CinderDisk * refresh volume list on IsoDomainListSyncronizer - IsoDomainListSyncronizer: manual refresh volume list, for manual fetch of volume list on 'Storage -> Images' sub-tab. * VmInfoBuilder - support Cinder disks Change-Id: Idcb7955f374d58efbdaddb09bc48d9d4baa03120 Signed-off-by: Daniel Erez <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/IsoDomainListSyncronizer.java 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/RunVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/ProviderProxyFactory.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/AbstractOpenStackStorageProviderProxy.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackImageProviderProxy.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderConnectionInfo.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderDisk.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/Disk.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/OpenStackVolumeProviderProperties.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ProviderType.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageDomainType.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageType.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDiskDaoDbFacadeImpl.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskDaoDbFacadeImpl.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/provider/ProviderDaoDbFacadeImpl.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java M backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilder.java M packaging/dbscripts/base_disks_sp.sql M packaging/dbscripts/create_views.sql A packaging/dbscripts/upgrade/03_06_0520_add_disk_storage_type_column_to_base_disks.sql 26 files changed, 812 insertions(+), 142 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/58/35358/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java index ce30b87..30cc653 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java @@ -5,6 +5,7 @@ import java.util.Map; import org.ovirt.engine.core.bll.context.CommandContext; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; import org.ovirt.engine.core.bll.storage.IStorageHelper; import org.ovirt.engine.core.bll.storage.StorageHelperBase; @@ -41,6 +42,8 @@ import org.ovirt.engine.core.dao.StoragePoolIsoMapDAO; public abstract class AbstractDiskVmCommand<T extends VmDiskOperationParameterBase> extends VmCommand<T> { + + private OpenStackVolumeProviderProxy volumeProviderProxy; public AbstractDiskVmCommand(T parameters) { this(parameters, null); @@ -307,4 +310,12 @@ getVm() != null && validate(new VmValidator(getVm()).vmNotLocked()); } + + protected OpenStackVolumeProviderProxy getVolumeProviderProxy() { + if (volumeProviderProxy == null) { + volumeProviderProxy = OpenStackVolumeProviderProxy + .getFromStorageDomainId(getStorageDomainId()); + } + return volumeProviderProxy; + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java index 6c7dc35..582de46 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java @@ -1,13 +1,16 @@ package org.ovirt.engine.core.bll; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.profiles.DiskProfileHelper; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageDependent; @@ -27,6 +30,7 @@ import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.asynctasks.EntityInfo; import org.ovirt.engine.core.common.businessentities.ActionGroup; +import org.ovirt.engine.core.common.businessentities.CinderDisk; import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType; import org.ovirt.engine.core.common.businessentities.DiskImage; @@ -44,6 +48,9 @@ import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; import org.ovirt.engine.core.common.businessentities.VmDeviceId; +import org.ovirt.engine.core.common.businessentities.VolumeFormat; +import org.ovirt.engine.core.common.businessentities.VolumeType; +import org.ovirt.engine.core.common.businessentities.image_storage_domain_map; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.VdcBllMessages; @@ -366,10 +373,17 @@ getParameters().getDiskInfo().setId(Guid.newGuid()); getParameters().setEntityInfo(new EntityInfo(VdcObjectType.Disk, getParameters().getDiskInfo().getId())); ImagesHandler.setDiskAlias(getParameters().getDiskInfo(), getVm()); - if (DiskStorageType.IMAGE == getParameters().getDiskInfo().getDiskStorageType()) { - createDiskBasedOnImage(); - } else { - createDiskBasedOnLun(); + + switch (getParameters().getDiskInfo().getDiskStorageType()) { + case IMAGE: + createDiskBasedOnImage(); + break; + case LUN: + createDiskBasedOnLun(); + break; + case CINDER: + createDiskBasedOnCinder(); + break; } } @@ -462,6 +476,56 @@ setSucceeded(tmpRetValue.getSucceeded()); } + private void createDiskBasedOnCinder() { + OpenStackVolumeProviderProxy proxy = getVolumeProviderProxy(); + + final CinderDisk cinderDisk = new CinderDisk(); + cinderDisk.setDiskAlias(getDiskAlias()); + cinderDisk.setSize(getParameters().getDiskInfo().getSize()); + + String newVolumeId = proxy.createVolumeFromDiskImage(cinderDisk); + cinderDisk.setId(Guid.createGuidFromString(newVolumeId)); + cinderDisk.setImageId(Guid.createGuidFromString(newVolumeId)); + cinderDisk.setBoot(getParameters().getDiskInfo().isBoot()); + cinderDisk.setDiskInterface(getParameters().getDiskInfo().getDiskInterface()); + cinderDisk.setDiskAlias(getParameters().getDiskInfo().getDiskAlias()); + cinderDisk.setDiskDescription(getParameters().getDiskInfo().getDiskDescription()); + cinderDisk.setShareable(getParameters().getDiskInfo().isShareable()); + cinderDisk.setStorageIds(new ArrayList<>(Arrays.asList(getParameters().getStorageDomainId()))); + cinderDisk.setSize(getParameters().getDiskInfo().getSize()); + cinderDisk.setVolumeType(VolumeType.Unassigned); + cinderDisk.setvolumeFormat(VolumeFormat.RAW); + cinderDisk.setCreationDate(new Date()); + cinderDisk.setLastModified(new Date()); + cinderDisk.setActive(true); + //cinderDisk.setImageStatus(ImageStatus.LOCKED); + //cinderDisk.setVmSnapshotId(getParameters().getVmSnapshotId()); + + TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { + @Override + public Void runInTransaction() { + getBaseDiskDao().save(cinderDisk); + getImageDao().save(cinderDisk.getImage()); + getImageStorageDomainMapDao().save(new image_storage_domain_map(cinderDisk.getImageId(), + cinderDisk.getStorageIds().get(0), cinderDisk.getQuotaId(), cinderDisk.getDiskProfileId())); + + if (getVm() != null) { + VmDeviceUtils.addManagedDevice(new VmDeviceId(cinderDisk.getId(), getVmId()), + VmDeviceGeneralType.DISK, + VmDeviceType.DISK, + null, + shouldDiskBePlugged(), + Boolean.TRUE.equals(cinderDisk.getReadOnly()), + null); + } + return null; + } + }); + getReturnValue().setActionReturnValue(cinderDisk.getId()); + plugDiskToVmIfNeeded(); + setSucceeded(true); + } + /** * If disk is not allow to have snapshot no VM snapshot Id should be updated. * @param parameters diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java index fcbeff6..709b627 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java @@ -18,6 +18,7 @@ import org.ovirt.engine.core.bll.utils.VmDeviceUtils; import org.ovirt.engine.core.bll.validator.StorageDomainValidator; import org.ovirt.engine.core.common.businessentities.BaseDisk; +import org.ovirt.engine.core.common.businessentities.CinderDisk; import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType; import org.ovirt.engine.core.common.businessentities.DiskImage; @@ -579,6 +580,16 @@ return lunDisks; } + public static List<CinderDisk> filterDiskBasedOnCinder(Collection<Disk> listOfDisks) { + List<CinderDisk> cinderDisks = new ArrayList<>(); + for (Disk disk : listOfDisks) { + if (disk.getDiskStorageType() == DiskStorageType.CINDER) { + cinderDisks.add((CinderDisk) disk); + } + } + return cinderDisks; + } + public static void removeDiskImage(DiskImage diskImage, Guid vmId) { try { removeDiskFromVm(vmId, diskImage.getId()); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/IsoDomainListSyncronizer.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/IsoDomainListSyncronizer.java index b1a688b..4ac4bbd 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/IsoDomainListSyncronizer.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/IsoDomainListSyncronizer.java @@ -15,6 +15,7 @@ import org.ovirt.engine.core.bll.provider.ProviderProxyFactory; import org.ovirt.engine.core.bll.provider.storage.OpenStackImageProviderProxy; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.businessentities.ImageFileType; @@ -205,6 +206,9 @@ } else if (storageDomain.getStorageDomainType() == StorageDomainType.Image && storageDomain.getStorageType() == StorageType.GLANCE) { refreshResult = refreshImageDomain(storageDomain, tempProblematicRepoFileList, imageType); + } else if (storageDomain.getStorageDomainType() == StorageDomainType.Volume && + storageDomain.getStorageType() == StorageType.CINDER) { + refreshResult = refreshVolumeDomain(storageDomain, tempProblematicRepoFileList, imageType); } else { log.error("Unable to refresh the storage domain '{}', Storage Domain Type '{}' not supported", storageDomainId, storageDomain.getStorageDomainType()); @@ -261,6 +265,36 @@ } } + private boolean refreshVolumeDomain(final StorageDomain storageDomain, + List<RepoImage> problematicRepoFileList, final ImageFileType imageType) { + final RepoFileMetaDataDAO repoFileMetaDataDao = repoStorageDom; + + Provider provider = providerDao.get(new Guid(storageDomain.getStorage())); + final OpenStackVolumeProviderProxy client = ProviderProxyFactory.getInstance().create(provider); + + Lock syncObject = getSyncObject(storageDomain.getId(), imageType); + try { + syncObject.lock(); + return (Boolean) TransactionSupport.executeInScope(TransactionScopeOption.RequiresNew, + new TransactionMethod<Object>() { + @Override + public Object runInTransaction() { + repoFileMetaDataDao.removeRepoDomainFileList(storageDomain.getId(), imageType); + + List<RepoImage> diskImages = client.getAllVolumesAsRepoImages(); + for (RepoImage repoImage : diskImages) { + repoImage.setRepoDomainId(storageDomain.getId()); + repoFileMetaDataDao.addRepoFileMap(repoImage); + } + + return true; + } + }); + } finally { + syncObject.unlock(); + } + } + /** * The procedure Try to refresh the repository files of the storage domain id, with storage pool Id. If succeeded * will return True, otherwise return false and update the list, of the problematic repository files with the 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 03a59e3..25ff2e5 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 @@ -8,6 +8,7 @@ import java.util.Map; import org.apache.commons.lang.StringUtils; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageDependent; @@ -45,8 +46,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; @@ -60,6 +63,7 @@ private List<PermissionSubject> permsList = null; private List<VM> listVms; private String cachedDiskIsBeingRemovedLockMessage; + private OpenStackVolumeProviderProxy volumeProviderProxy; public RemoveDiskCommand(T parameters) { super(parameters); @@ -109,6 +113,12 @@ // or additional storage types are added, other else-if clauses should be added. if (getDisk().getDiskStorageType() == DiskStorageType.IMAGE) { return canRemoveDiskBasedOnImageStorageCheck(); + } + + if (getDisk().getDiskStorageType() == DiskStorageType.CINDER) { + getParameters().setStorageDomainId(((DiskImage) getDisk()).getStorageIds().get(0)); + setStorageDomainId(getParameters().getStorageDomainId()); + return true; } return true; @@ -276,17 +286,41 @@ @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()); + 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 CINDER: + final DiskImage cinderDisk = (DiskImage) getDisk(); + TransactionSupport.executeInScope(TransactionScopeOption.Required, + new TransactionMethod<Object>() { + @Override + public Object runInTransaction() { + getDiskImageDynamicDAO().remove(cinderDisk.getImageId()); + getBaseDiskDao().remove(cinderDisk.getId()); + getVmDeviceDAO().remove(new VmDeviceId(cinderDisk.getId(), null)); + return null; + } + }); + + try { + OpenStackVolumeProviderProxy proxy = getVolumeProviderProxy(); + proxy.deleteVolume(getDisk().getId().toString()); + } catch (Exception e) { + + } setSucceeded(true); - } - } else { - removeLunDisk(); + break; + case LUN: + removeLunDisk(); + break; } } @@ -470,4 +504,20 @@ @Override public void addQuotaPermissionSubject(List<PermissionSubject> quotaPermissionList) { } + + protected OpenStackVolumeProviderProxy getVolumeProviderProxy() { + if (volumeProviderProxy == null) { + volumeProviderProxy = OpenStackVolumeProviderProxy + .getFromStorageDomainId(getStorageDomainId()); + } + return volumeProviderProxy; + } + + 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/RunVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java index 1a1f6b1..a54be55 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java @@ -228,7 +228,7 @@ if (getVdsToRunOn()) { VMStatus status = null; try { - if (connectLunDisks(getVdsId())) { + if (connectLunDisks(getVdsId()) && updateCinderDisksConnections()) { status = createVm(); ExecutionHandler.setAsyncJob(getExecutionContext(), true); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java index e862170..2f9bb98 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommandBase.java @@ -9,11 +9,13 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; +import com.woorea.openstack.cinder.model.ConnectionInfo; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.job.ExecutionContext; import org.ovirt.engine.core.bll.job.ExecutionHandler; import org.ovirt.engine.core.bll.job.JobRepositoryFactory; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.bll.scheduling.RunVmDelayer; import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; import org.ovirt.engine.core.bll.storage.StorageHelperDirector; @@ -23,6 +25,9 @@ import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.action.VmOperationParameterBase; +import org.ovirt.engine.core.common.businessentities.CinderConnectionInfo; +import org.ovirt.engine.core.common.businessentities.CinderConnectionInfo.CinderConnectionData; +import org.ovirt.engine.core.common.businessentities.CinderDisk; import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand; import org.ovirt.engine.core.common.businessentities.LUNs; import org.ovirt.engine.core.common.businessentities.LunDisk; @@ -59,6 +64,7 @@ private SnapshotsValidator snapshotsValidator=new SnapshotsValidator(); private final List<Guid> runVdsList = new ArrayList<Guid>(); private Guid lastDecreasedVds; + private OpenStackVolumeProviderProxy volumeProviderProxy; protected RunVmCommandBase(Guid commandId) { super(commandId); @@ -302,6 +308,35 @@ return true; } + protected boolean updateCinderDisksConnections() { + if (getVm().getDiskMap().isEmpty()) { + VmHandler.updateDisksFromDb(getVm()); + } + List<CinderDisk> cinderDisks = ImagesHandler.filterDiskBasedOnCinder(getVm().getDiskMap().values()); + for (CinderDisk cinderDisk : cinderDisks) { + OpenStackVolumeProviderProxy proxy = getVolumeProviderProxy(cinderDisk.getStorageIds().get(0)); + ConnectionInfo connectionInfo = proxy.initializeConnectionForVolume(cinderDisk.getId().toString()); + + CinderConnectionInfo cinderConnectionInfo = new CinderConnectionInfo(); + cinderConnectionInfo.setDriverVolumeType(connectionInfo.getDriverVolumeType()); + + CinderConnectionData cinderConnectionData = new CinderConnectionData(); + cinderConnectionData.setName(connectionInfo.getData().getName()); + cinderConnectionData.setSecretType(connectionInfo.getData().getSecretType()); + cinderConnectionData.setSecretUuid(connectionInfo.getData().getSecretUuid()); + cinderConnectionData.setQosSpecs(connectionInfo.getData().getQosSpecs()); + cinderConnectionData.setAuthEnabled(connectionInfo.getData().getAuthEnabled()); + cinderConnectionData.setAuthUsername(connectionInfo.getData().getAuthUsername()); + cinderConnectionData.setAccessMode(connectionInfo.getData().getAccessMode()); + cinderConnectionData.setHosts(connectionInfo.getData().getHosts()); + cinderConnectionData.setPorts(connectionInfo.getData().getPorts()); + cinderConnectionInfo.setData(cinderConnectionData); + + cinderDisk.setCinderConnectionInfo(cinderConnectionInfo); + } + return true; + } + private void decreasePendingVms() { Guid vdsId = getCurrentVdsId(); VM vm = getVm(); @@ -389,4 +424,11 @@ protected String getLockMessage() { return VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED.name(); } + + protected OpenStackVolumeProviderProxy getVolumeProviderProxy(Guid storageDomainId) { + if (volumeProviderProxy == null) { + volumeProviderProxy = OpenStackVolumeProviderProxy.getFromStorageDomainId(storageDomainId); + } + return volumeProviderProxy; + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/ProviderProxyFactory.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/ProviderProxyFactory.java index 57df428..f2bbaa0 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/ProviderProxyFactory.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/ProviderProxyFactory.java @@ -3,7 +3,9 @@ import org.ovirt.engine.core.bll.host.provider.foreman.ForemanHostProviderProxy; import org.ovirt.engine.core.bll.provider.network.openstack.OpenstackNetworkProviderProxy; import org.ovirt.engine.core.bll.provider.storage.OpenStackImageProviderProxy; +import org.ovirt.engine.core.bll.provider.storage.OpenStackVolumeProviderProxy; import org.ovirt.engine.core.common.businessentities.OpenStackImageProviderProperties; +import org.ovirt.engine.core.common.businessentities.OpenStackVolumeProviderProperties; import org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties; import org.ovirt.engine.core.common.businessentities.Provider; @@ -37,6 +39,9 @@ case OPENSTACK_IMAGE: return (P) new OpenStackImageProviderProxy((Provider<OpenStackImageProviderProperties>) provider); + case OPENSTACK_VOLUME: + return (P) new OpenStackVolumeProviderProxy((Provider<OpenStackVolumeProviderProperties>) provider); + default: return null; } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/AbstractOpenStackStorageProviderProxy.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/AbstractOpenStackStorageProviderProxy.java new file mode 100644 index 0000000..7308066 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/AbstractOpenStackStorageProviderProxy.java @@ -0,0 +1,133 @@ +package org.ovirt.engine.core.bll.provider.storage; + +import com.woorea.openstack.base.client.HttpMethod; +import com.woorea.openstack.base.client.OpenStackClient; +import com.woorea.openstack.base.client.OpenStackRequest; +import com.woorea.openstack.base.client.OpenStackTokenProvider; +import com.woorea.openstack.keystone.model.Access; +import com.woorea.openstack.keystone.utils.KeystoneTokenProvider; +import org.ovirt.engine.core.bll.provider.ProviderProxy; +import org.ovirt.engine.core.common.businessentities.Provider; +import org.ovirt.engine.core.common.businessentities.StorageDomain; +import org.ovirt.engine.core.common.businessentities.StorageDomainDynamic; +import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; +import org.ovirt.engine.core.common.businessentities.StorageDomainType; +import org.ovirt.engine.core.common.businessentities.StorageFormatType; +import org.ovirt.engine.core.common.businessentities.StorageType; +import org.ovirt.engine.core.common.businessentities.TenantProviderProperties; +import org.ovirt.engine.core.common.config.Config; +import org.ovirt.engine.core.common.config.ConfigValues; +import org.ovirt.engine.core.common.errors.VdcBLLException; +import org.ovirt.engine.core.common.errors.VdcBllErrors; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; + +import java.security.cert.Certificate; +import java.util.List; + +public abstract class AbstractOpenStackStorageProviderProxy<C extends OpenStackClient, T extends TenantProviderProperties> implements ProviderProxy { + + protected C client; + + protected Provider<T> provider; + + protected OpenStackTokenProvider tokenProvider; + + protected KeystoneTokenProvider keystoneTokenProvider; + + @Override + public void testConnection() { + try { + getClient().execute(new OpenStackRequest<>(getClient(), HttpMethod.GET, "", null, null)); + } catch (RuntimeException e) { + throw new VdcBLLException(VdcBllErrors.PROVIDER_FAILURE, e); + } + } + + protected abstract C getClient(); + + protected Provider getProvider() { + return provider; + } + + protected OpenStackTokenProvider getTokenProvider() { + if (tokenProvider == null && getProvider().isRequiringAuthentication()) { + String tenantName = provider.getAdditionalProperties().getTenantName(); + tokenProvider = getKeystoneTokenProvider().getProviderByTenant(tenantName); + } + return tokenProvider; + } + + protected KeystoneTokenProvider getKeystoneTokenProvider() { + if (keystoneTokenProvider == null) { + String tenantName = provider.getAdditionalProperties().getTenantName(); + keystoneTokenProvider = new KeystoneTokenProvider(Config.<String> getValue(ConfigValues.KeystoneAuthUrl), + getProvider().getUsername(), getProvider().getPassword()); + } + return keystoneTokenProvider; + } + + protected Access getAccess() { + String tenantName = provider.getAdditionalProperties().getTenantName(); + return getKeystoneTokenProvider().getAccessByTenant(tenantName); + } + + protected String getTenantId() { + return getAccess().getToken().getTenant().getId(); + } + + @Override + public List<? extends Certificate> getCertificateChain() { + return null; + } + + protected void addStorageDomain(StorageType storageType, StorageDomainType storageDomainType) { + // Storage domain static + StorageDomainStatic domainStaticEntry = new StorageDomainStatic(); + domainStaticEntry.setId(Guid.newGuid()); + domainStaticEntry.setStorage(provider.getId().toString()); + domainStaticEntry.setStorageName(provider.getName()); + domainStaticEntry.setDescription(provider.getDescription()); + domainStaticEntry.setStorageFormat(StorageFormatType.V1); + domainStaticEntry.setStorageType(storageType); + domainStaticEntry.setStorageDomainType(storageDomainType); + getDbFacade().getStorageDomainStaticDao().save(domainStaticEntry); + // Storage domain dynamic + StorageDomainDynamic domainDynamicEntry = new StorageDomainDynamic(); + domainDynamicEntry.setId(domainStaticEntry.getId()); + domainDynamicEntry.setAvailableDiskSize(0); + domainDynamicEntry.setUsedDiskSize(0); + getDbFacade().getStorageDomainDynamicDao().save(domainDynamicEntry); + } + + @Override + public void onModification() { + List<StorageDomain> storageDomains = + getDbFacade().getStorageDomainDao().getAllByConnectionId(provider.getId()); + + // updating storage domain information + for (StorageDomain storageDomainEntry : storageDomains) { + StorageDomainStatic domainStaticEntry = + getDbFacade().getStorageDomainStaticDao().get(storageDomainEntry.getId()); + domainStaticEntry.setStorageName(provider.getName()); + domainStaticEntry.setDescription(provider.getDescription()); + getDbFacade().getStorageDomainStaticDao().update(domainStaticEntry); + } + } + + @Override + public void onRemoval() { + List<StorageDomain> storageDomains = getDbFacade() + .getStorageDomainDao().getAllByConnectionId(provider.getId()); + + // removing the static and dynamic storage domain entries + for (StorageDomain storageDomainEntry : storageDomains) { + getDbFacade().getStorageDomainDynamicDao().remove(storageDomainEntry.getId()); + getDbFacade().getStorageDomainStaticDao().remove(storageDomainEntry.getId()); + } + } + + protected static DbFacade getDbFacade() { + return DbFacade.getInstance(); + } +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackImageProviderProxy.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackImageProviderProxy.java index fcc0548..024b3a0 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackImageProviderProxy.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackImageProviderProxy.java @@ -8,38 +8,26 @@ import java.util.List; import java.util.Map; -import com.woorea.openstack.base.client.HttpMethod; import com.woorea.openstack.base.client.OpenStackRequest; -import com.woorea.openstack.base.client.OpenStackTokenProvider; import com.woorea.openstack.glance.Glance; import com.woorea.openstack.glance.model.Image; import com.woorea.openstack.glance.model.ImageDownload; import com.woorea.openstack.glance.model.Images; -import com.woorea.openstack.keystone.utils.KeystoneTokenProvider; -import org.ovirt.engine.core.bll.provider.ProviderProxy; import org.ovirt.engine.core.bll.provider.ProviderProxyFactory; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.ImageFileType; import org.ovirt.engine.core.common.businessentities.OpenStackImageProviderProperties; import org.ovirt.engine.core.common.businessentities.Provider; import org.ovirt.engine.core.common.businessentities.RepoImage; -import org.ovirt.engine.core.common.businessentities.StorageDomain; -import org.ovirt.engine.core.common.businessentities.StorageDomainDynamic; import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; import org.ovirt.engine.core.common.businessentities.StorageDomainType; -import org.ovirt.engine.core.common.businessentities.StorageFormatType; import org.ovirt.engine.core.common.businessentities.StorageType; import org.ovirt.engine.core.common.businessentities.VolumeFormat; -import org.ovirt.engine.core.common.config.Config; -import org.ovirt.engine.core.common.config.ConfigValues; -import org.ovirt.engine.core.common.errors.VdcBLLException; -import org.ovirt.engine.core.common.errors.VdcBllErrors; import org.ovirt.engine.core.compat.Guid; -import org.ovirt.engine.core.dal.dbbroker.DbFacade; -public class OpenStackImageProviderProxy implements ProviderProxy { +public class OpenStackImageProviderProxy extends AbstractOpenStackStorageProviderProxy<Glance, OpenStackImageProviderProperties> { enum GlanceImageFormat { RAW("raw"), @@ -79,23 +67,8 @@ private static final int QCOW2_SIZE_OFFSET = 24; - private Provider<OpenStackImageProviderProperties> provider; - - private OpenStackTokenProvider tokenProvider; - - private Glance client; - public OpenStackImageProviderProxy(Provider<OpenStackImageProviderProperties> provider) { this.provider = provider; - } - - @Override - public void testConnection() { - try { - getClient().execute(new OpenStackRequest<>(getClient(), HttpMethod.GET, "", null, null)); - } catch (RuntimeException e) { - throw new VdcBLLException(VdcBllErrors.PROVIDER_FAILURE, e); - } } @Override @@ -103,59 +76,9 @@ return null; } - private static DbFacade getDbFacade() { - return DbFacade.getInstance(); - } - @Override public void onAddition() { - // Storage domain static - StorageDomainStatic domainStaticEntry = new StorageDomainStatic(); - domainStaticEntry.setId(Guid.newGuid()); - domainStaticEntry.setStorage(provider.getId().toString()); - domainStaticEntry.setStorageName(provider.getName()); - domainStaticEntry.setDescription(provider.getDescription()); - domainStaticEntry.setStorageFormat(StorageFormatType.V1); - domainStaticEntry.setStorageType(StorageType.GLANCE); - domainStaticEntry.setStorageDomainType(StorageDomainType.Image); - getDbFacade().getStorageDomainStaticDao().save(domainStaticEntry); - // Storage domain dynamic - StorageDomainDynamic domainDynamicEntry = new StorageDomainDynamic(); - domainDynamicEntry.setId(domainStaticEntry.getId()); - domainDynamicEntry.setAvailableDiskSize(0); - domainDynamicEntry.setUsedDiskSize(0); - getDbFacade().getStorageDomainDynamicDao().save(domainDynamicEntry); - } - - @Override - public void onModification() { - List<StorageDomain> storageDomains = - getDbFacade().getStorageDomainDao().getAllByConnectionId(provider.getId()); - - // updating storage domain information - for (StorageDomain storageDomainEntry : storageDomains) { - StorageDomainStatic domainStaticEntry = - getDbFacade().getStorageDomainStaticDao().get(storageDomainEntry.getId()); - domainStaticEntry.setStorageName(provider.getName()); - domainStaticEntry.setDescription(provider.getDescription()); - getDbFacade().getStorageDomainStaticDao().update(domainStaticEntry); - } - } - - @Override - public void onRemoval() { - List<StorageDomain> storageDomains = getDbFacade() - .getStorageDomainDao().getAllByConnectionId(provider.getId()); - - // removing the static and dynamic storage domain entries - for (StorageDomain storageDomainEntry : storageDomains) { - getDbFacade().getStorageDomainDynamicDao().remove(storageDomainEntry.getId()); - getDbFacade().getStorageDomainStaticDao().remove(storageDomainEntry.getId()); - } - } - - private Provider getProvider() { - return provider; + addStorageDomain(StorageType.GLANCE, StorageDomainType.Image); } public static OpenStackImageProviderProxy getFromStorageDomainId(Guid storageDomainId) { @@ -167,16 +90,7 @@ return null; } - private OpenStackTokenProvider getTokenProvider() { - if (tokenProvider == null && getProvider().isRequiringAuthentication()) { - String tenantName = provider.getAdditionalProperties().getTenantName(); - tokenProvider = new KeystoneTokenProvider(Config.<String> getValue(ConfigValues.KeystoneAuthUrl), - getProvider().getUsername(), getProvider().getPassword()).getProviderByTenant(tenantName); - } - return tokenProvider; - } - - private Glance getClient() { + protected Glance getClient() { if (client == null) { client = new Glance(getProvider().getUrl() + API_VERSION); client.setTokenProvider(getTokenProvider()); 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 new file mode 100644 index 0000000..59b37dd --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/storage/OpenStackVolumeProviderProxy.java @@ -0,0 +1,106 @@ +package org.ovirt.engine.core.bll.provider.storage; + +import java.security.cert.Certificate; +import java.util.ArrayList; +import java.util.List; + +import com.woorea.openstack.base.client.OpenStackRequest; +import com.woorea.openstack.cinder.model.ConnectionInfo; +import com.woorea.openstack.cinder.model.Volume; +import com.woorea.openstack.cinder.model.VolumeForCreate; +import com.woorea.openstack.cinder.model.Volumes; +import org.ovirt.engine.core.bll.provider.ProviderProxyFactory; +import org.ovirt.engine.core.common.businessentities.CinderDisk; +import org.ovirt.engine.core.common.businessentities.ImageFileType; +import org.ovirt.engine.core.common.businessentities.OpenStackVolumeProviderProperties; +import org.ovirt.engine.core.common.businessentities.Provider; +import org.ovirt.engine.core.common.businessentities.RepoImage; +import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; +import org.ovirt.engine.core.common.businessentities.StorageDomainType; +import org.ovirt.engine.core.common.businessentities.StorageType; + +import com.woorea.openstack.cinder.Cinder; +import org.ovirt.engine.core.compat.Guid; + + +public class OpenStackVolumeProviderProxy extends AbstractOpenStackStorageProviderProxy<Cinder, OpenStackVolumeProviderProperties> { + + private static final String API_VERSION = "/v2/"; + + public OpenStackVolumeProviderProxy(Provider<OpenStackVolumeProviderProperties> provider) { + this.provider = provider; + } + + @Override + public List<? extends Certificate> getCertificateChain() { + return null; + } + + @Override + public void onAddition() { + addStorageDomain(StorageType.CINDER, StorageDomainType.Volume); + } + + protected Cinder getClient() { + return getClient(""); + } + + protected Cinder getClient(String tenantId) { + if (client == null) { + client = new Cinder(getProvider().getUrl().concat(API_VERSION).concat(tenantId)); + client.setTokenProvider(getTokenProvider()); + } + return client; + } + + public List<RepoImage> getAllVolumesAsRepoImages() { + ArrayList<RepoImage> repoImages = new ArrayList<>(); + OpenStackRequest<Volumes> listRequest = getClient(getTenantId()).volumes().list(true); + + Volumes volumes = listRequest.execute(); + for (Volume volume : volumes) { + RepoImage repoImage = volumeToDiskImage(volume); + repoImages.add(repoImage); + } + + return repoImages; + } + + public String createVolumeFromDiskImage(CinderDisk cinderDisk) { + VolumeForCreate cinderVolume = new VolumeForCreate(); + + cinderVolume.setName(cinderDisk.getDiskAlias()); + cinderVolume.setSize((int) (cinderDisk.getSize() / (1024 * 1024 * 1024))); + + Volume retCinderVolume = getClient(getTenantId()).volumes().create(cinderVolume).execute(); + + return retCinderVolume.getId(); + } + + public ConnectionInfo initializeConnectionForVolume(String volumeId) { + return getClient(getTenantId()).volumes().initializeConnection(volumeId).execute(); + } + + public void deleteVolume(String volumeId) { + getClient(getTenantId()).volumes().delete(volumeId).execute(); + } + + private RepoImage volumeToDiskImage(Volume volume) { + RepoImage repoImage = new RepoImage(); + repoImage.setSize(volume.getSize() * (long) 1024 * 1024 * 1024); + repoImage.setRepoImageName(volume.getName()); + repoImage.setRepoImageId(volume.getId()); + repoImage.setFileType(ImageFileType.Disk); + repoImage.setDateCreated(null); + return repoImage; + } + + public static OpenStackVolumeProviderProxy getFromStorageDomainId(Guid storageDomainId) { + StorageDomainStatic storageDomainStatic = getDbFacade().getStorageDomainStaticDao().get(storageDomainId); + if (storageDomainStatic != null) { + Provider provider = getDbFacade().getProviderDao().get(new Guid(storageDomainStatic.getStorage())); + return ProviderProxyFactory.getInstance().create(provider); + } + return null; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderConnectionInfo.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderConnectionInfo.java new file mode 100644 index 0000000..0004891 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderConnectionInfo.java @@ -0,0 +1,149 @@ +package org.ovirt.engine.core.common.businessentities; + +import java.io.Serializable; +import java.util.List; + +public class CinderConnectionInfo implements Serializable { + + public static final class CinderConnectionData implements Serializable { + private String name; + private String secretType; + private String secretUuid; + private String qosSpecs; + private Boolean authEnabled; + private String authUsername; + private String accessMode; + private List<String> hosts; + private List<String> ports; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSecretType() { + return secretType; + } + + public void setSecretType(String secretType) { + this.secretType = secretType; + } + + public String getSecretUuid() { + return secretUuid; + } + + public void setSecretUuid(String secretUuid) { + this.secretUuid = secretUuid; + } + + public String getQosSpecs() { + return qosSpecs; + } + + public void setQosSpecs(String qosSpecs) { + this.qosSpecs = qosSpecs; + } + + public Boolean getAuthEnabled() { + return authEnabled; + } + + public void setAuthEnabled(Boolean authEnabled) { + this.authEnabled = authEnabled; + } + + public String getAuthUsername() { + return authUsername; + } + + public void setAuthUsername(String authUsername) { + this.authUsername = authUsername; + } + + public String getAccessMode() { + return accessMode; + } + + public void setAccessMode(String accessMode) { + this.accessMode = accessMode; + } + + public List<String> getHosts() { + return hosts; + } + + public void setHosts(List<String> hosts) { + this.hosts = hosts; + } + + public List<String> getPorts() { + return ports; + } + + public void setPorts(List<String> ports) { + this.ports = ports; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ConnectionData [secretType=" + secretType + + ", name=" + name + + ", qosSpecs=" + qosSpecs + + ", authEnabled=" + authEnabled + + ", accessMode=" + accessMode + + ", authUsername=" + authUsername + + ", hosts=" + hosts + + ", ports=" + ports + "]"; + } + } + + private String driverVolumeType; + + private CinderConnectionData data; + + /** + * @return the driverVolumeType + */ + public String getDriverVolumeType() { + return driverVolumeType; + } + + /** + * @param driverVolumeType the driverVolumeType to set + */ + public void setDriverVolumeType(String driverVolumeType) { + this.driverVolumeType = driverVolumeType; + } + + /** + * @return the data + */ + public CinderConnectionData getData() { + return data; + } + + /** + * @param data the data to set + */ + public void setData(CinderConnectionData data) { + this.data = data; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ConnectionInfo [driverVolumeType=" + driverVolumeType + "," + + " data=" + data + "]"; + } + +} + diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderDisk.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderDisk.java new file mode 100644 index 0000000..b2695e8 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/CinderDisk.java @@ -0,0 +1,20 @@ +package org.ovirt.engine.core.common.businessentities; + +public class CinderDisk extends DiskImage { + + CinderConnectionInfo cinderConnectionInfo; + + public CinderConnectionInfo getCinderConnectionInfo() { + return cinderConnectionInfo; + } + + public void setCinderConnectionInfo(CinderConnectionInfo cinderConnectionInfo) { + this.cinderConnectionInfo = cinderConnectionInfo; + } + + @Override + public DiskStorageType getDiskStorageType() { + return DiskStorageType.CINDER; + } + +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/Disk.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/Disk.java index 1130f17..726363c 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/Disk.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/Disk.java @@ -147,7 +147,8 @@ public enum DiskStorageType implements Identifiable { // FIXME add ids and remove the ordinal impl of getValue IMAGE, - LUN; + LUN, + CINDER; @Override public int getValue() { diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/OpenStackVolumeProviderProperties.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/OpenStackVolumeProviderProperties.java new file mode 100644 index 0000000..dd58528 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/OpenStackVolumeProviderProperties.java @@ -0,0 +1,17 @@ +package org.ovirt.engine.core.common.businessentities; + +public class OpenStackVolumeProviderProperties extends TenantProviderProperties { + + private static final long serialVersionUID = -3887979451360188295L; + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("OpenStackVolumeProviderProperties [pluginType=") + .append(", tenantName=") + .append(getTenantName()) + .append("]"); + return builder.toString(); + } + +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ProviderType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ProviderType.java index 795c107..2891325 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ProviderType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ProviderType.java @@ -11,7 +11,8 @@ public enum ProviderType implements Identifiable { OPENSTACK_NETWORK(0, VdcObjectType.Network), FOREMAN(1, VdcObjectType.VDS), - OPENSTACK_IMAGE(2, VdcObjectType.Storage); + OPENSTACK_IMAGE(2, VdcObjectType.Storage), + OPENSTACK_VOLUME(3, VdcObjectType.Storage); private int value; private Set<VdcObjectType> providedTypes; diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageDomainType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageDomainType.java index e52848f..abfadbe 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageDomainType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageDomainType.java @@ -7,6 +7,7 @@ ISO, ImportExport, Image, + Volume, Unknown; public int getValue() { diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageType.java index 0f42ee3..f7ff1ba 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/StorageType.java @@ -11,7 +11,8 @@ LOCALFS(4, Subtype.FILE), POSIXFS(6, Subtype.FILE), GLUSTERFS(7, Subtype.FILE), - GLANCE(8, Subtype.FILE); + GLANCE(8, Subtype.FILE), + CINDER(9, Subtype.NONE); public enum Subtype { NONE, FILE, BLOCK } @@ -59,4 +60,8 @@ public boolean isLocal() { return this == LOCALFS; } + + public boolean isOpenStackDomain() { + return this == GLANCE || this == CINDER; + } } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDiskDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDiskDaoDbFacadeImpl.java index 3d87e67..4e0b169 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDiskDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/BaseDiskDaoDbFacadeImpl.java @@ -1,6 +1,7 @@ package org.ovirt.engine.core.dao; import org.ovirt.engine.core.common.businessentities.BaseDisk; +import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.utils.EnumUtils; import org.ovirt.engine.core.compat.Guid; import org.springframework.jdbc.core.RowMapper; @@ -29,7 +30,8 @@ .addValue("boot", entity.isBoot()) .addValue("sgio", entity.getSgio()) .addValue("alignment", entity.getAlignment()) - .addValue("last_alignment_scan", entity.getLastAlignmentScan()); + .addValue("last_alignment_scan", entity.getLastAlignmentScan()) + .addValue("disk_storage_type", ((Disk) entity).getDiskStorageType()); } @Override diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskDaoDbFacadeImpl.java index 74567a1..aa16360 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskDaoDbFacadeImpl.java @@ -2,14 +2,23 @@ import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.ovirt.engine.core.common.businessentities.CinderDisk; import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType; import org.ovirt.engine.core.common.businessentities.DiskImage; +import org.ovirt.engine.core.common.businessentities.ImageStatus; import org.ovirt.engine.core.common.businessentities.LunDisk; +import org.ovirt.engine.core.common.businessentities.StorageType; +import org.ovirt.engine.core.common.businessentities.VolumeFormat; +import org.ovirt.engine.core.common.businessentities.VolumeType; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacadeUtils; import org.ovirt.engine.core.dao.DiskImageDAODbFacadeImpl.DiskImageRowMapper; +import org.ovirt.engine.core.utils.GuidUtils; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @@ -123,6 +132,10 @@ case LUN: disk = LunDiskRowMapper.instance.mapRow(rs, rowNum); break; + + case CINDER: + disk = CinderDiskRowMapper.instance.mapRow(rs, rowNum); + break; } return disk; @@ -183,4 +196,42 @@ return new LunDisk(); } } + + private static class CinderDiskRowMapper extends AbstractDiskRowMapper<CinderDisk> { + + public static CinderDiskRowMapper instance = new CinderDiskRowMapper(); + + private CinderDiskRowMapper() { + } + + @Override + public CinderDisk mapRow(ResultSet rs, int rowNum) throws SQLException { + CinderDisk disk = super.mapRow(rs, rowNum); + mapEntity(rs, disk); + return disk; + } + + protected void mapEntity(ResultSet rs, CinderDisk entity) throws SQLException { + entity.setCreationDate(DbFacadeUtils.fromDate(rs.getTimestamp("creation_date"))); + entity.setDescription(rs.getString("description")); + entity.setImageId(getGuidDefaultEmpty(rs, "image_guid")); + entity.setSize(rs.getLong("size")); + entity.setImageStatus(ImageStatus.forValue(rs.getInt("imageStatus"))); + entity.setLastModified(DbFacadeUtils.fromDate(rs.getTimestamp("lastModified"))); + entity.setStorageIds(GuidUtils.getGuidListFromString(rs.getString("storage_id"))); + entity.setStorageTypes(new ArrayList<>(Arrays.asList(StorageType.CINDER))); + entity.setStoragesNames(split(rs.getString("storage_name"))); + entity.setVmSnapshotId(getGuid(rs, "vm_snapshot_id")); + entity.setVolumeType(VolumeType.forValue(rs.getInt("volume_type"))); + entity.setvolumeFormat(VolumeFormat.forValue(rs.getInt("volume_format"))); + entity.setId(getGuidDefaultEmpty(rs, "image_group_id")); + entity.setStoragePath(split(rs.getString("storage_path"))); + entity.setBoot(rs.getBoolean("boot")); + } + + @Override + protected CinderDisk createDiskEntity() { + return new CinderDisk(); + } + } } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/provider/ProviderDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/provider/ProviderDaoDbFacadeImpl.java index 1e16224..9952f47 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/provider/ProviderDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/provider/ProviderDaoDbFacadeImpl.java @@ -6,6 +6,7 @@ import java.util.List; import org.ovirt.engine.core.common.businessentities.OpenStackImageProviderProperties; +import org.ovirt.engine.core.common.businessentities.OpenStackVolumeProviderProperties; import org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties; import org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties.AgentConfiguration; import org.ovirt.engine.core.common.businessentities.Provider; @@ -45,6 +46,11 @@ OpenStackImageProviderProperties imageProperties = (OpenStackImageProviderProperties) entity.getAdditionalProperties(); tenantName = imageProperties.getTenantName(); + break; + case OPENSTACK_VOLUME: + OpenStackVolumeProviderProperties volumeProperties = + (OpenStackVolumeProviderProperties) entity.getAdditionalProperties(); + tenantName = volumeProperties.getTenantName(); break; default: break; @@ -127,6 +133,10 @@ OpenStackImageProviderProperties imageProperties = new OpenStackImageProviderProperties(); imageProperties.setTenantName(rs.getString("tenant_name")); return imageProperties; + case OPENSTACK_VOLUME: + OpenStackVolumeProviderProperties volumeProperties = new OpenStackVolumeProviderProperties(); + volumeProperties.setTenantName(rs.getString("tenant_name")); + return volumeProperties; default: return null; } diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java index 9ee2f30..d8f6631 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java @@ -329,6 +329,12 @@ public static final String Fdc = "fdc"; public static final String Guid = "GUID"; public static final String Disk = "disk"; + public static final String VolType = "volType"; + public static final String VolPort = "volPort"; + public static final String VolTransport = "volTransport"; + public static final String VolfileServer = "volfileServer"; + public static final String VolumeInfo = "volumeInfo"; + public static final String Tcp = "tcp"; // iotune public static final String Iotune = "ioTune"; public static final String TotalBytesSec = "total_bytes_sec"; diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilder.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilder.java index f194356..6f5da1e 100644 --- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilder.java +++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VmInfoBuilder.java @@ -12,6 +12,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.FeatureSupported; +import org.ovirt.engine.core.common.businessentities.CinderDisk; import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType; import org.ovirt.engine.core.common.businessentities.DiskImage; @@ -316,32 +317,49 @@ struct.put(VdsProperties.Index, 0); } addAddress(vmDevice, struct); - if (disk.getDiskStorageType() == DiskStorageType.IMAGE) { - DiskImage diskImage = (DiskImage) disk; - struct.put(VdsProperties.PoolId, diskImage.getStoragePoolId().toString()); - struct.put(VdsProperties.DomainId, diskImage.getStorageIds().get(0).toString()); - struct.put(VdsProperties.ImageId, diskImage.getId().toString()); - struct.put(VdsProperties.VolumeId, diskImage.getImageId().toString()); - struct.put(VdsProperties.Format, diskImage.getVolumeFormat().toString() - .toLowerCase()); - struct.put(VdsProperties.PropagateErrors, disk.getPropagateErrors().toString() - .toLowerCase()); - if (FeatureSupported.storageQoS(vm.getVdsGroupCompatibilityVersion())) { - Map<String, Integer> ioTune = - buildIoTune(diskImage, diskProfileStorageQosMap, storageQosIoTuneMap); - if (ioTune != null) { - if (vmDevice.getSpecParams() == null) { - vmDevice.setSpecParams(new HashMap<String, Object>()); + switch (disk.getDiskStorageType()) { + case IMAGE: + DiskImage diskImage = (DiskImage) disk; + struct.put(VdsProperties.PoolId, diskImage.getStoragePoolId().toString()); + struct.put(VdsProperties.DomainId, diskImage.getStorageIds().get(0).toString()); + struct.put(VdsProperties.ImageId, diskImage.getId().toString()); + struct.put(VdsProperties.VolumeId, diskImage.getImageId().toString()); + struct.put(VdsProperties.Format, diskImage.getVolumeFormat().toString() + .toLowerCase()); + struct.put(VdsProperties.PropagateErrors, disk.getPropagateErrors().toString() + .toLowerCase()); + if (FeatureSupported.storageQoS(vm.getVdsGroupCompatibilityVersion())) { + Map<String, Integer> ioTune = + buildIoTune(diskImage, diskProfileStorageQosMap, storageQosIoTuneMap); + if (ioTune != null) { + if (vmDevice.getSpecParams() == null) { + vmDevice.setSpecParams(new HashMap<String, Object>()); + } + vmDevice.getSpecParams().put(VdsProperties.Iotune, ioTune); } - vmDevice.getSpecParams().put(VdsProperties.Iotune, ioTune); } - } - } else { - LunDisk lunDisk = (LunDisk) disk; - struct.put(VdsProperties.Guid, lunDisk.getLun().getLUN_id()); - struct.put(VdsProperties.Format, VolumeFormat.RAW.toString().toLowerCase()); - struct.put(VdsProperties.PropagateErrors, PropagateErrors.Off.toString() - .toLowerCase()); + break; + case LUN: + LunDisk lunDisk = (LunDisk) disk; + struct.put(VdsProperties.Guid, lunDisk.getLun().getLUN_id()); + struct.put(VdsProperties.Format, VolumeFormat.RAW.toString().toLowerCase()); + struct.put(VdsProperties.PropagateErrors, PropagateErrors.Off.toString().toLowerCase()); + break; + case CINDER: + CinderDisk cinderDisk = (CinderDisk) disk; + Map<String, Object> volumeInfo = new HashMap<>(); + volumeInfo.put(VdsProperties.VolType, VdsProperties.NETWORK); + volumeInfo.put(VdsProperties.Path, cinderDisk.getCinderConnectionInfo().getData().getName()); + volumeInfo.put(VdsProperties.Protocol, cinderDisk.getCinderConnectionInfo().getDriverVolumeType()); + volumeInfo.put(VdsProperties.VolfileServer, cinderDisk.getCinderConnectionInfo().getData().getHosts().get(0)); + volumeInfo.put(VdsProperties.VolPort, cinderDisk.getCinderConnectionInfo().getData().getPorts().get(0)); + volumeInfo.put(VdsProperties.VolTransport, VdsProperties.Tcp); + + struct.put(VdsProperties.VolumeInfo, volumeInfo); + struct.put(VdsProperties.Path, cinderDisk.getCinderConnectionInfo().getData().getName()); + struct.put(VdsProperties.Format, VolumeFormat.RAW.toString().toLowerCase()); + struct.put(VdsProperties.PropagateErrors, PropagateErrors.Off.toString().toLowerCase()); + break; } addBootOrder(vmDevice, struct); diff --git a/packaging/dbscripts/base_disks_sp.sql b/packaging/dbscripts/base_disks_sp.sql index 0eb21a6..2b97f02 100644 --- a/packaging/dbscripts/base_disks_sp.sql +++ b/packaging/dbscripts/base_disks_sp.sql @@ -18,7 +18,8 @@ v_boot BOOLEAN, v_sgio INTEGER, v_alignment SMALLINT, - v_last_alignment_scan TIMESTAMP WITH TIME ZONE) + v_last_alignment_scan TIMESTAMP WITH TIME ZONE, + v_disk_storage_type SMALLINT) RETURNS VOID AS $procedure$ BEGIN @@ -33,7 +34,8 @@ boot, sgio, alignment, - last_alignment_scan) + last_alignment_scan, + disk_storage_type) VALUES( v_disk_id, v_disk_interface, @@ -45,7 +47,8 @@ v_boot, v_sgio, v_alignment, - v_last_alignment_scan); + v_last_alignment_scan, + v_disk_storage_type); END; $procedure$ LANGUAGE plpgsql; @@ -64,7 +67,8 @@ v_boot BOOLEAN, v_sgio INTEGER, v_alignment SMALLINT, - v_last_alignment_scan TIMESTAMP WITH TIME ZONE) + v_last_alignment_scan TIMESTAMP WITH TIME ZONE, + v_disk_storage_type SMALLINT) RETURNS VOID AS $procedure$ BEGIN @@ -78,7 +82,8 @@ boot = v_boot, sgio = v_sgio, alignment = v_alignment, - last_alignment_scan = v_last_alignment_scan + last_alignment_scan = v_last_alignment_scan, + disk_storage_type = v_disk_storage_type WHERE disk_id = v_disk_id; END; $procedure$ LANGUAGE plpgsql; diff --git a/packaging/dbscripts/create_views.sql b/packaging/dbscripts/create_views.sql index 3d31550..1786cd9 100644 --- a/packaging/dbscripts/create_views.sql +++ b/packaging/dbscripts/create_views.sql @@ -173,11 +173,11 @@ bd.boot, bd.sgio, bd.alignment, - bd.last_alignment_scan + bd.last_alignment_scan, + bd.disk_storage_type FROM ( - SELECT 0 AS disk_storage_type, - storage_for_image_view.storage_id as storage_id, -- Storage fields + SELECT storage_for_image_view.storage_id as storage_id, -- Storage fields storage_for_image_view.storage_path as storage_path, storage_for_image_view.storage_name as storage_name, storage_for_image_view.storage_type as storage_type, @@ -222,8 +222,7 @@ FROM images_storage_domain_view INNER JOIN storage_for_image_view ON images_storage_domain_view.image_guid = storage_for_image_view.image_id UNION - SELECT 1 AS disk_storage_type, - null AS storage_id, -- Storage domain fields + SELECT null AS storage_id, -- Storage domain fields null AS storage_path, null AS storage_name, null AS storage_type, diff --git a/packaging/dbscripts/upgrade/03_06_0520_add_disk_storage_type_column_to_base_disks.sql b/packaging/dbscripts/upgrade/03_06_0520_add_disk_storage_type_column_to_base_disks.sql new file mode 100644 index 0000000..5a27bad --- /dev/null +++ b/packaging/dbscripts/upgrade/03_06_0520_add_disk_storage_type_column_to_base_disks.sql @@ -0,0 +1,15 @@ +select fn_db_add_column('base_disks', 'disk_storage_type', 'SMALLINT DEFAULT NULL'); + +UPDATE base_disks SET disk_storage_type = +CASE + WHEN EXISTS ( + SELECT * + FROM images + WHERE images.image_group_id = base_disks.disk_id) + THEN 0 + WHEN EXISTS ( + SELECT * + FROM disk_lun_map + WHERE disk_lun_map.disk_id = base_disks.disk_id) + THEN 1 +END; \ No newline at end of file -- To view, visit http://gerrit.ovirt.org/35358 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Idcb7955f374d58efbdaddb09bc48d9d4baa03120 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Daniel Erez <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
