Adam Litke has uploaded a new change for review.
Change subject: tests: Add a live merge functional test
......................................................................
tests: Add a live merge functional test
Test whether we can successfully merge the active layer. Uses lots of
the functional test infrastructure! Only runs if vdsm says it can
support live merge.
Change-Id: Idd5a2f7eedaef9e90981256de66fc3ed21658e89
Signed-off-by: Adam Litke <alitke(a)redhat.com>
---
M tests/functional/utils.py
M tests/functional/virtTests.py
2 files changed, 185 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/29824/1
diff --git a/tests/functional/utils.py b/tests/functional/utils.py
index 494be98..e3cdba6 100644
--- a/tests/functional/utils.py
+++ b/tests/functional/utils.py
@@ -228,3 +228,41 @@
def updateVmPolicy(self, vmId, vcpuLimit):
result = self.vdscli.updateVmPolicy([vmId, vcpuLimit])
return result['status']['code'],
result['status']['message']
+
+ def getTaskStatus(self, taskId):
+ result = self.vdscli.getTaskStatus(taskId)
+ return result['status']['code'],
result['status']['message'],\
+ result['taskStatus']
+
+ def getVolumeInfo(self, sdId, spId, imgId, volId):
+ result = self.vdscli.getVolumeInfo(sdId, spId, imgId, volId)
+ return result['status']['code'],
result['status']['message'],\
+ result['info']
+
+ def createVolume(self, sdId, spId, imgId, size, volFormat, preallocate,
+ diskType, volId, desc, baseImgId, baseVolId):
+ result = self.vdscli.createVolume(sdId, spId, imgId, size, volFormat,
+ preallocate, diskType, volId, desc,
+ baseImgId, baseVolId)
+ return result['status']['code'],
result['status']['message'],\
+ result['uuid']
+
+ def deleteVolume(self, sdId, spId, imgId, volIds, postZero=False,
+ force=False):
+ result = self.vdscli.deleteVolume(sdId, spId, imgId, volIds, postZero,
+ force)
+ return result['status']['code'],
result['status']['message'],\
+ result['uuid']
+
+ def snapshot(self, vmId, snapDrives, snapMemVolHandle=''):
+ result = self.vdscli.snapshot(vmId, snapDrives, snapMemVolHandle)
+ return result['status']['code'],
result['status']['message']
+
+ def merge(self, vmId, drive, base, top, bandwidth, jobId):
+ result = self.vdscli.merge(vmId, drive, base, top, bandwidth, jobId)
+ return result['status']['code'],
result['status']['message']
+
+ def list(self, fullStatus=False, vmList=()):
+ result = self.vdscli.list(fullStatus, vmList)
+ return result['status']['code'],
result['status']['message'], \
+ result['vmList']
diff --git a/tests/functional/virtTests.py b/tests/functional/virtTests.py
index 94ce240..b811b92 100644
--- a/tests/functional/virtTests.py
+++ b/tests/functional/virtTests.py
@@ -22,6 +22,7 @@
import math
import tempfile
import logging
+import uuid
from stat import S_IROTH
from functools import partial, wraps
@@ -32,7 +33,8 @@
from testrunner import temporaryPath
from vdsm.utils import CommandPath, RollbackContext
-import storageTests as storage
+import storageTests
+import storage
from storage.misc import execCmd
from utils import VdsProxy, SUCCESS
@@ -109,6 +111,18 @@
return method(self, *args, **kwargs)
else:
raise SkipTest('KVM is not enabled')
+ return wrapped
+
+
+def requireLiveMerge(method):
+ @wraps(method)
+ def wrapped(self, *args, **kwargs):
+ status, msg, result = self.vdsm.getVdsCapabilities()
+ self.assertEqual(status, SUCCESS, msg)
+ if result.get('liveMerge') == 'true':
+ return method(self, *args, **kwargs)
+ else:
+ raise SkipTest('Live Merge is not available')
return wrapped
@@ -227,9 +241,9 @@
@requireKVM
@permutations([['localfs'], ['iscsi'], ['nfs']])
def testVmWithStorage(self, backendType):
- disk = storage.StorageTest()
+ disk = storageTests.StorageTest()
disk.setUp()
- conf = storage.storageLayouts[backendType]
+ conf = storageTests.storageLayouts[backendType]
drives = disk.generateDriveConf(conf)
customization = {'vmId': '88888888-eeee-ffff-aaaa-111111111111',
'vmName': 'testVmWithStorage' + backendType,
@@ -247,8 +261,8 @@
def testVmWithDevice(self, *devices):
customization = {'vmId': '77777777-ffff-3333-bbbb-222222222222',
'vmName': 'testVm', 'devices': [],
'display': 'vnc'}
- storageLayout = storage.storageLayouts['localfs']
- diskSpecs = storage.StorageTest.generateDriveConf(storageLayout)
+ storageLayout = storageTests.storageLayouts['localfs']
+ diskSpecs = storageTests.StorageTest.generateDriveConf(storageLayout)
pciSpecs = {'bus': '0x00', 'domain': '0x0000',
'function': '0x0', 'type': 'pci'}
ccidSpecs = {'slot': '0', 'controller': '0',
'type': 'ccid'}
@@ -412,3 +426,131 @@
self.vdsm.updateVmPolicy(customization['vmId'],
'50')
self.assertEqual(status, SUCCESS, msg)
+
+
+@expandPermutations
+class LiveMergeTest(VirtTestBase):
+ def _waitTask(self, taskId):
+ def assertTaskOK():
+ status, msg, result = self.vdsm.getTaskStatus(taskId)
+ self.assertEqual(status, SUCCESS, msg)
+ self.assertEquals(result['taskState'], 'finished')
+
+ self.retryAssert(assertTaskOK, timeout=60)
+
+ def _waitBlockJobs(self, vmId, jobIds):
+ def assertJobsGone():
+ status, msg, result = self.vdsm.getVmStats(vmId)
+ self.assertEqual(status, SUCCESS, msg)
+ self.assertTrue('vmJobs' in result)
+ self.assertTrue(all([x not in result['vmJobs'].keys()
+ for x in jobIds]))
+
+ self.retryAssert(assertJobsGone, timeout=60)
+
+ def _snapshotVM(self, vmId, drives, rollback):
+ snapDrives = []
+ for drive in drives:
+ sd = drive['domainID']
+ sp = drive['poolID']
+ img = drive['imageID']
+ vol = drive['volumeID']
+ newVol = str(uuid.uuid4())
+ volFormat = storage.volume.COW_FORMAT
+ preallocate = storage.volume.SPARSE_VOL
+ desc = 'snapshot for %s' % vol
+
+ # Create volume and wait
+ status, msg, result = self.vdsm.getVolumeInfo(sd, sp, img, vol)
+ self.assertEqual(status, SUCCESS, msg)
+ size = result['capacity']
+ diskType = result['disktype']
+
+ status, msg, taskId = self.vdsm.createVolume(sd, sp, img, size,
+ volFormat,
+ preallocate, diskType,
+ newVol, desc, img,
+ vol)
+ self.assertEqual(status, SUCCESS, msg)
+ self._waitTask(taskId)
+ undo = lambda sd=sd, sp=sp, img=img, vol=newVol: \
+ self._waitTask(self.vdsm.deleteVolume(sd, sp, img, vol)[2])
+ rollback.prependDefer(undo)
+
+ snapDrives.append({'domainID': sd,
+ 'imageID': img,
+ 'volumeID': newVol,
+ 'baseVolumeID': vol})
+
+ # Create snapshot
+ status, msg = self.vdsm.snapshot(vmId, snapDrives)
+ self.assertEqual(status, SUCCESS, msg)
+ return snapDrives
+
+ def _orderChain(self, vmId, dev, chain):
+ parentMap = {}
+ for vol in chain:
+ status, msg, info = self.vdsm.getVolumeInfo(dev['domainID'],
+ dev['poolID'],
+ dev['imageID'], vol)
+ self.assertEqual(status, SUCCESS, msg)
+ parent = info['parent']
+ parentMap[vol] = parent
+
+ vol = dev['volumeID']
+ chain = list()
+ while True:
+ chain.insert(0, vol)
+ vol = parentMap.get(vol, '00000000-0000-0000-0000-000000000000')
+ if vol == '00000000-0000-0000-0000-000000000000':
+ break
+ return chain
+
+ def _getVolumeChains(self, vmId):
+ chains = {}
+ status, msg, result = self.vdsm.list(True, (vmId,))
+ self.assertEqual(status, SUCCESS, msg)
+ vmDef = result[0]
+ for dev in vmDef['devices']:
+ if dev['device'] != 'disk':
+ continue
+ chains[dev['imageID']] = self._orderChain(vmId, dev,
+ [x['volumeID'] for x in
+ dev['volumeChain']])
+ return chains
+
+ @requireKVM
+ @requireLiveMerge
+ def testCapable(self):
+ pass
+
+ @permutations([['localfs']])
+ def testMergeActiveLayer(self, backendType):
+ disk = storageTests.StorageTest()
+ disk.setUp()
+ conf = storageTests.storageLayouts[backendType]
+ drives = disk.generateDriveConf(conf)
+ vmId = '12121212-abab-baba-abab-222222222222'
+ customization = {'vmId': vmId,
+ 'vmName': 'testMergeActive' + backendType,
+ 'drives': drives,
+ 'display': 'vnc'}
+
+ with RollbackContext() as rollback:
+ disk.createVdsmStorageLayout(conf, 3, rollback)
+ with RunningVm(self.vdsm, customization) as vm:
+ self._waitForStartup(vm, VM_MINIMAL_UPTIME)
+ snapDrives = self._snapshotVM(vmId, drives, rollback)
+ chains = {}
+ jobIds = []
+ for drive in snapDrives:
+ base = drive['baseVolumeID']
+ top = drive['volumeID']
+ jobId = str(uuid.uuid4())
+ chains[drive['imageID']] = [base, top]
+ status, msg = self.vdsm.merge(vmId, drive, base, top, 0,
+ jobId)
+ jobIds.append(jobId)
+ self._waitBlockJobs(vmId, jobIds)
+ actual = self._getVolumeChains(vmId)
+ self.assertEquals(chains, actual)
--
To view, visit
http://gerrit.ovirt.org/29824
To unsubscribe, visit
http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idd5a2f7eedaef9e90981256de66fc3ed21658e89
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <alitke(a)redhat.com>