diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42210to42300.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42210to42300.java index 393f20399503..0b08c376ae40 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42210to42300.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42210to42300.java @@ -21,12 +21,23 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; +import java.util.UUID; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + +import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate { + private PrimaryDataStoreDao storageDao; + @Override public String[] getUpgradableVersionRange() { return new String[]{"4.22.1.0", "4.23.0.0"}; @@ -51,6 +62,56 @@ public InputStream[] getPrepareScripts() { @Override public void performDataMigration(Connection conn) { unhideJsInterpretationEnabled(conn); + normalizeStorPoolPrimaryStorageUuids(); + } + + protected PrimaryDataStoreDao getStorageDao() { + if (storageDao == null) { + storageDao = new PrimaryDataStoreDaoImpl(); + } + return storageDao; + } + + /** + * StorPool primary storage used {@code templateName + ";" + uuid} as {@code storage_pool.uuid}. + * Normalize to a plain UUID form so API and validation treat {@code id} like other pools. + * Template name remains in {@code storage_pool_details} ({@code SP_TEMPLATE}). + */ + protected void normalizeStorPoolPrimaryStorageUuids() { + SearchBuilder sb = getStorageDao().createSearchBuilder(); + sb.and("poolType", sb.entity().getPoolType(), SearchCriteria.Op.EQ); + sb.and("uuid", sb.entity().getUuid(), SearchCriteria.Op.LIKE); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("poolType", StoragePoolType.StorPool); + sc.setParameters("uuid", "%;%"); + List pools = getStorageDao().search(sc, null); + int updated = 0; + for (StoragePoolVO pool : pools) { + final String templatePrefixedPoolUuid = pool.getUuid(); + if (templatePrefixedPoolUuid == null) { + continue; + } + final String[] parts = templatePrefixedPoolUuid.split(";"); + if (parts.length < 2) { + continue; + } + final String realUuid = parts[1].trim(); + try { + UUID.fromString(realUuid); + } catch (IllegalArgumentException e) { + logger.warn( + "Skipping StorPool storage pool id [{}]: value after ';' is not a valid UUID: [{}]", + pool.getId(), realUuid); + continue; + } + pool.setUuid(realUuid); + getStorageDao().update(pool.getId(), pool); + updated++; + } + if (updated > 0) { + logger.info("Normalized {} StorPool primary storage pool UUID(s) to plain UUID form.", updated); + } } protected void unhideJsInterpretationEnabled(Connection conn) { diff --git a/plugins/storage/volume/storpool/src/main/java/com/cloud/agent/api/storage/StorPoolModifyStoragePoolCommand.java b/plugins/storage/volume/storpool/src/main/java/com/cloud/agent/api/storage/StorPoolModifyStoragePoolCommand.java index a72a4620de17..8d428aa653ca 100644 --- a/plugins/storage/volume/storpool/src/main/java/com/cloud/agent/api/storage/StorPoolModifyStoragePoolCommand.java +++ b/plugins/storage/volume/storpool/src/main/java/com/cloud/agent/api/storage/StorPoolModifyStoragePoolCommand.java @@ -22,11 +22,13 @@ import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.storage.StoragePool; +import java.util.Map; + public class StorPoolModifyStoragePoolCommand extends ModifyStoragePoolCommand { private String volumeName; - public StorPoolModifyStoragePoolCommand(boolean add, StoragePool pool, String volumeName) { - super(add, pool); + public StorPoolModifyStoragePoolCommand(boolean add, StoragePool pool, String volumeName, Map details) { + super(add, pool, details); this.volumeName = volumeName; } diff --git a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/StorPoolModifyStorageCommandWrapper.java b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/StorPoolModifyStorageCommandWrapper.java index 8d6dcff8aed7..a30185ac49a5 100644 --- a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/StorPoolModifyStorageCommandWrapper.java +++ b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/StorPoolModifyStorageCommandWrapper.java @@ -63,7 +63,7 @@ public Answer execute(final StorPoolModifyStoragePoolCommand command, final Libv final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); final KVMStoragePool storagepool = storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(), command.getPool() - .getUserInfo(), command.getPool().getType()); + .getUserInfo(), command.getPool().getType(), command.getDetails()); if (storagepool == null) { logger.debug(String.format("Did not find a storage pool [%s]", command.getPool().getId())); return new Answer(command, false, String.format("Failed to create storage pool [%s]", command.getPool().getId())); diff --git a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java index 545f7b33c5fd..8bc9f414749e 100644 --- a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java +++ b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java @@ -75,7 +75,7 @@ public static void SP_LOG(String fmt, Object... args) { public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map details, boolean isPrimaryStorage) { SP_LOG("StorPoolStorageAdaptor.createStoragePool: uuid=%s, host=%s:%d, path=%s, userInfo=%s, type=%s", uuid, host, port, path, userInfo, storagePoolType); - StorPoolStoragePool storagePool = new StorPoolStoragePool(uuid, host, port, storagePoolType, this); + StorPoolStoragePool storagePool = new StorPoolStoragePool(uuid, host, port, storagePoolType, this, details); storageUuidToStoragePool.put(uuid, storagePool); return storagePool; } @@ -409,7 +409,7 @@ public KVMPhysicalDisk createTemplateFromDirectDownloadFile(String templateFileP srcFile = new QemuImgFile(srcTemplateFilePath, srcFileFormat); - String spTemplate = destPool.getUuid().split(";")[0]; + String spTemplate = destPool.getAuthUserName(); QemuImg qemu = new QemuImg(timeout); OutputInterpreter.AllLinesParser parser = createStorPoolVolume(destPool, srcFile, qemu, spTemplate); diff --git a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStoragePool.java b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStoragePool.java index ab5dc03d3431..a12aa56dce2e 100644 --- a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStoragePool.java +++ b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStoragePool.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Map.Entry; +import org.apache.cloudstack.storage.datastore.util.StorPoolUtil; import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -53,12 +54,13 @@ public class StorPoolStoragePool implements KVMStoragePool { private String _localPath; private String storageNodeId = getStorPoolConfigParam("SP_OURID"); - public StorPoolStoragePool(String uuid, String host, int port, StoragePoolType storagePoolType, StorageAdaptor storageAdaptor) { + public StorPoolStoragePool(String uuid, String host, int port, StoragePoolType storagePoolType, StorageAdaptor storageAdaptor, Map details) { _uuid = uuid; _sourceHost = host; _sourcePort = port; _storagePoolType = storagePoolType; _storageAdaptor = storageAdaptor; + _authUsername = details.get(StorPoolUtil.SP_TEMPLATE); } @Override diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/StorPoolPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/StorPoolPrimaryDataStoreLifeCycle.java index d299fe34ffc2..565de4af85ed 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/StorPoolPrimaryDataStoreLifeCycle.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/StorPoolPrimaryDataStoreLifeCycle.java @@ -161,7 +161,7 @@ public DataStore initialize(Map dsInfos) { PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters(); parameters.setName(name); - parameters.setUuid(conn.getTemplateName() + ";" + UUID.randomUUID().toString()); + parameters.setUuid(UUID.randomUUID().toString()); parameters.setZoneId(zoneId); parameters.setProviderName(providerName); parameters.setType(StoragePoolType.StorPool); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/provider/StorPoolHostListener.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/provider/StorPoolHostListener.java index e27e15e04a82..2be416c458f4 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/provider/StorPoolHostListener.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/provider/StorPoolHostListener.java @@ -22,7 +22,9 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.inject.Inject; @@ -119,7 +121,9 @@ public boolean hostConnect(long hostId, long poolId) throws StorageConflictExcep return false; } - StorPoolModifyStoragePoolCommand cmd = new StorPoolModifyStoragePoolCommand(true, pool, volumeOnPool.getValue()); + Map details = new HashMap<>(); + details.put(StorPoolUtil.SP_TEMPLATE, conn.getTemplateName()); + StorPoolModifyStoragePoolCommand cmd = new StorPoolModifyStoragePoolCommand(true, pool, volumeOnPool.getValue(), details); final Answer answer = agentMgr.easySend(hostId, cmd); StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(pool.getId(), hostId); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolUtil.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolUtil.java index dc4dacba450a..15dd5e42dd42 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolUtil.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/datastore/util/StorPoolUtil.java @@ -336,7 +336,7 @@ private static SpConnectionDesc updateStorageAndStorageDetails(String url, long poolDetails.persist(new StoragePoolDetailVO(poolId, SP_AUTH_TOKEN, conn.getAuthToken(), false)); poolDetails.persist(new StoragePoolDetailVO(poolId, SP_TEMPLATE, conn.getTemplateName(), false)); StoragePoolVO pool = storagePool.findById(poolId); - pool.setUuid(conn.getTemplateName() + ";" + UUID.randomUUID().toString()); + pool.setUuid(UUID.randomUUID().toString()); storagePool.update(poolId, pool); StorPoolUtil.spLog( "Storage pool with id=%s and template's name=%s was updated and its connection details are hidden from UI.",