73
73
import java .util .Arrays ;
74
74
import java .util .HashSet ;
75
75
import java .util .Set ;
76
+ import java .util .concurrent .ConcurrentHashMap ;
76
77
import java .util .stream .Collectors ;
77
78
78
79
@@ -81,6 +82,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
81
82
private StorageLayer _storageLayer ;
82
83
private String _mountPoint = "/mnt" ;
83
84
private String _manageSnapshotPath ;
85
+ private static final ConcurrentHashMap <String , Integer > storagePoolRefCounts = new ConcurrentHashMap <>();
84
86
85
87
private String rbdTemplateSnapName = "cloudstack-base-snap" ;
86
88
private static final int RBD_FEATURE_LAYERING = 1 ;
@@ -644,8 +646,44 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
644
646
}
645
647
}
646
648
649
+ /**
650
+ * adjust refcount
651
+ */
652
+ private int adjustStoragePoolRefCount (String uuid , int adjustment ) {
653
+ final String mutexKey = storagePoolRefCounts .keySet ().stream ()
654
+ .filter (k -> k .equals (uuid ))
655
+ .findFirst ()
656
+ .orElse (uuid );
657
+ synchronized (mutexKey ) {
658
+ // some access on the storagePoolRefCounts.key(mutexKey) element
659
+ int refCount = storagePoolRefCounts .computeIfAbsent (mutexKey , k -> 0 );
660
+ refCount += adjustment ;
661
+ if (refCount < 1 ) {
662
+ storagePoolRefCounts .remove (mutexKey );
663
+ } else {
664
+ storagePoolRefCounts .put (mutexKey , refCount );
665
+ }
666
+ return refCount ;
667
+ }
668
+ }
669
+ /**
670
+ * Thread-safe increment storage pool usage refcount
671
+ * @param uuid UUID of the storage pool to increment the count
672
+ */
673
+ private void incStoragePoolRefCount (String uuid ) {
674
+ adjustStoragePoolRefCount (uuid , 1 );
675
+ }
676
+ /**
677
+ * Thread-safe decrement storage pool usage refcount for the given uuid and return if storage pool still in use.
678
+ * @param uuid UUID of the storage pool to decrement the count
679
+ * @return true if the storage pool is still used, else false.
680
+ */
681
+ private boolean decStoragePoolRefCount (String uuid ) {
682
+ return adjustStoragePoolRefCount (uuid , -1 ) > 0 ;
683
+ }
684
+
647
685
@ Override
648
- public KVMStoragePool createStoragePool (String name , String host , int port , String path , String userInfo , StoragePoolType type , Map <String , String > details ) {
686
+ public KVMStoragePool createStoragePool (String name , String host , int port , String path , String userInfo , StoragePoolType type , Map <String , String > details , boolean isPrimaryStorage ) {
649
687
logger .info ("Attempting to create storage pool " + name + " (" + type .toString () + ") in libvirt" );
650
688
651
689
StoragePool sp = null ;
@@ -751,6 +789,12 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
751
789
}
752
790
753
791
try {
792
+ if (!isPrimaryStorage ) {
793
+ // only ref count storage pools for secondary storage, as primary storage is assumed
794
+ // to be always mounted, as long the primary storage isn't fully deleted.
795
+ incStoragePoolRefCount (name );
796
+ }
797
+
754
798
if (sp .isActive () == 0 ) {
755
799
logger .debug ("Attempting to activate pool " + name );
756
800
sp .create (0 );
@@ -762,6 +806,7 @@ public KVMStoragePool createStoragePool(String name, String host, int port, Stri
762
806
763
807
return getStoragePool (name );
764
808
} catch (LibvirtException e ) {
809
+ decStoragePoolRefCount (name );
765
810
String error = e .toString ();
766
811
if (error .contains ("Storage source conflict" )) {
767
812
throw new CloudRuntimeException ("A pool matching this location already exists in libvirt, " +
@@ -812,6 +857,13 @@ private boolean destroyStoragePoolHandleException(Connect conn, String uuid)
812
857
@ Override
813
858
public boolean deleteStoragePool (String uuid ) {
814
859
logger .info ("Attempting to remove storage pool " + uuid + " from libvirt" );
860
+
861
+ // decrement and check if storage pool still in use
862
+ if (decStoragePoolRefCount (uuid )) {
863
+ logger .info (String .format ("deleteStoragePool: Storage pool %s still in use" , uuid ));
864
+ return true ;
865
+ }
866
+
815
867
Connect conn = null ;
816
868
try {
817
869
conn = LibvirtConnection .getConnection ();
0 commit comments