7272import java .util .Arrays ;
7373import java .util .HashSet ;
7474import java .util .Set ;
75+ import java .util .concurrent .ConcurrentHashMap ;
7576import java .util .stream .Collectors ;
7677
7778
@@ -80,6 +81,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
8081 private StorageLayer _storageLayer ;
8182 private String _mountPoint = "/mnt" ;
8283 private String _manageSnapshotPath ;
84+ private static final ConcurrentHashMap <String , Integer > storagePoolRefCounts = new ConcurrentHashMap <>();
8385
8486 private String rbdTemplateSnapName = "cloudstack-base-snap" ;
8587 private static final int RBD_FEATURE_LAYERING = 1 ;
@@ -637,6 +639,39 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
637639 }
638640 }
639641
642+ /**
643+ * adjust refcount
644+ */
645+ private int adjustStoragePoolRefCount (String uuid , int adjustment ) {
646+ synchronized (uuid ) {
647+ // some access on the storagePoolRefCounts.key(uuid) element
648+ int refCount = storagePoolRefCounts .computeIfAbsent (uuid , k -> 0 );
649+ refCount += adjustment ;
650+ storagePoolRefCounts .put (uuid , refCount );
651+ if (refCount < 1 ) {
652+ storagePoolRefCounts .remove (uuid );
653+ } else {
654+ storagePoolRefCounts .put (uuid , refCount );
655+ }
656+ return refCount ;
657+ }
658+ }
659+ /**
660+ * Thread-safe increment storage pool usage refcount
661+ * @param uuid UUID of the storage pool to increment the count
662+ */
663+ private void incStoragePoolRefCount (String uuid ) {
664+ adjustStoragePoolRefCount (uuid , 1 );
665+ }
666+ /**
667+ * Thread-safe decrement storage pool usage refcount for the given uuid and return if storage pool still in use.
668+ * @param uuid UUID of the storage pool to decrement the count
669+ * @return true if the storage pool is still used, else false.
670+ */
671+ private boolean decStoragePoolRefCount (String uuid ) {
672+ return adjustStoragePoolRefCount (uuid , -1 ) > 0 ;
673+ }
674+
640675 @ Override
641676 public KVMStoragePool createStoragePool (String name , String host , int port , String path , String userInfo , StoragePoolType type , Map <String , String > details ) {
642677 s_logger .info ("Attempting to create storage pool " + name + " (" + type .toString () + ") in libvirt" );
@@ -744,6 +779,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
744779 }
745780
746781 try {
782+ incStoragePoolRefCount (name );
747783 if (sp .isActive () == 0 ) {
748784 s_logger .debug ("Attempting to activate pool " + name );
749785 sp .create (0 );
@@ -755,6 +791,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
755791
756792 return getStoragePool (name );
757793 } catch (LibvirtException e ) {
794+ decStoragePoolRefCount (name );
758795 String error = e .toString ();
759796 if (error .contains ("Storage source conflict" )) {
760797 throw new CloudRuntimeException ("A pool matching this location already exists in libvirt, " +
@@ -805,6 +842,13 @@ private boolean destroyStoragePoolHandleException(Connect conn, String uuid)
805842 @ Override
806843 public boolean deleteStoragePool (String uuid ) {
807844 s_logger .info ("Attempting to remove storage pool " + uuid + " from libvirt" );
845+
846+ // decrement and check if storage pool still in use
847+ if (decStoragePoolRefCount (uuid )) {
848+ s_logger .info (String .format ("deleteStoragePool: Storage pool %s still in use" , uuid ));
849+ return true ;
850+ }
851+
808852 Connect conn ;
809853 try {
810854 conn = LibvirtConnection .getConnection ();
0 commit comments