Skip to content

Commit ed981e3

Browse files
committed
CA-408452: remove vhd parent if it does not have one
A previous change stopped the cleanup code unilaterally removing the `vhd-parent` configuration of the lef coalesced VHD which resulted in failures where VHDs that should have declared a parent no longer did until a subsequent SR scan restored the configuration value. This is the alternate mirror case where the leaf coalesce collapses the entire tree out and so the `vhd-parent` becomes redundant, again until a subsequent SR scan removes it. To satisfy both use cases remove the `vhd-parent` property if and only if the coalesced VHD has no parent. Signed-off-by: Mark Syms <mark.syms@cloud.com>
1 parent 542072d commit ed981e3

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

libs/sm/cleanup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,9 @@ def _doCoalesceLeaf(self, vdi):
23302330
vdi.parent.children = []
23312331
vdi.parent = None
23322332

2333+
if parent.parent is None:
2334+
parent.delConfig(VDI.DB_VHD_PARENT)
2335+
23332336
extraSpace = self._calcExtraSpaceNeeded(vdi, parent)
23342337
freeSpace = self.getFreeSpace()
23352338
if freeSpace < extraSpace:

tests/test_cleanup.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from uuid import uuid4
88

99
from sm import cleanup
10+
from sm import fjournaler
1011
from sm.core import lock
1112

1213
from sm.core import util
@@ -16,6 +17,8 @@
1617

1718
import XenAPI
1819

20+
MEGA = 1024 * 1024
21+
1922

2023
class FakeFile(object):
2124
pass
@@ -1815,6 +1818,46 @@ def test_not_plugged_retry(self):
18151818
# Assert
18161819
self.assertIsNotNone(sr)
18171820

1821+
def test_doCoalesceLeaf_no_parent_after(self):
1822+
sr = create_cleanup_sr(self.xapi_mock)
1823+
sr.journaler = mock.create_autospec(fjournaler.Journaler)
1824+
parent_uuid = str(uuid.uuid4())
1825+
mock_parent = mock.MagicMock()
1826+
mock_parent.uuid = parent_uuid
1827+
mock_parent.parent = None
1828+
mock_parent.raw = False
1829+
mock_parent.getSizeVHD.return_value = 10 * MEGA
1830+
1831+
vdi_uuid = str(uuid.uuid4())
1832+
mock_vdi = mock.MagicMock()
1833+
mock_vdi.uuid = vdi_uuid
1834+
mock_vdi.getSizeVHD.return_value = 10 * MEGA
1835+
mock_vdi.parent = mock_parent
1836+
1837+
sr._doCoalesceLeaf(mock_vdi)
1838+
1839+
mock_parent.delConfig.assert_called_with("vhd-parent")
1840+
1841+
def test_doCoalesceLeaf_parent_remains_after(self):
1842+
sr = create_cleanup_sr(self.xapi_mock)
1843+
sr.journaler = mock.create_autospec(fjournaler.Journaler)
1844+
parent_uuid = str(uuid.uuid4())
1845+
mock_parent = mock.MagicMock()
1846+
mock_parent.uuid = parent_uuid
1847+
mock_parent.parent = mock.MagicMock()
1848+
mock_parent.raw = False
1849+
mock_parent.getSizeVHD.return_value = 10 * MEGA
1850+
1851+
vdi_uuid = str(uuid.uuid4())
1852+
mock_vdi = mock.MagicMock()
1853+
mock_vdi.uuid = vdi_uuid
1854+
mock_vdi.getSizeVHD.return_value = 10 * MEGA
1855+
mock_vdi.parent = mock_parent
1856+
1857+
sr._doCoalesceLeaf(mock_vdi)
1858+
1859+
self.assertNotIn('vhd-parent', mock_parent.delConfig.call_args)
1860+
18181861

18191862
class TestLockGCActive(unittest.TestCase):
18201863

0 commit comments

Comments
 (0)