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 393f2039950..0b08c376ae4 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.Connection; 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 class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgr @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 a72a4620de1..8d428aa653c 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 @@ package com.cloud.agent.api.storage; 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 8d6dcff8aed..a30185ac49a 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 final class StorPoolModifyStorageCommandWrapper extends CommandWrapper 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 class StorPoolStorageAdaptor implements StorageAdaptor { 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 04100a3c6d3..76660dd87ea 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.List; 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 d299fe34ffc..565de4af85e 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 class StorPoolPrimaryDataStoreLifeCycle extends BasePrimaryDataStoreLifeC 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 e27e15e04a8..2be416c458f 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.Field; 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 class StorPoolHostListener implements HypervisorHostListener { 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 dc4dacba450..15dd5e42dd4 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 @@ public class StorPoolUtil { 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.",