This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 8ea9fc911d1 StoragePoolType as class (#8544)
8ea9fc911d1 is described below
commit 8ea9fc911d14faaf1d5480e71e5a1c42fbbbf18c
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Mon Feb 5 13:27:15 2024 +0530
StoragePoolType as class (#8544)
* StoragePoolType as a class
* Fix agent side StoragePoolType enum to class
* Handle StoragePoolType for StoragePoolJoinVO
* Since StoragePoolType is a class, it cannot be converted by @Enumerated
annotation.
Implemented conveter class and logic to utilize @Convert annotation.
* Fix UserVMJoinVO for StoragePoolType
* fixed missing imports
* Since StoragePoolType is a class, it cannot be converted by @Enumerated
annotation.
Implemented conveter class and logic to utilize @Convert annotation.
* Fixed equals for the enum.
* removed not needed try/catch for prepareAttribute
* Added license to the file.
* Implemented "supportsPhysicalDiskCopy" for storage adaptor.
Co-authored-by: mprokopchuk <[email protected]>
* Add javadoc to StoragePoolType class
* Add unit test for StoragePoolType comparisons
* StoragePoolType "==" and ".equals()" fix.
* Fix StoragePoolType for FiberChannelAdapter
* Fix for abstract storage adaptor set up issue
* review comments
* Pass StoragePoolType object for poolType dao attribute
---------
Co-authored-by: Marcus Sorensen <[email protected]>
Co-authored-by: mprokopchuk <[email protected]>
Co-authored-by: mprokopchuk <[email protected]>
---
api/src/main/java/com/cloud/storage/Storage.java | 133 +++++++++++++++++----
.../test/java/com/cloud/storage/StorageTest.java | 9 ++
.../agent/transport/StoragePoolTypeAdaptor.java | 53 ++++++++
.../main/java/com/cloud/serializer/GsonHelper.java | 3 +
.../com/cloud/agent/transport/RequestTest.java | 4 +-
.../datacenter/entity/api/db/EngineHostVO.java | 3 +
.../src/main/java/com/cloud/host/HostVO.java | 3 +
.../src/main/java/com/cloud/storage/VolumeVO.java | 8 +-
.../com/cloud/util/StoragePoolTypeConverter.java | 40 +++++++
.../storage/datastore/db/PrimaryDataStoreDao.java | 3 +-
.../datastore/db/PrimaryDataStoreDaoImpl.java | 3 +-
.../storage/datastore/db/StoragePoolVO.java | 10 +-
.../storage/volume/VolumeServiceTest.java | 5 +-
.../java/com/cloud/utils/db/GenericDaoBase.java | 61 +++++++++-
.../kvm/storage/FiberChannelAdapter.java | 6 +-
.../kvm/storage/IscsiAdmStorageAdaptor.java | 6 +-
.../kvm/storage/KVMStoragePoolManager.java | 59 ++++++---
.../kvm/storage/KVMStorageProcessor.java | 2 +-
.../kvm/storage/LibvirtStorageAdaptor.java | 39 +++---
.../kvm/storage/ManagedNfsStorageAdaptor.java | 3 +
.../kvm/storage/ScaleIOStorageAdaptor.java | 12 +-
.../hypervisor/kvm/storage/StorageAdaptor.java | 9 ++
.../hypervisor/kvm/storage/StorageAdaptorInfo.java | 3 -
.../kvm/storage/ScaleIOStoragePoolTest.java | 7 +-
.../com/cloud/simulator/MockStoragePoolVO.java | 6 +-
.../simulator/dao/MockStoragePoolDaoImpl.java | 2 +-
.../CloudStackPrimaryDataStoreLifeCycleImpl.java | 2 +-
.../kvm/storage/LinstorStorageAdaptor.java | 6 +-
.../kvm/storage/StorPoolStorageAdaptor.java | 6 +-
.../api/query/dao/StoragePoolJoinDaoImpl.java | 42 +++----
.../com/cloud/api/query/vo/StoragePoolJoinVO.java | 4 +-
.../java/com/cloud/api/query/vo/UserVmJoinVO.java | 4 +-
.../java/com/cloud/storage/StorageManagerImpl.java | 6 +-
.../storage/listener/StoragePoolMonitorTest.java | 2 +
34 files changed, 441 insertions(+), 123 deletions(-)
diff --git a/api/src/main/java/com/cloud/storage/Storage.java
b/api/src/main/java/com/cloud/storage/Storage.java
index 8a2ec1a8905..2ef424adcb0 100644
--- a/api/src/main/java/com/cloud/storage/Storage.java
+++ b/api/src/main/java/com/cloud/storage/Storage.java
@@ -16,10 +16,14 @@
// under the License.
package com.cloud.storage;
-import org.apache.commons.lang.NotImplementedException;
-
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.commons.lang3.StringUtils;
public class Storage {
public static enum ImageFormat {
@@ -135,37 +139,72 @@ public class Storage {
ISODISK /* Template corresponding to a iso (non root disk) present in
an OVA */
}
- public static enum StoragePoolType {
- Filesystem(false, true, true), // local directory
- NetworkFilesystem(true, true, true), // NFS
- IscsiLUN(true, false, false), // shared LUN, with a clusterfs overlay
- Iscsi(true, false, false), // for e.g., ZFS Comstar
- ISO(false, false, false), // for iso image
- LVM(false, false, false), // XenServer local LVM SR
- CLVM(true, false, false),
- RBD(true, true, false), //
http://libvirt.org/storage.html#StorageBackendRBD
- SharedMountPoint(true, false, true),
- VMFS(true, true, false), // VMware VMFS storage
- PreSetup(true, true, false), // for XenServer, Storage Pool is set up
by customers.
- EXT(false, true, false), // XenServer local EXT SR
- OCFS2(true, false, false),
- SMB(true, false, false),
- Gluster(true, false, false),
- PowerFlex(true, true, true), // Dell EMC PowerFlex/ScaleIO (formerly
VxFlexOS)
- ManagedNFS(true, false, false),
- Linstor(true, true, false),
- DatastoreCluster(true, true, false), // for VMware, to abstract pool
of clusters
- StorPool(true, true, true),
- FiberChannel(true, true, false); // Fiber Channel Pool for KVM
hypervisors is used to find the volume by WWN value
(/dev/disk/by-id/wwn-<wwnvalue>)
-
+ /**
+ * StoragePoolTypes carry some details about the format and capabilities
of a storage pool. While not necessarily a
+ * 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and
StorageAdaptor) implementations, it is
+ * often used to decide which storage plugin or storage command to call,
so it may be necessary for new storage
+ * plugins to add a StoragePoolType. This can be done by adding it below,
or by creating a new public static final
+ * instance of StoragePoolType in the plugin itself, which registers it
with the map.
+ *
+ * Note that if the StoragePoolType is for KVM and defined in plugin code
rather than below, care must be taken to
+ * ensure this is available on the agent side as well. This is best done
by defining the StoragePoolType in a common
+ * package available on both management server and agent plugin jars.
+ */
+ public static class StoragePoolType {
+ private static final Map<String, StoragePoolType> map = new
LinkedHashMap<>();
+
+ public static final StoragePoolType Filesystem = new
StoragePoolType("Filesystem", false, true, true);
+ public static final StoragePoolType NetworkFilesystem = new
StoragePoolType("NetworkFilesystem", true, true, true);
+ public static final StoragePoolType IscsiLUN = new
StoragePoolType("IscsiLUN", true, false, false);
+ public static final StoragePoolType Iscsi = new
StoragePoolType("Iscsi", true, false, false);
+ public static final StoragePoolType ISO = new StoragePoolType("ISO",
false, false, false);
+ public static final StoragePoolType LVM = new StoragePoolType("LVM",
false, false, false);
+ public static final StoragePoolType CLVM = new StoragePoolType("CLVM",
true, false, false);
+ public static final StoragePoolType RBD = new StoragePoolType("RBD",
true, true, false);
+ public static final StoragePoolType SharedMountPoint = new
StoragePoolType("SharedMountPoint", true, false, true);
+ public static final StoragePoolType VMFS = new StoragePoolType("VMFS",
true, true, false);
+ public static final StoragePoolType PreSetup = new
StoragePoolType("PreSetup", true, true, false);
+ public static final StoragePoolType EXT = new StoragePoolType("EXT",
false, true, false);
+ public static final StoragePoolType OCFS2 = new
StoragePoolType("OCFS2", true, false, false);
+ public static final StoragePoolType SMB = new StoragePoolType("SMB",
true, false, false);
+ public static final StoragePoolType Gluster = new
StoragePoolType("Gluster", true, false, false);
+ public static final StoragePoolType PowerFlex = new
StoragePoolType("PowerFlex", true, true, true);
+ public static final StoragePoolType ManagedNFS = new
StoragePoolType("ManagedNFS", true, false, false);
+ public static final StoragePoolType Linstor = new
StoragePoolType("Linstor", true, true, false);
+ public static final StoragePoolType DatastoreCluster = new
StoragePoolType("DatastoreCluster", true, true, false);
+ public static final StoragePoolType StorPool = new
StoragePoolType("StorPool", true,true,true);
+ public static final StoragePoolType FiberChannel = new
StoragePoolType("FiberChannel", true,true,false);
+
+
+ private final String name;
private final boolean shared;
private final boolean overprovisioning;
private final boolean encryption;
- StoragePoolType(boolean shared, boolean overprovisioning, boolean
encryption) {
+ /**
+ * New StoragePoolType, set the name to check with it in Dao (Note: Do
not register it into the map of pool types).
+ * @param name name of the StoragePoolType.
+ */
+ public StoragePoolType(String name) {
+ this.name = name;
+ this.shared = false;
+ this.overprovisioning = false;
+ this.encryption = false;
+ }
+
+ /**
+ * Define a new StoragePoolType, and register it into the map of pool
types known to the management server.
+ * @param name Simple unique name of the StoragePoolType.
+ * @param shared Storage pool is shared/accessible to multiple
hypervisors
+ * @param overprovisioning Storage pool supports overprovisioning
+ * @param encryption Storage pool supports encrypted volumes
+ */
+ public StoragePoolType(String name, boolean shared, boolean
overprovisioning, boolean encryption) {
+ this.name = name;
this.shared = shared;
this.overprovisioning = overprovisioning;
this.encryption = encryption;
+ addStoragePoolType(this);
}
public boolean isShared() {
@@ -177,6 +216,48 @@ public class Storage {
}
public boolean supportsEncryption() { return encryption; }
+
+ private static void addStoragePoolType(StoragePoolType
storagePoolType) {
+ map.putIfAbsent(storagePoolType.name, storagePoolType);
+ }
+
+ public static StoragePoolType[] values() {
+ return map.values().toArray(StoragePoolType[]::new).clone();
+ }
+
+ public static StoragePoolType valueOf(String name) {
+ if (StringUtils.isBlank(name)) {
+ return null;
+ }
+
+ StoragePoolType storage = map.get(name);
+ if (storage == null) {
+ throw new IllegalArgumentException("StoragePoolType '" + name
+ "' not found");
+ }
+ return storage;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ StoragePoolType that = (StoragePoolType) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
}
public static List<StoragePoolType> getNonSharedStoragePoolTypes() {
diff --git a/api/src/test/java/com/cloud/storage/StorageTest.java
b/api/src/test/java/com/cloud/storage/StorageTest.java
index 951ee9fe76a..5f40db46dea 100644
--- a/api/src/test/java/com/cloud/storage/StorageTest.java
+++ b/api/src/test/java/com/cloud/storage/StorageTest.java
@@ -74,4 +74,13 @@ public class StorageTest {
Assert.assertTrue(StoragePoolType.DatastoreCluster.supportsOverProvisioning());
Assert.assertTrue(StoragePoolType.Linstor.supportsOverProvisioning());
}
+
+ @Test
+ public void equalityTest() {
+ StoragePoolType t1 = StoragePoolType.NetworkFilesystem;
+ StoragePoolType t2 = StoragePoolType.NetworkFilesystem;
+ Assert.assertTrue(t1 == StoragePoolType.NetworkFilesystem);
+ Assert.assertTrue(t1.equals(StoragePoolType.NetworkFilesystem));
+ Assert.assertFalse(t1.equals(StoragePoolType.EXT));
+ }
}
diff --git
a/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java
b/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java
new file mode 100644
index 00000000000..635f6d06cf5
--- /dev/null
+++ b/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.transport;
+
+import com.cloud.storage.Storage.StoragePoolType;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+
+/**
+ * {@link StoragePoolType} acts as extendable set of singleton objects and
should return same result when used "=="
+ * or {@link Object#equals(Object)}.
+ * To support that, need to return existing object for a given name instead of
creating new.
+ */
+public class StoragePoolTypeAdaptor implements
JsonDeserializer<StoragePoolType>, JsonSerializer<StoragePoolType> {
+ @Override
+ public StoragePoolType deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
+ if (json instanceof JsonPrimitive && ((JsonPrimitive)
json).isString()) {
+ return StoragePoolType.valueOf(json.getAsString());
+ }
+ return null;
+ }
+
+ @Override
+ public JsonElement serialize(StoragePoolType src, Type typeOfSrc,
JsonSerializationContext context) {
+ String name = src.name();
+ if (name == null) {
+ return new JsonNull();
+ }
+ return new JsonPrimitive(name);
+ }
+}
diff --git a/core/src/main/java/com/cloud/serializer/GsonHelper.java
b/core/src/main/java/com/cloud/serializer/GsonHelper.java
index 7ac85d39317..c3653e5089c 100644
--- a/core/src/main/java/com/cloud/serializer/GsonHelper.java
+++ b/core/src/main/java/com/cloud/serializer/GsonHelper.java
@@ -37,6 +37,8 @@ import com.cloud.agent.transport.InterfaceTypeAdaptor;
import com.cloud.agent.transport.LoggingExclusionStrategy;
import com.cloud.agent.transport.Request.NwGroupsCommandTypeAdaptor;
import com.cloud.agent.transport.Request.PortConfigListTypeAdaptor;
+import com.cloud.agent.transport.StoragePoolTypeAdaptor;
+import com.cloud.storage.Storage;
import com.cloud.utils.Pair;
public class GsonHelper {
@@ -69,6 +71,7 @@ public class GsonHelper {
}.getType(), new PortConfigListTypeAdaptor());
builder.registerTypeAdapter(new TypeToken<Pair<Long, Long>>() {
}.getType(), new NwGroupsCommandTypeAdaptor());
+ builder.registerTypeAdapter(Storage.StoragePoolType.class, new
StoragePoolTypeAdaptor());
Gson gson = builder.create();
dsAdaptor.initGson(gson);
dtAdaptor.initGson(gson);
diff --git a/core/src/test/java/com/cloud/agent/transport/RequestTest.java
b/core/src/test/java/com/cloud/agent/transport/RequestTest.java
index 21766ba038f..6eada0226fc 100644
--- a/core/src/test/java/com/cloud/agent/transport/RequestTest.java
+++ b/core/src/test/java/com/cloud/agent/transport/RequestTest.java
@@ -255,7 +255,7 @@ public class RequestTest extends TestCase {
public void testGoodCommand() {
s_logger.info("Testing good Command");
String content =
"[{\"com.cloud.agent.api.GetVolumeStatsCommand\":{\"volumeUuids\":[\"dcc860ac-4a20-498f-9cb3-bab4d57aa676\"],"
- +
"\"poolType\":\"NetworkFilesystem\",\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]";
+ +
"\"poolType\":{\"name\":\"NetworkFilesystem\"},\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]";
Request sreq = new Request(Version.v2, 1L, 2L, 3L, 1L, (short)1,
content);
sreq.setSequence(1);
Command cmds[] = sreq.getCommands();
@@ -266,7 +266,7 @@ public class RequestTest extends TestCase {
public void testBadCommand() {
s_logger.info("Testing Bad Command");
String content =
"[{\"com.cloud.agent.api.SomeJunkCommand\":{\"volumeUuids\":[\"dcc860ac-4a20-498f-9cb3-bab4d57aa676\"],"
- +
"\"poolType\":\"NetworkFilesystem\",\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]";
+ +
"\"poolType\":{\"name\":\"NetworkFilesystem\"},\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]";
Request sreq = new Request(Version.v2, 1L, 2L, 3L, 1L, (short)1,
content);
sreq.setSequence(1);
Command cmds[] = sreq.getCommands();
diff --git
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
index 846b4157786..5315bca4b9a 100644
---
a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
+++
b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineHostVO.java
@@ -22,6 +22,7 @@ import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
@@ -45,6 +46,7 @@ import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceState;
import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.util.StoragePoolTypeConverter;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.StateMachine;
@@ -126,6 +128,7 @@ public class EngineHostVO implements EngineHost, Identity {
private String resource;
@Column(name = "fs_type")
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType fsType;
@Column(name = "available")
diff --git a/engine/schema/src/main/java/com/cloud/host/HostVO.java
b/engine/schema/src/main/java/com/cloud/host/HostVO.java
index 697401ad069..b7cac8ff8cb 100644
--- a/engine/schema/src/main/java/com/cloud/host/HostVO.java
+++ b/engine/schema/src/main/java/com/cloud/host/HostVO.java
@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
@@ -44,6 +45,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
import com.cloud.resource.ResourceState;
import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.util.StoragePoolTypeConverter;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.GenericDao;
import java.util.Arrays;
@@ -130,6 +132,7 @@ public class HostVO implements Host {
private String resource;
@Column(name = "fs_type")
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType fsType;
@Column(name = "available")
diff --git a/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
b/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
index 0bd71ea6d86..d8dfbb6f076 100644
--- a/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
+++ b/engine/schema/src/main/java/com/cloud/storage/VolumeVO.java
@@ -20,6 +20,7 @@ import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
@@ -32,6 +33,7 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
+import com.cloud.util.StoragePoolTypeConverter;
import
org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import com.cloud.storage.Storage.ProvisioningType;
@@ -114,7 +116,7 @@ public class VolumeVO implements Volume {
Type volumeType = Volume.Type.UNKNOWN;
@Column(name = "pool_type")
- @Enumerated(EnumType.STRING)
+ @Convert(converter = StoragePoolTypeConverter.class)
StoragePoolType poolType;
@Column(name = GenericDao.REMOVED_COLUMN)
@@ -331,9 +333,7 @@ public class VolumeVO implements Volume {
this.poolType = poolType;
}
- public StoragePoolType getPoolType() {
- return poolType;
- }
+ public StoragePoolType getPoolType() { return poolType; }
@Override
public long getDomainId() {
diff --git
a/engine/schema/src/main/java/com/cloud/util/StoragePoolTypeConverter.java
b/engine/schema/src/main/java/com/cloud/util/StoragePoolTypeConverter.java
new file mode 100644
index 00000000000..ab4148ec834
--- /dev/null
+++ b/engine/schema/src/main/java/com/cloud/util/StoragePoolTypeConverter.java
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.util;
+
+import com.cloud.storage.Storage.StoragePoolType;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+
+/**
+ * Converts {@link StoragePoolType} to and from {@link String} using {@link
StoragePoolType#name()}.
+ *
+ * @author mprokopchuk
+ */
+@Converter
+public class StoragePoolTypeConverter implements
AttributeConverter<StoragePoolType, String> {
+ @Override
+ public String convertToDatabaseColumn(StoragePoolType attribute) {
+ return attribute != null ? attribute.name() : null;
+ }
+
+ @Override
+ public StoragePoolType convertToEntityAttribute(String dbData) {
+ return dbData != null ? StoragePoolType.valueOf(dbData) : null;
+ }
+}
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
index 8f77b4ba63e..cfd12862c83 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
@@ -21,6 +21,7 @@ import java.util.Map;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.ScopeType;
+import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.utils.db.GenericDao;
@@ -130,7 +131,7 @@ public interface PrimaryDataStoreDao extends
GenericDao<StoragePoolVO, Long> {
Integer countAll();
- List<StoragePoolVO> findPoolsByStorageType(String storageType);
+ List<StoragePoolVO> findPoolsByStorageType(Storage.StoragePoolType
storageType);
List<StoragePoolVO> listStoragePoolsWithActiveVolumesByOfferingId(long
offeringid);
}
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
index af7dbdc0225..bcd2d27ad63 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
@@ -31,6 +31,7 @@ import org.apache.commons.collections.CollectionUtils;
import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.ScopeType;
+import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolTagVO;
@@ -619,7 +620,7 @@ public class PrimaryDataStoreDaoImpl extends
GenericDaoBase<StoragePoolVO, Long>
}
@Override
- public List<StoragePoolVO> findPoolsByStorageType(String storageType) {
+ public List<StoragePoolVO> findPoolsByStorageType(Storage.StoragePoolType
storageType) {
SearchCriteria<StoragePoolVO> sc = AllFieldSearch.create();
sc.setParameters("poolType", storageType);
return listBy(sc);
diff --git
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
index 926b8a5a01d..27179a8467e 100644
---
a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
+++
b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
@@ -21,11 +21,13 @@ import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
+import com.cloud.util.StoragePoolTypeConverter;
import com.cloud.utils.UriUtils;
import com.cloud.utils.db.Encrypt;
import com.cloud.utils.db.GenericDao;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
@@ -57,7 +59,7 @@ public class StoragePoolVO implements StoragePool {
private String uuid = null;
@Column(name = "pool_type", updatable = false, nullable = false, length =
32)
- @Enumerated(value = EnumType.STRING)
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType poolType;
@Column(name = GenericDao.CREATED_COLUMN)
@@ -180,8 +182,8 @@ public class StoragePoolVO implements StoragePool {
return poolType;
}
- public void setPoolType(StoragePoolType protocol) {
- poolType = protocol;
+ public void setPoolType(StoragePoolType poolType) {
+ this.poolType = poolType;
}
@Override
@@ -273,7 +275,7 @@ public class StoragePoolVO implements StoragePool {
@Override
public String getPath() {
String updatedPath = path;
- if (poolType == StoragePoolType.SMB) {
+ if (poolType.equals(StoragePoolType.SMB)) {
updatedPath = UriUtils.getUpdateUri(updatedPath, false);
if (updatedPath.contains("password") && updatedPath.contains("?"))
{
updatedPath = updatedPath.substring(0,
updatedPath.indexOf('?'));
diff --git
a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java
b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java
index ee4b77c269c..f4c6df7dd40 100644
---
a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java
+++
b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeServiceTest.java
@@ -19,6 +19,7 @@
package org.apache.cloudstack.storage.volume;
+import com.cloud.storage.Storage;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
@@ -185,7 +186,9 @@ public class VolumeServiceTest extends TestCase{
public void
validateDestroySourceVolumeAfterMigrationExpungeSourceVolumeAfterMigrationThrowExceptionReturnFalse()
throws
ExecutionException, InterruptedException{
VolumeObject volumeObject = new VolumeObject();
- volumeObject.configure(null, new VolumeVO() {});
+ VolumeVO vo = new VolumeVO() {};
+ vo.setPoolType(Storage.StoragePoolType.Filesystem);
+ volumeObject.configure(null, vo);
List<Exception> exceptions = new ArrayList<>(Arrays.asList(new
InterruptedException(), new ExecutionException() {}));
diff --git a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
index 6bf36df0941..b46b82f50b0 100644
--- a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
+++ b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
@@ -42,13 +42,16 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.naming.ConfigurationException;
+import javax.persistence.AttributeConverter;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.EmbeddedId;
import javax.persistence.EntityExistsException;
import javax.persistence.EnumType;
@@ -123,6 +126,7 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
protected final static TimeZone s_gmtTimeZone =
TimeZone.getTimeZone("GMT");
protected final static Map<Class<?>, GenericDao<?, ? extends
Serializable>> s_daoMaps = new ConcurrentHashMap<Class<?>, GenericDao<?, ?
extends Serializable>>(71);
+ private final ConversionSupport _conversionSupport;
protected Class<T> _entityBeanType;
protected String _table;
@@ -287,6 +291,7 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
}
}
+ _conversionSupport = new ConversionSupport();
setRunLevel(ComponentLifecycle.RUN_LEVEL_SYSTEM);
}
@@ -649,6 +654,9 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
}
} else if (type == byte[].class) {
field.set(entity, rs.getBytes(index));
+ } else if (field.getDeclaredAnnotation(Convert.class) != null) {
+ Object val =
_conversionSupport.convertToEntityAttribute(field, rs.getObject(index));
+ field.set(entity, val);
} else {
field.set(entity, rs.getObject(index));
}
@@ -1386,7 +1394,7 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
}
String stackTrace = ExceptionUtils.getStackTrace(new
CloudRuntimeException(String.format("The query to count all the records of [%s]
resulted in a value smaller than"
- + " the result set's size [count of records: %s, result set's
size: %s]. Using the result set's size instead.", _entityBeanType,
+ + " the result set's size [count of records: %s,
result set's size: %s]. Using the result set's size instead.", _entityBeanType,
count, resultSetSize)));
s_logger.warn(stackTrace);
@@ -1595,7 +1603,10 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
return;
}
}
- if (attr.field.getType() == String.class) {
+ if(attr.field.getDeclaredAnnotation(Convert.class) != null) {
+ Object val =
_conversionSupport.convertToDatabaseColumn(attr.field, value);
+ pstmt.setObject(j, val);
+ } else if (attr.field.getType() == String.class) {
final String str = (String)value;
if (str == null) {
pstmt.setString(j, null);
@@ -2221,4 +2232,50 @@ public abstract class GenericDaoBase<T, ID extends
Serializable> extends Compone
return sql;
}
+
+ /**
+ * Support conversion between DB and Entity values.
+ * Detects whether field is annotated with {@link Convert} annotation and
use converter instance from the annotation.
+ */
+ static class ConversionSupport {
+ /**
+ * Contains cache of {@link AttributeConverter} instances.
+ */
+ private static final Map<Class<?>, AttributeConverter<?, ?>>
s_converterCacheMap = new ConcurrentHashMap<>();
+
+ /**
+ * Checks whether field annotated with {@link Convert} annotation and
tries to convert source value with converter.
+ *
+ * @param field Entity field
+ * @param value DB value
+ * @return converted value if field is annotated with {@link Convert}
or original value otherwise
+ */
+ private <T> T convertToEntityAttribute(Field field, Object value) {
+ return (T) getConverter(field).map(converter ->
converter.convertToEntityAttribute(value)).orElse(value);
+ }
+
+ /**
+ * Checks whether field annotated with {@link Convert} annotation and
tries to convert source value with converter.
+ *
+ * @param field Entity field
+ * @param value Entity value
+ * @return converted value if field is annotated with {@link Convert}
or original value otherwise
+ */
+ private <T> T convertToDatabaseColumn(Field field, Object value) {
+ return (T) getConverter(field).map(converter ->
converter.convertToDatabaseColumn(value)).orElse(value);
+ }
+
+ private Optional<AttributeConverter<Object, Object>>
getConverter(Field field) {
+ return Optional.of(field).map(f ->
f.getAnnotation(Convert.class)).map(Convert::converter).filter(AttributeConverter.class::isAssignableFrom).map(converterType
-> {
+ return (AttributeConverter<Object, Object>)
s_converterCacheMap.computeIfAbsent(converterType, ct -> {
+ try {
+ return (AttributeConverter<?, ?>)
ct.getDeclaredConstructor().newInstance();
+ } catch (ReflectiveOperationException e) {
+ throw new CloudRuntimeException("Unable to create
converter for the class " + converterType, e);
+ }
+ });
+ });
+ }
+ }
+
}
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/FiberChannelAdapter.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/FiberChannelAdapter.java
index be7cb727ad7..83636b9a9c3 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/FiberChannelAdapter.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/FiberChannelAdapter.java
@@ -19,12 +19,16 @@ package com.cloud.hypervisor.kvm.storage;
import com.cloud.storage.Storage;
import com.cloud.utils.exception.CloudRuntimeException;
-@StorageAdaptorInfo(storagePoolType=Storage.StoragePoolType.FiberChannel)
public class FiberChannelAdapter extends MultipathSCSIAdapterBase {
public FiberChannelAdapter() {
LOGGER.info("Loaded FiberChannelAdapter for StorageLayer");
}
+ @Override
+ public Storage.StoragePoolType getStoragePoolType() {
+ return Storage.StoragePoolType.FiberChannel;
+ }
+
@Override
public KVMStoragePool getStoragePool(String uuid) {
KVMStoragePool pool = MapStorageUuidToStoragePool.get(uuid);
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
index f980cd295bd..46cca60ac4e 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java
@@ -36,7 +36,6 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
-@StorageAdaptorInfo(storagePoolType=StoragePoolType.Iscsi)
public class IscsiAdmStorageAdaptor implements StorageAdaptor {
private static final Logger s_logger =
Logger.getLogger(IscsiAdmStorageAdaptor.class);
@@ -51,6 +50,11 @@ public class IscsiAdmStorageAdaptor implements
StorageAdaptor {
return storagePool;
}
+ @Override
+ public StoragePoolType getStoragePoolType() {
+ return StoragePoolType.Iscsi;
+ }
+
@Override
public KVMStoragePool getStoragePool(String uuid) {
return MapStorageUuidToStoragePool.get(uuid);
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
index b1842f38da2..679407e2f58 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.hypervisor.kvm.storage;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
@@ -98,27 +100,45 @@ public class KVMStoragePoolManager {
public KVMStoragePoolManager(StorageLayer storagelayer, KVMHAMonitor
monitor) {
this._haMonitor = monitor;
this._storageMapper.put("libvirt", new
LibvirtStorageAdaptor(storagelayer));
- // add other storage adaptors here
- // this._storageMapper.put("newadaptor", new
NewStorageAdaptor(storagelayer));
- this._storageMapper.put(StoragePoolType.ManagedNFS.toString(), new
ManagedNfsStorageAdaptor(storagelayer));
- this._storageMapper.put(StoragePoolType.PowerFlex.toString(), new
ScaleIOStorageAdaptor(storagelayer));
+ // add other storage adaptors manually here
- // add any adaptors that wish to register themselves via annotation
+ // add any adaptors that wish to register themselves via call to
adaptor.getStoragePoolType()
Reflections reflections = new
Reflections("com.cloud.hypervisor.kvm.storage");
- Set<Class<? extends StorageAdaptor>> storageAdaptors =
reflections.getSubTypesOf(StorageAdaptor.class);
- for (Class<? extends StorageAdaptor> storageAdaptor : storageAdaptors)
{
- StorageAdaptorInfo info =
storageAdaptor.getAnnotation(StorageAdaptorInfo.class);
- if (info != null && info.storagePoolType() != null) {
- if
(this._storageMapper.containsKey(info.storagePoolType().toString())) {
- s_logger.warn(String.format("Duplicate StorageAdaptor type
%s, not loading %s", info.storagePoolType().toString(),
storageAdaptor.getName()));
+ Set<Class<? extends StorageAdaptor>> storageAdaptorClasses =
reflections.getSubTypesOf(StorageAdaptor.class);
+ for (Class<? extends StorageAdaptor> storageAdaptorClass :
storageAdaptorClasses) {
+ s_logger.debug("Checking pool type for adaptor " +
storageAdaptorClass.getName());
+ if (Modifier.isAbstract(storageAdaptorClass.getModifiers()) ||
storageAdaptorClass.isInterface()) {
+ s_logger.debug("Skipping registration of abstract class /
interface " + storageAdaptorClass.getName());
+ continue;
+ }
+ if
(storageAdaptorClass.isAssignableFrom(LibvirtStorageAdaptor.class)) {
+ s_logger.debug("Skipping re-registration of
LibvirtStorageAdaptor");
+ continue;
+ }
+ try {
+ Constructor<?> storageLayerConstructor =
Arrays.stream(storageAdaptorClass.getConstructors())
+ .filter(c -> c.getParameterCount() == 1)
+ .filter(c ->
c.getParameterTypes()[0].isAssignableFrom(StorageLayer.class))
+ .findFirst().orElse(null);
+ StorageAdaptor adaptor;
+
+ if (storageLayerConstructor == null) {
+ adaptor =
storageAdaptorClass.getDeclaredConstructor().newInstance();
} else {
- try {
- s_logger.info(String.format("adding storage adaptor
for %s", storageAdaptor.getName()));
-
this._storageMapper.put(info.storagePoolType().toString(),
storageAdaptor.getDeclaredConstructor().newInstance());
- } catch (Exception ex) {
- throw new CloudRuntimeException(ex.toString());
+ adaptor = (StorageAdaptor)
storageLayerConstructor.newInstance(storagelayer);
+ }
+
+ StoragePoolType storagePoolType = adaptor.getStoragePoolType();
+ if (storagePoolType != null) {
+ if
(this._storageMapper.containsKey(storagePoolType.toString())) {
+ s_logger.warn(String.format("Duplicate StorageAdaptor
type %s, not loading %s", storagePoolType, storageAdaptorClass.getName()));
+ } else {
+ s_logger.info(String.format("Adding storage adaptor
for %s", storageAdaptorClass.getName()));
+ this._storageMapper.put(storagePoolType.toString(),
adaptor);
}
}
+ } catch (Exception ex) {
+ throw new CloudRuntimeException("Failed to set up storage
adaptors", ex);
}
}
@@ -127,6 +147,13 @@ public class KVMStoragePoolManager {
}
}
+ /**
+ * Returns true if physical disk copy functionality supported.
+ */
+ public boolean supportsPhysicalDiskCopy(StoragePoolType type) {
+ return getStorageAdaptor(type).supportsPhysicalDiskCopy(type);
+ }
+
public boolean connectPhysicalDisk(StoragePoolType type, String poolUuid,
String volPath, Map<String, String> details) {
StorageAdaptor adaptor = getStorageAdaptor(type);
KVMStoragePool pool = adaptor.getStoragePool(poolUuid);
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index 1be4a8b6185..f958a1b181d 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -403,7 +403,7 @@ public class KVMStorageProcessor implements
StorageProcessor {
if (primaryPool.getType() == StoragePoolType.CLVM) {
templatePath = ((NfsTO)imageStore).getUrl() + File.separator +
templatePath;
vol = templateToPrimaryDownload(templatePath, primaryPool,
volume.getUuid(), volume.getSize(), cmd.getWaitInMillSeconds());
- } if (primaryPool.getType() == StoragePoolType.PowerFlex) {
+ } if
(storagePoolMgr.supportsPhysicalDiskCopy(primaryPool.getType())) {
Map<String, String> details = primaryStore.getDetails();
String path = details != null ?
details.get("managedStoreTarget") : null;
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
index bdaa419c698..83a5c06cb5b 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
@@ -459,6 +459,12 @@ public class LibvirtStorageAdaptor implements
StorageAdaptor {
return parser.parseStorageVolumeXML(volDefXML);
}
+ @Override
+ public StoragePoolType getStoragePoolType() {
+ // This is mapped manually in KVMStoragePoolManager
+ return null;
+ }
+
@Override
public KVMStoragePool getStoragePool(String uuid) {
return this.getStoragePool(uuid, false);
@@ -775,23 +781,22 @@ public class LibvirtStorageAdaptor implements
StorageAdaptor {
s_logger.info("Attempting to create volume " + name + " (" +
pool.getType().toString() + ") in pool "
+ pool.getUuid() + " with size " + toHumanReadableSize(size));
- switch (pool.getType()) {
- case RBD:
- return createPhysicalDiskByLibVirt(name, pool,
PhysicalDiskFormat.RAW, provisioningType, size);
- case NetworkFilesystem:
- case Filesystem:
- switch (format) {
- case QCOW2:
- case RAW:
- return createPhysicalDiskByQemuImg(name, pool, format,
provisioningType, size, passphrase);
- case DIR:
- case TAR:
- return createPhysicalDiskByLibVirt(name, pool, format,
provisioningType, size);
- default:
- throw new CloudRuntimeException("Unexpected disk
format is specified.");
- }
- default:
- return createPhysicalDiskByLibVirt(name, pool, format,
provisioningType, size);
+ StoragePoolType poolType = pool.getType();
+ if (poolType.equals(StoragePoolType.RBD)) {
+ return createPhysicalDiskByLibVirt(name, pool,
PhysicalDiskFormat.RAW, provisioningType, size);
+ } else if (poolType.equals(StoragePoolType.NetworkFilesystem) ||
poolType.equals(StoragePoolType.Filesystem)) {
+ switch (format) {
+ case QCOW2:
+ case RAW:
+ return createPhysicalDiskByQemuImg(name, pool, format,
provisioningType, size, passphrase);
+ case DIR:
+ case TAR:
+ return createPhysicalDiskByLibVirt(name, pool, format,
provisioningType, size);
+ default:
+ throw new CloudRuntimeException("Unexpected disk format is
specified.");
+ }
+ } else {
+ return createPhysicalDiskByLibVirt(name, pool, format,
provisioningType, size);
}
}
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ManagedNfsStorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ManagedNfsStorageAdaptor.java
index b23dd9a1790..62029fa1e34 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ManagedNfsStorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ManagedNfsStorageAdaptor.java
@@ -65,6 +65,9 @@ public class ManagedNfsStorageAdaptor implements
StorageAdaptor {
return storagePool;
}
+ @Override
+ public StoragePoolType getStoragePoolType() { return
StoragePoolType.ManagedNFS; }
+
@Override
public KVMStoragePool getStoragePool(String uuid) {
return getStoragePool(uuid, false);
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
index b85be041e48..2cd68753e01 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java
@@ -41,22 +41,19 @@ import org.apache.log4j.Logger;
import org.libvirt.LibvirtException;
import com.cloud.storage.Storage;
-import com.cloud.storage.StorageLayer;
import com.cloud.storage.StorageManager;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import org.apache.commons.lang3.StringUtils;
-@StorageAdaptorInfo(storagePoolType= Storage.StoragePoolType.PowerFlex)
public class ScaleIOStorageAdaptor implements StorageAdaptor {
private static final Logger LOGGER =
Logger.getLogger(ScaleIOStorageAdaptor.class);
private static final Map<String, KVMStoragePool>
MapStorageUuidToStoragePool = new HashMap<>();
private static final int DEFAULT_DISK_WAIT_TIME_IN_SECS = 60;
- private StorageLayer storageLayer;
- public ScaleIOStorageAdaptor(StorageLayer storagelayer) {
- storageLayer = storagelayer;
+ public ScaleIOStorageAdaptor() {
+
}
@Override
@@ -70,6 +67,11 @@ public class ScaleIOStorageAdaptor implements StorageAdaptor
{
return pool;
}
+ @Override
+ public Storage.StoragePoolType getStoragePoolType() {
+ return Storage.StoragePoolType.PowerFlex;
+ }
+
@Override
public KVMStoragePool getStoragePool(String uuid, boolean refreshInfo) {
return getStoragePool(uuid);
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
index ecf8691c6ed..34bf08f4496 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java
@@ -26,6 +26,8 @@ import com.cloud.storage.Storage.StoragePoolType;
public interface StorageAdaptor {
+ StoragePoolType getStoragePoolType();
+
public KVMStoragePool getStoragePool(String uuid);
// Get the storage pool from libvirt, but control if libvirt should
refresh the pool (can take a long time)
@@ -91,4 +93,11 @@ public interface StorageAdaptor {
* @param timeout
*/
KVMPhysicalDisk createTemplateFromDirectDownloadFile(String
templateFilePath, String destTemplatePath, KVMStoragePool destPool,
Storage.ImageFormat format, int timeout);
+
+ /**
+ * Returns true if storage adaptor supports physical disk copy
functionality.
+ */
+ default boolean supportsPhysicalDiskCopy(StoragePoolType type) {
+ return StoragePoolType.PowerFlex == type;
+ }
}
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptorInfo.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptorInfo.java
index fce976535f6..8d4b0c60a86 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptorInfo.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptorInfo.java
@@ -22,10 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import com.cloud.storage.Storage.StoragePoolType;
-
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE })
public @interface StorageAdaptorInfo {
- StoragePoolType storagePoolType();
}
diff --git
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
index 492bc275a3f..7989f9e6a69 100644
---
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
+++
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePoolTest.java
@@ -37,14 +37,12 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.storage.Storage.StoragePoolType;
-import com.cloud.storage.StorageLayer;
import com.cloud.utils.script.Script;
@RunWith(MockitoJUnitRunner.class)
@@ -54,9 +52,6 @@ public class ScaleIOStoragePoolTest {
StorageAdaptor adapter;
- @Mock
- StorageLayer storageLayer;
-
@Before
public void setUp() throws Exception {
final String uuid = "345fc603-2d7e-47d2-b719-a0110b3732e6";
@@ -65,7 +60,7 @@ public class ScaleIOStoragePoolTest {
Map<String,String> details = new HashMap<String, String>();
details.put(ScaleIOGatewayClient.STORAGE_POOL_SYSTEM_ID, systemId);
- adapter = spy(new ScaleIOStorageAdaptor(storageLayer));
+ adapter = spy(new ScaleIOStorageAdaptor());
pool = new ScaleIOStoragePool(uuid, "192.168.1.19", 443,
"a519be2f00000000", type, details, adapter);
}
diff --git
a/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/MockStoragePoolVO.java
b/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/MockStoragePoolVO.java
index 46cd0e47a7b..385ed3273ac 100644
---
a/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/MockStoragePoolVO.java
+++
b/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/MockStoragePoolVO.java
@@ -17,14 +17,14 @@
package com.cloud.simulator;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
+import com.cloud.util.StoragePoolTypeConverter;
import org.apache.cloudstack.api.InternalIdentity;
import com.cloud.storage.Storage.StoragePoolType;
@@ -50,7 +50,7 @@ public class MockStoragePoolVO implements InternalIdentity {
private String hostGuid;
@Column(name = "pool_type")
- @Enumerated(value = EnumType.STRING)
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType poolType;
public MockStoragePoolVO() {
diff --git
a/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java
b/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java
index ea9bcc4063c..c656b84289d 100644
---
a/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java
+++
b/plugins/hypervisors/simulator/src/main/java/com/cloud/simulator/dao/MockStoragePoolDaoImpl.java
@@ -52,7 +52,7 @@ public class MockStoragePoolDaoImpl extends
GenericDaoBase<MockStoragePoolVO, Lo
public MockStoragePoolVO findByHost(String hostUuid) {
SearchCriteria<MockStoragePoolVO> sc = hostguidSearch.create();
sc.setParameters("hostguid", hostUuid);
- sc.setParameters("type", StoragePoolType.Filesystem.toString());
+ sc.setParameters("type", StoragePoolType.Filesystem);
return findOneBy(sc);
}
diff --git
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
index 685565d73b0..bad57068a73 100644
---
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
+++
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java
@@ -263,7 +263,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl
implements PrimaryDataStore
parameters.setPort(port);
parameters.setPath(hostPath);
} else {
- StoragePoolType type = Enum.valueOf(StoragePoolType.class, scheme);
+ StoragePoolType type = StoragePoolType.valueOf(scheme);
if (type != null) {
parameters.setType(type);
diff --git
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
index 917b7c0ed0c..deee5fb6c41 100644
---
a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
+++
b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
@@ -54,7 +54,6 @@ import com.linbit.linstor.api.model.ResourceWithVolumes;
import com.linbit.linstor.api.model.StoragePool;
import com.linbit.linstor.api.model.VolumeDefinition;
-@StorageAdaptorInfo(storagePoolType=Storage.StoragePoolType.Linstor)
public class LinstorStorageAdaptor implements StorageAdaptor {
private static final Logger s_logger =
Logger.getLogger(LinstorStorageAdaptor.class);
private static final Map<String, KVMStoragePool>
MapStorageUuidToStoragePool = new HashMap<>();
@@ -66,6 +65,11 @@ public class LinstorStorageAdaptor implements StorageAdaptor
{
return new DevelopersApi(client);
}
+ @Override
+ public Storage.StoragePoolType getStoragePoolType() {
+ return Storage.StoragePoolType.Linstor;
+ }
+
private static String getLinstorRscName(String name) {
return LinstorUtil.RSC_PREFIX + name;
}
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 273f088d77f..d8f77ac88c6 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
@@ -39,7 +39,6 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
-@StorageAdaptorInfo(storagePoolType=StoragePoolType.StorPool)
public class StorPoolStorageAdaptor implements StorageAdaptor {
public static void SP_LOG(String fmt, Object... args) {
try (PrintWriter spLogFile = new PrintWriter(new BufferedWriter(new
FileWriter("/var/log/cloudstack/agent/storpool-agent.log", true)))) {
@@ -65,6 +64,11 @@ public class StorPoolStorageAdaptor implements
StorageAdaptor {
return storagePool;
}
+ @Override
+ public StoragePoolType getStoragePoolType() {
+ return StoragePoolType.StorPool;
+ }
+
@Override
public KVMStoragePool getStoragePool(String uuid) {
SP_LOG("StorPoolStorageAdaptor.getStoragePool: uuid=%s", uuid);
diff --git
a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
index e75e86108c7..c587eb40f18 100644
--- a/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
+++ b/server/src/main/java/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java
@@ -16,6 +16,27 @@
// under the License.
package com.cloud.api.query.dao;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.annotation.AnnotationService;
+import org.apache.cloudstack.annotation.dao.AnnotationDao;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import
org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.capacity.CapacityManager;
@@ -33,25 +54,6 @@ import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
-import org.apache.cloudstack.annotation.AnnotationService;
-import org.apache.cloudstack.annotation.dao.AnnotationDao;
-import org.apache.cloudstack.api.response.StoragePoolResponse;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import
org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-import org.apache.cloudstack.utils.jsinterpreter.TagAsRuleHelper;
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
-import javax.inject.Inject;
-import java.util.ArrayList;
-import java.util.List;
@Component
public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO,
Long> implements StoragePoolJoinDao {
@@ -337,7 +339,7 @@ public class StoragePoolJoinDaoImpl extends
GenericDaoBase<StoragePoolJoinVO, Lo
if (keyword != null) {
SearchCriteria<StoragePoolJoinVO> ssc = createSearchCriteria();
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
- ssc.addOr("poolType", SearchCriteria.Op.LIKE, "%" + keyword + "%");
+ ssc.addOr("poolType", SearchCriteria.Op.LIKE, new
Storage.StoragePoolType("%" + keyword + "%"));
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
diff --git a/server/src/main/java/com/cloud/api/query/vo/StoragePoolJoinVO.java
b/server/src/main/java/com/cloud/api/query/vo/StoragePoolJoinVO.java
index 5eb04d2e00d..85e904be973 100644
--- a/server/src/main/java/com/cloud/api/query/vo/StoragePoolJoinVO.java
+++ b/server/src/main/java/com/cloud/api/query/vo/StoragePoolJoinVO.java
@@ -19,12 +19,14 @@ package com.cloud.api.query.vo;
import java.util.Date;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
+import com.cloud.util.StoragePoolTypeConverter;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -64,7 +66,7 @@ public class StoragePoolJoinVO extends BaseViewVO implements
InternalIdentity, I
private StoragePoolStatus status;
@Column(name = "pool_type")
- @Enumerated(value = EnumType.STRING)
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType poolType;
@Column(name = GenericDao.CREATED_COLUMN)
diff --git a/server/src/main/java/com/cloud/api/query/vo/UserVmJoinVO.java
b/server/src/main/java/com/cloud/api/query/vo/UserVmJoinVO.java
index a465e8990e7..dbad73a39bb 100644
--- a/server/src/main/java/com/cloud/api/query/vo/UserVmJoinVO.java
+++ b/server/src/main/java/com/cloud/api/query/vo/UserVmJoinVO.java
@@ -22,6 +22,7 @@ import java.util.Map;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
+import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
@@ -38,6 +39,7 @@ import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.user.Account;
+import com.cloud.util.StoragePoolTypeConverter;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@@ -256,7 +258,7 @@ public class UserVmJoinVO extends
BaseViewWithTagInformationVO implements Contro
private String poolUuid;
@Column(name = "pool_type", updatable = false, nullable = false, length =
32)
- @Enumerated(value = EnumType.STRING)
+ @Convert(converter = StoragePoolTypeConverter.class)
private StoragePoolType poolType;
@Column(name = "volume_id")
diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
index 04889d0b2a8..8bcb2ac3956 100644
--- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
@@ -2133,7 +2133,7 @@ public class StorageManagerImpl extends ManagerBase
implements StorageManager, C
StoragePoolInfo childStoragePoolInfo =
childDataStoreAnswer.getPoolInfo();
StoragePoolVO dataStoreVO =
getExistingPoolByUuid(childStoragePoolInfo.getUuid());
if (dataStoreVO == null &&
childDataStoreAnswer.getPoolType().equalsIgnoreCase("NFS")) {
- List<StoragePoolVO> nfsStoragePools =
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem.toString());
+ List<StoragePoolVO> nfsStoragePools =
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem);
for (StoragePoolVO storagePool : nfsStoragePools) {
String storagePoolUUID = storagePool.getUuid();
if
(childStoragePoolInfo.getName().equalsIgnoreCase(storagePoolUUID.replaceAll("-",
""))) {
@@ -2193,7 +2193,7 @@ public class StorageManagerImpl extends ManagerBase
implements StorageManager, C
StoragePoolInfo childStoragePoolInfo =
childDataStoreAnswer.getPoolInfo();
StoragePoolVO dataStoreVO =
_storagePoolDao.findPoolByUUID(childStoragePoolInfo.getUuid());
if (dataStoreVO == null &&
childDataStoreAnswer.getPoolType().equalsIgnoreCase("NFS")) {
- List<StoragePoolVO> nfsStoragePools =
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem.toString());
+ List<StoragePoolVO> nfsStoragePools =
_storagePoolDao.findPoolsByStorageType(StoragePoolType.NetworkFilesystem);
for (StoragePoolVO storagePool : nfsStoragePools) {
String storagePoolUUID = storagePool.getUuid();
if
(childStoragePoolInfo.getName().equalsIgnoreCase(storagePoolUUID.replaceAll("-",
""))) {
@@ -2474,7 +2474,7 @@ public class StorageManagerImpl extends ManagerBase
implements StorageManager, C
@DB
public StoragePoolVO findLocalStorageOnHost(long hostId) {
SearchCriteria<StoragePoolVO> sc = LocalStorageSearch.create();
- sc.setParameters("type", new Object[] {StoragePoolType.Filesystem,
StoragePoolType.LVM});
+ sc.setParameters("type", StoragePoolType.Filesystem,
StoragePoolType.LVM);
sc.setJoinParameters("poolHost", "hostId", hostId);
List<StoragePoolVO> storagePools = _storagePoolDao.search(sc, null);
if (!storagePools.isEmpty()) {
diff --git
a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
index fa6b71d0cb2..3be6e02d04b 100644
---
a/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
+++
b/server/src/test/java/com/cloud/storage/listener/StoragePoolMonitorTest.java
@@ -21,6 +21,7 @@ import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.ScopeType;
+import com.cloud.storage.Storage;
import com.cloud.storage.StorageManagerImpl;
import com.cloud.storage.StoragePoolStatus;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@@ -53,6 +54,7 @@ public class StoragePoolMonitorTest {
pool.setScope(ScopeType.CLUSTER);
pool.setStatus(StoragePoolStatus.Up);
pool.setId(123L);
+ pool.setPoolType(Storage.StoragePoolType.Filesystem);
cmd = new StartupRoutingCommand();
cmd.setHypervisorType(Hypervisor.HypervisorType.KVM);
}