@@ -527,6 +527,8 @@ class VDI(object):
527
527
ONBOOT_RESET = "reset"
528
528
DB_ALLOW_CACHING = "allow_caching"
529
529
530
+ DB_COALESCEING = "coalesceing"
531
+
530
532
CONFIG_TYPE = {
531
533
DB_VDI_PARENT : XAPI .CONFIG_SM ,
532
534
DB_VDI_TYPE : XAPI .CONFIG_SM ,
@@ -539,7 +541,8 @@ class VDI(object):
539
541
DB_LEAFCLSC : XAPI .CONFIG_OTHER ,
540
542
DB_ONBOOT : XAPI .CONFIG_ON_BOOT ,
541
543
DB_ALLOW_CACHING : XAPI .CONFIG_ALLOW_CACHING ,
542
- DB_GC_NO_SPACE : XAPI .CONFIG_SM
544
+ DB_GC_NO_SPACE : XAPI .CONFIG_SM ,
545
+ DB_COALESCEING : XAPI .CONFIG_SM
543
546
}
544
547
545
548
LIVE_LEAF_COALESCE_MAX_SIZE = 20 * 1024 * 1024 # bytes
@@ -838,7 +841,7 @@ def _call_plugin_coalesce(self, hostRef):
838
841
self .sr .xapi .session .xenapi .host .call_plugin ( \
839
842
hostRef , XAPI .PLUGIN_ON_SLAVE , "commit_tapdisk" , args )
840
843
841
- def _doCoalesceOnHost (self , hostRef ):
844
+ def _doCoalesceOnHost (self , leaves : List [ "VDI" ], hostRef : str ):
842
845
self .validate ()
843
846
self .parent .validate (True )
844
847
self .parent ._increaseSizeVirt (self .sizeVirt )
@@ -847,18 +850,15 @@ def _doCoalesceOnHost(self, hostRef):
847
850
# Children and parent need to be RW for QCOW2 coalesce, otherwise tapdisk(libqcow) will crash trying to access them
848
851
849
852
def abortTest ():
850
- file = self .sr ._gc_running_file (self )
851
853
try :
852
- with open (file , "r" ) as f :
853
- if not f .read ():
854
- #TODO: Need to call commit cancel on the hostRef if we stop
855
- self ._call_plug_cancel (hostRef )
856
- return True
857
- except OSError as e :
858
- if e .errno == errno .ENOENT :
859
- util .SMlog ("File {} does not exist" .format (file ))
860
- else :
861
- util .SMlog ("IOError: {}" .format (e ))
854
+ for leaf in leaves :
855
+ if leaf .getConfig (VDI .DB_VDI_ACTIVATING , default = False ):
856
+ isActivating = True
857
+ break
858
+ if isActivating :
859
+ self ._call_plug_cancel (hostRef )
860
+ return True
861
+ except Exception as e : #TODO: Correct exception here
862
862
return True
863
863
return False
864
864
@@ -879,7 +879,7 @@ def _isOpenOnHosts(self) -> Optional[str]:
879
879
return hostRef
880
880
return None
881
881
882
- def _doCoalesce (self ) -> None :
882
+ def _doCoalesce (self , leaves = None ) -> None :
883
883
"""Coalesce self onto parent. Only perform the actual coalescing of
884
884
an image, but not the subsequent relinking. We'll do that as the next step,
885
885
after reloading the entire SR in case things have changed while we
@@ -888,7 +888,7 @@ def _doCoalesce(self) -> None:
888
888
self .parent .validate (True )
889
889
self .parent ._increaseSizeVirt (self .sizeVirt )
890
890
self .sr ._updateSlavesOnResize (self .parent )
891
- self ._coalesceCowImage (0 )
891
+ self ._coalesceCowImage (0 , leaves = leaves )
892
892
self .parent .validate (True )
893
893
#self._verifyContents(0)
894
894
self .parent .updateBlockInfo ()
@@ -992,20 +992,19 @@ def _vdi_is_raw(self, vdi_path):
992
992
uuid = self .extractUuid (vdi_path )
993
993
return self .sr .vdis [uuid ].vdi_type == VdiType .RAW
994
994
995
- def _coalesceCowImage (self , timeOut ):
995
+ def _coalesceCowImage (self , timeOut , leaves : List [ "VDI" ] = None ):
996
996
Util .log (" Running COW coalesce on %s" % self )
997
997
def abortTest ():
998
998
if self .cowutil .isCoalesceableOnRemote ():
999
- file = self .sr ._gc_running_file (self )
1000
999
try :
1001
- with open (file , "r" ) as f :
1002
- if not f .read ():
1000
+ if leaves is not None :
1001
+ for leaf in leaves :
1002
+ if leaf .getConfig (VDI .DB_VDI_ACTIVATING , default = False ):
1003
+ isActivating = True
1004
+ break
1005
+ if isActivating :
1003
1006
return True
1004
- except OSError as e :
1005
- if e .errno == errno .ENOENT :
1006
- util .SMlog ("File {} does not exist" .format (file ))
1007
- else :
1008
- util .SMlog ("IOError: {}" .format (e ))
1007
+ except Exception as e : #TODO: Correct exception here
1009
1008
return True
1010
1009
return IPCFlag (self .sr .uuid ).test (FLAG_TYPE_ABORT )
1011
1010
@@ -1490,7 +1489,7 @@ def _setChainRo(self, was_ro: List[str]) -> None:
1490
1489
self .sr .lvmCache .setReadonly (lvName , True )
1491
1490
1492
1491
@override
1493
- def _doCoalesce (self ) -> None :
1492
+ def _doCoalesce (self , leaves = None ) -> None :
1494
1493
"""LVMVDI parents must first be activated, inflated, and made writable"""
1495
1494
try :
1496
1495
self ._activateChain ()
@@ -1794,7 +1793,7 @@ def _setParent(self, parent) -> None:
1794
1793
(self .uuid , self .parentUuid ))
1795
1794
1796
1795
@override
1797
- def _doCoalesce (self ) -> None :
1796
+ def _doCoalesce (self , leaves = None ) -> None :
1798
1797
try :
1799
1798
self ._activateChain ()
1800
1799
self .parent .validate ()
@@ -2448,11 +2447,18 @@ def cleanupJournals(self, dryRun=False):
2448
2447
def cleanupCache (self , maxAge = - 1 ) -> int :
2449
2448
return 0
2450
2449
2451
- def _hasLeavesAttachedOn (self , vdi : VDI ):
2452
- leaves = vdi .getAllLeaves ()
2450
+ def _hasLeavesAttachedOn (self , leaves : List [VDI ]):
2453
2451
leaves_vdi = [leaf .uuid for leaf in leaves ]
2454
2452
return util .get_hosts_attached_on (self .xapi .session , leaves_vdi )
2455
2453
2454
+ def _put_coalesce_flag_on_leaves (self , leaves : List [VDI ]):
2455
+ for leaf in leaves :
2456
+ leaf .setConfig (VDI .DB_COALESCEING , "true" )
2457
+
2458
+ def _remove_coalesce_flag_on_leaves (self , leaves : List [VDI ]):
2459
+ for leaf in leaves :
2460
+ leaf .delConfig (VDI .DB_COALESCEING )
2461
+
2456
2462
def _gc_running_file (self , vdi ):
2457
2463
run_file = "gc_running_{}" .format (vdi .uuid )
2458
2464
return os .path .join (NON_PERSISTENT_DIR , str (self .uuid ), run_file )
@@ -2470,14 +2476,16 @@ def _coalesce(self, vdi: VDI):
2470
2476
# don't expect the rest of the process to take long
2471
2477
2472
2478
#TODO: Create `gc_running` in `/run/nonpersistent/sm/<sr uuid>/`
2473
- if os .path .exists (self ._gc_running_file (vdi )):
2474
- util .SMlog ("gc_running already exist for {}. Ignoring..." .format (self .uuid ))
2479
+ # if os.path.exists(self._gc_running_file(vdi)):
2480
+ # util.SMlog("gc_running already exist for {}. Ignoring...".format(self.uuid))
2475
2481
2476
- with open (self ._gc_running_file (vdi ), "w" ) as f :
2477
- f .write ("1" )
2482
+ # with open(self._gc_running_file(vdi), "w") as f:
2483
+ # f.write("1")
2478
2484
2479
2485
self .journaler .create (vdi .JRN_COALESCE , vdi .uuid , "1" )
2480
- host_refs = self ._hasLeavesAttachedOn (vdi )
2486
+ leaves = vdi .getAllLeaves ()
2487
+ self ._put_coalesce_flag_on_leaves (leaves )
2488
+ host_refs = self ._hasLeavesAttachedOn (leaves )
2481
2489
#TODO: this check of multiple host_refs should be done earlier in `is_coalesceable` to avoid stopping this late every time
2482
2490
if len (host_refs ) > 1 :
2483
2491
util .SMlog ("Not coalesceable, chain activated more than once" )
@@ -2486,12 +2494,13 @@ def _coalesce(self, vdi: VDI):
2486
2494
try :
2487
2495
if host_refs and vdi .cowutil .isCoalesceableOnRemote :
2488
2496
#Leaf opened on another host, we need to call online coalesce
2489
- vdi ._doCoalesceOnHost (host_refs [0 ])
2497
+ vdi ._doCoalesceOnHost (leaves , host_refs [0 ])
2490
2498
skipRelink = True
2491
2499
else :
2492
- vdi ._doCoalesce ()
2500
+ vdi ._doCoalesce (leaves = leaves )
2493
2501
except :
2494
- os .unlink (self ._gc_running_file (vdi ))
2502
+ self ._remove_coalesce_flag_on_leaves (leaves )
2503
+ # os.unlink(self._gc_running_file(vdi))
2495
2504
raise
2496
2505
"""
2497
2506
vdi._doCoalesce will call vdi._coalesceCowImage (after doing other things).
@@ -2520,7 +2529,8 @@ def _coalesce(self, vdi: VDI):
2520
2529
vdi .parent ._reloadChildren (vdi )
2521
2530
self .journaler .remove (vdi .JRN_RELINK , vdi .uuid )
2522
2531
2523
- os .unlink (self ._gc_running_file (vdi ))
2532
+ # os.unlink(self._gc_running_file(vdi))
2533
+ self ._remove_coalesce_flag_on_leaves (leaves )
2524
2534
self .deleteVDI (vdi )
2525
2535
2526
2536
class CoalesceTracker :
0 commit comments