Adam Litke has uploaded a new change for review.
Change subject: libvdsm: Add unit tests
......................................................................
libvdsm: Add unit tests
Change-Id: Ifbf032ed569a42a4eceeedfa536e737a2f8ded6b
Signed-off-by: Adam Litke <agl(a)us.ibm.com>
---
M Makefile.am
M tests/Makefile.am
A tests/apiData.py
A tests/apiTests.py
M tests/run_tests.sh.in
M tests/run_tests_local.sh.in
M vdsm_api/Bridge.py
7 files changed, 786 insertions(+), 7 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/06/8406/1
diff --git a/Makefile.am b/Makefile.am
index 8cbfdd1..84cbff9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -114,8 +114,7 @@
vds_bootstrap/miniyum.py \
$(NULL)
-PEP8_BLACKLIST = \
- restData.py
+PEP8_BLACKLIST = apiData.py,restData.py
check-local:
find . -path './.git' -prune -type f -o \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a5e4c64..9faf981 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,7 @@
test_modules = \
alignmentScanTests.py \
+ apiTests.py \
betterPopenTests.py \
betterThreadingTests.py \
capsTests.py \
@@ -65,6 +66,7 @@
dist_vdsmtests_PYTHON = \
$(test_modules) \
+ apiData.py \
monkeypatch.py \
testrunner.py \
testValidation.py
diff --git a/tests/apiData.py b/tests/apiData.py
new file mode 100644
index 0000000..2566bde
--- /dev/null
+++ b/tests/apiData.py
@@ -0,0 +1,526 @@
+class APIData(object):
+ def __init__(self, obj, meth, data):
+ self.obj = obj
+ self.meth = meth
+ self.data = data
+
+testPing_apidata = [
+ APIData('Global', 'ping', {
+ 'status': {'code': 0, 'message': 'OK'}})
+]
+
+testCapabilities_apidata = [
+ APIData('Global', 'getCapabilities',
+ {'info': {'HBAInventory': {'FC': [],
+ 'iSCSI': [{'InitiatorName':
'iqn.1994-05.com.redhat:9fb32884fc31'}]},
+ 'ISCSIInitiatorName':
'iqn.1994-05.com.redhat:9fb32884fc31',
+ 'bondings': {'bond0': {'addr': '',
+ 'cfg': {},
+ 'hwaddr': '00:00:00:00:00:00',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'slaves': []},
+ 'bond1': {'addr': '',
+ 'cfg': {},
+ 'hwaddr': '00:00:00:00:00:00',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'slaves': []},
+ 'bond2': {'addr': '',
+ 'cfg': {},
+ 'hwaddr': '00:00:00:00:00:00',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'slaves': []},
+ 'bond3': {'addr': '',
+ 'cfg': {},
+ 'hwaddr': '00:00:00:00:00:00',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'slaves': []},
+ 'bond4': {'addr': '',
+ 'cfg': {},
+ 'hwaddr': '00:00:00:00:00:00',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'slaves': []}},
+ 'bridges': {'ovirtmgmt': {'addr':
'192.168.4.37',
+ 'cfg': {'BOOTPROTO':
'dhcp',
+ 'DEVICE': 'ovirtmgmt',
+ 'NM_CONTROLLED': 'yes',
+ 'ONBOOT': 'yes',
+ 'TYPE': 'Bridge'},
+ 'mtu': '1500',
+ 'netmask': '255.255.192.0',
+ 'ports': ['eth0',
'vnet0'],
+ 'stp': 'off'}},
+ 'clusterLevels': ['3.0', '3.1', '3.2'],
+ 'cpuCores': '4',
+ 'cpuFlags':
'fpu,vme,de,pse,tsc,msr,pae,mce,cx8,apic,sep,mtrr,pge,mca,cmov,pat,pse36,clflush,mmx,fxsr,sse,sse2,ht,syscall,nx,mmxext,fxsr_opt,rdtscp,lm,3dnowext,3dnow,rep_good,nopl,extd_apicid,pni,cx16,lahf_lm,cmp_legacy,svm,extapic,cr8_legacy,model_athlon,model_Opteron_G1,model_Opteron_G2',
+ 'cpuModel': 'Dual-Core AMD Opteron(tm) Processor 2220',
+ 'cpuSockets': '2',
+ 'cpuSpeed': '2799.911',
+ 'emulatedMachines': ['pc-0.15',
+ 'pc-1.0',
+ 'pc',
+ 'pc-0.14',
+ 'pc-0.13',
+ 'pc-0.12',
+ 'pc-0.11',
+ 'pc-0.10',
+ 'isapc',
+ 'pc-0.15',
+ 'pc-1.0',
+ 'pc',
+ 'pc-0.14',
+ 'pc-0.13',
+ 'pc-0.12',
+ 'pc-0.11',
+ 'pc-0.10',
+ 'isapc'],
+ 'guestOverhead': '65',
+ 'hooks': {},
+ 'kvmEnabled': 'true',
+ 'lastClient': '127.0.0.1',
+ 'lastClientIface': 'ovirtmgmt',
+ 'management_ip': '',
+ 'memSize': '3955',
+ 'netConfigDirty': 'False',
+ 'networks': {'ovirtmgmt': {'addr':
'192.168.4.37',
+ 'bridged': True,
+ 'cfg': {'BOOTPROTO':
'dhcp',
+ 'DEVICE': 'ovirtmgmt',
+ 'NM_CONTROLLED': 'yes',
+ 'ONBOOT': 'yes',
+ 'TYPE': 'Bridge'},
+ 'gateway': '192.168.0.1',
+ 'iface': 'ovirtmgmt',
+ 'mtu': '1500',
+ 'netmask': '255.255.192.0',
+ 'ports': ['eth0',
'vnet0'],
+ 'stp': 'off'}},
+ 'nics': {'eth0': {'addr': '',
+ 'cfg': {'BRIDGE': 'ovirtmgmt',
+ 'DEVICE': 'eth0',
+ 'HWADDR': '00:14:5e:6d:92:d0',
+ 'NM_CONTROLLED': 'yes',
+ 'ONBOOT': 'yes',
+ 'TYPE': 'Ethernet'},
+ 'hwaddr': '00:14:5e:6d:92:d0',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'speed': 1000},
+ 'eth1': {'addr': '',
+ 'cfg': {'BOOTPROTO': 'dhcp',
+ 'DEVICE': 'eth1',
+ 'HWADDR': '00:14:5E:B3:8F:70',
+ 'NM_CONTROLLED': 'yes',
+ 'ONBOOT': 'no',
+ 'UUID':
'487e5217-0bcb-4eac-bf96-d7c7d2a7e9dc'},
+ 'hwaddr': '00:14:5e:b3:8f:70',
+ 'mtu': '1500',
+ 'netmask': '',
+ 'speed': 0}},
+ 'operatingSystem': {'name': 'Fedora',
+ 'release': '1',
+ 'version': '17'},
+ 'packages2': {'kernel': {'buildtime':
1338723317.0,
+ 'release': '1.fc17.x86_64',
+ 'version': '3.4.0'},
+ 'libvirt': {'buildtime':
'1340891887',
+ 'release': '3.fc17',
+ 'version': '0.9.11.4'},
+ 'qemu-img': {'buildtime':
'1343612073',
+ 'release': '1.fc17',
+ 'version': '1.0.1'},
+ 'qemu-kvm': {'buildtime':
'1343612073',
+ 'release': '1.fc17',
+ 'version': '1.0.1'},
+ 'spice-server': {'buildtime':
'1336983054',
+ 'release': '5.fc17',
+ 'version': '0.10.1'},
+ 'vdsm': {'buildtime': '1348601496',
+ 'release': '0.417.giteceb791.fc17',
+ 'version': '4.10.0'}},
+ 'reservedMem': '321',
+ 'software_revision': '0.417',
+ 'software_version': '4.10',
+ 'supportedProtocols': ['2.2', '2.3'],
+ 'supportedRHEVMs': ['3.0', '3.1'],
+ 'uuid':
'806EC463-A088-3F7D-804A-D6A0F8D9BC1E_00:14:5e:6d:92:d0',
+ 'version_name': 'Snow Man',
+ 'vlans': {},
+ 'vmTypes': ['kvm']},
+ 'status': {'code': 0, 'message': 'Done'}})
+]
+
+testStorageDomains_apidata = [
+ APIData('Global', 'getConnectedStoragePools',
+ {'poollist': ['342d186f-3556-442e-b0b0-0b083403138d'],
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('Global', 'getStorageDomains',
+ {'domlist': ['6589d50f-9558-4377-b0e2-b2456d491866',
+ 'ee8e704f-dc3f-418f-806c-8826cb0d07ba'],
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('StorageDomain', 'getInfo',
+ {'info': {'class': 'Data',
+ 'lver': 89,
+ 'master_ver': 2,
+ 'name': 'data2',
+ 'pool': ['342d186f-3556-442e-b0b0-0b083403138d'],
+ 'remotePath': '/var/lib/vdsm/storage/data2',
+ 'role': 'Master',
+ 'spm_id': 1,
+ 'type': 'LOCALFS',
+ 'uuid': '6589d50f-9558-4377-b0e2-b2456d491866',
+ 'version': '0'},
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('StorageDomain', 'getStats',
+ {'stats': {'diskfree': '23935705088',
+ 'disktotal': '44233609216',
+ 'mdafree': 0,
+ 'mdasize': 0,
+ 'mdathreshold': True,
+ 'mdavalid': True},
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('StorageDomain', 'getInfo',
+ {'info': {'class': 'Iso',
+ 'lver': -1,
+ 'master_ver': 0,
+ 'name': 'isos',
+ 'pool': ['342d186f-3556-442e-b0b0-0b083403138d'],
+ 'remotePath': '127.0.0.1:/var/lib/vdsm/storage/isos',
+ 'role': 'Regular',
+ 'spm_id': -1,
+ 'type': 'NFS',
+ 'uuid': 'ee8e704f-dc3f-418f-806c-8826cb0d07ba',
+ 'version': '0'},
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('StorageDomain', 'getStats',
+ {'stats': {'diskfree': '23935844352',
+ 'disktotal': '44233654272',
+ 'mdafree': 0,
+ 'mdasize': 0,
+ 'mdathreshold': True,
+ 'mdavalid': True},
+ 'status': {'code': 0, 'message': 'OK'}}),
+]
+
+testStats_apidata = [
+ APIData('Global', 'getStats',
+ {'info': {'anonHugePages': '1274',
+ 'cpuIdle': '97.41',
+ 'cpuLoad': '0.54',
+ 'cpuSys': '1.40',
+ 'cpuSysVdsmd': '0.37',
+ 'cpuUser': '1.19',
+ 'cpuUserVdsmd': '0.75',
+ 'dateTime': '2012-09-28T14:34:22 GMT',
+ 'diskStats': {'/tmp': {'free': '22825'},
+ '/var/log': {'free': '22825'},
+ '/var/log/core': {'free': '22825'},
+ '/var/run/vdsm/': {'free': '1900'}},
+ 'elapsedTime': '4127',
+ 'generationID': 'f62bbd35-a89c-4a58-8527-e6f6945b525d',
+ 'ksmCpu': 1544,
+ 'ksmPages': 64,
+ 'ksmState': True,
+ 'memAvailable': 1223,
+ 'memCommitted': 1089,
+ 'memShared': 57034,
+ 'memUsed': '57',
+ 'netConfigDirty': 'False',
+ 'network': {'bond0': {'macAddr': '',
+ 'name': 'bond0',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'bond1': {'macAddr': '',
+ 'name': 'bond1',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'bond2': {'macAddr': '',
+ 'name': 'bond2',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'bond3': {'macAddr': '',
+ 'name': 'bond3',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'bond4': {'macAddr': '',
+ 'name': 'bond4',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'eth0': {'macAddr': '',
+ 'name': 'eth0',
+ 'rxDropped': '305433',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'up',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'},
+ 'eth1': {'macAddr': '',
+ 'name': 'eth1',
+ 'rxDropped': '0',
+ 'rxErrors': '0',
+ 'rxRate': '0.0',
+ 'speed': '1000',
+ 'state': 'down',
+ 'txDropped': '0',
+ 'txErrors': '0',
+ 'txRate': '0.0'}},
+ 'rxDropped': '305433',
+ 'rxRate': '0.00',
+ 'statsAge': '1.17',
+ 'storageDomains': {'6589d50f-9558-4377-b0e2-b2456d491866':
{'code': 0,
+
'delay': '0.00183606147766',
+
'lastCheck': '7.5',
+
'valid': True},
+ 'ee8e704f-dc3f-418f-806c-8826cb0d07ba':
{'code': 0,
+
'delay': '0.00101399421692',
+
'lastCheck': '7.5',
+
'valid': True}},
+ 'swapFree': 5946,
+ 'swapTotal': 6079,
+ 'thpState': 'always',
+ 'txDropped': '0',
+ 'txRate': '0.00',
+ 'vmActive': 1,
+ 'vmCount': 1,
+ 'vmMigrating': 0},
+ 'status': {'code': 0, 'message': 'Done'}}),
+]
+
+testVMs_apidata = [
+ APIData('Global', 'getVMList',
+ {'status': {'code': 0, 'message': 'Done'},
+ 'vmList': [{'status': 'Up', 'vmId':
'ebe00e6e-386f-4705-a92f-d5f497bd2a1e'}]}),
+ APIData('Global', 'getVMList',
+ {'status': {'code': 0, 'message': 'Done'},
+ 'vmList': [{'acpiEnable': 'true',
+ 'clientIp': '',
+ 'cpuType': 'Opteron_G1',
+ 'custom':
{'device_c6315666-b158-4626-9003-c6bd964d03ef':
'VmId=ebe00e6e-386f-4705-a92f-d5f497bd2a1e,DeviceId=c6315666-b158-4626-9003-c6bd964d03ef,Device=usb,Type=controller,BootOrder=0,SpecParams={},Address={bus=0x00,
domain=0x0000, type=pci, slot=0x01,
function=0x2},IsManaged=false,IsPlugged=true,IsReadOnly=false,alias=usb0',
+
'device_c6315666-b158-4626-9003-c6bd964d03efdevice_4bbcfe38-bce8-433f-bf2d-33ced8452f44':
'VmId=ebe00e6e-386f-4705-a92f-d5f497bd2a1e,DeviceId=4bbcfe38-bce8-433f-bf2d-33ced8452f44,Device=ide,Type=controller,BootOrder=0,SpecParams={},Address={bus=0x00,
domain=0x0000, type=pci, slot=0x01,
function=0x1},IsManaged=false,IsPlugged=true,IsReadOnly=false,alias=ide0',
+
'device_c6315666-b158-4626-9003-c6bd964d03efdevice_4bbcfe38-bce8-433f-bf2d-33ced8452f44device_0c855d2e-aaa6-4444-9a8d-3fa9e89998e3':
'VmId=ebe00e6e-386f-4705-a92f-d5f497bd2a1e,DeviceId=0c855d2e-aaa6-4444-9a8d-3fa9e89998e3,Device=virtio-serial,Type=controller,BootOrder=0,SpecParams={},Address={bus=0x00,
domain=0x0000, type=pci, slot=0x04,
function=0x0},IsManaged=false,IsPlugged=true,IsReadOnly=false,alias=virtio-serial0',
+
'device_c6315666-b158-4626-9003-c6bd964d03efdevice_4bbcfe38-bce8-433f-bf2d-33ced8452f44device_0c855d2e-aaa6-4444-9a8d-3fa9e89998e3device_9378e8f9-99cf-4651-9fb8-42a3177f5ba9':
'VmId=ebe00e6e-386f-4705-a92f-d5f497bd2a1e,DeviceId=9378e8f9-99cf-4651-9fb8-42a3177f5ba9,Device=unix,Type=channel,BootOrder=0,SpecParams={},Address={port=1,
bus=0, controller=0,
type=virtio-serial},IsManaged=false,IsPlugged=true,IsReadOnly=false,alias=channel0',
+
'device_c6315666-b158-4626-9003-c6bd964d03efdevice_4bbcfe38-bce8-433f-bf2d-33ced8452f44device_0c855d2e-aaa6-4444-9a8d-3fa9e89998e3device_9378e8f9-99cf-4651-9fb8-42a3177f5ba9device_c5b7c45c-5a12-408b-81c5-5f02843571a5':
'VmId=ebe00e6e-386f-4705-a92f-d5f497bd2a1e,DeviceId=c5b7c45c-5a12-408b-81c5-5f02843571a5,Device=unix,Type=channel,BootOrder=0,SpecParams={},Address={port=2,
bus=0, controller=0,
type=virtio-serial},IsManaged=false,IsPlugged=true,IsReadOnly=false,alias=channel1'},
+ 'devices': [{'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x2',
+ 'slot': '0x01',
+ 'type': 'pci'},
+ 'alias': 'usb0',
+ 'device': 'usb',
+ 'deviceId':
'c6315666-b158-4626-9003-c6bd964d03ef',
+ 'specParams': {},
+ 'type': 'controller'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x0',
+ 'slot': '0x02',
+ 'type': 'pci'},
+ 'alias': 'video0',
+ 'device': 'qxl',
+ 'deviceId':
'53bf8fdb-c4a2-4a02-8190-dd5e59836d12',
+ 'specParams': {'vram': '65536'},
+ 'type': 'video'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x0',
+ 'slot': '0x03',
+ 'type': 'pci'},
+ 'alias': 'net0',
+ 'device': 'bridge',
+ 'deviceId':
'f70d6ad8-1ec1-4f82-b5ec-fbcc6356c700',
+ 'macAddr': '00:1a:4a:16:01:53',
+ 'network': 'ovirtmgmt',
+ 'nicModel': 'pv',
+ 'specParams': {},
+ 'type': 'interface'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x0',
+ 'slot': '0x06',
+ 'type': 'pci'},
+ 'alias': 'balloon0',
+ 'device': 'memballoon',
+ 'deviceId':
'bf9d331c-924c-443b-8d2c-8955cfc1ac3f',
+ 'specParams': {'model': 'virtio'},
+ 'type': 'balloon'},
+ {'address': {'bus': '1',
+ 'controller': '0',
+ 'target': '0',
+ 'type': 'drive',
+ 'unit': '0'},
+ 'alias': 'ide0-1-0',
+ 'device': 'cdrom',
+ 'deviceId':
'aa56e486-dd13-4fe7-a37c-ee627b1bbb0c',
+ 'iface': 'ide',
+ 'index': '2',
+ 'name': 'hdc',
+ 'path':
'/rhev/data-center/342d186f-3556-442e-b0b0-0b083403138d/ee8e704f-dc3f-418f-806c-8826cb0d07ba/images/11111111-1111-1111-1111-111111111111/Fedora-17-x86_64-netinst.iso',
+ 'readonly': 'True',
+ 'specParams': {'path':
'Fedora-17-x86_64-netinst.iso'},
+ 'type': 'disk'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x0',
+ 'slot': '0x05',
+ 'type': 'pci'},
+ 'alias': 'virtio-disk0',
+ 'apparentsize': '8589934592',
+ 'bootOrder': '1',
+ 'device': 'disk',
+ 'deviceId':
'c6cb49eb-612f-422c-89aa-a6a5d79198d3',
+ 'domainID':
'6589d50f-9558-4377-b0e2-b2456d491866',
+ 'format': 'raw',
+ 'iface': 'virtio',
+ 'imageID':
'c6cb49eb-612f-422c-89aa-a6a5d79198d3',
+ 'index': 0,
+ 'name': 'vda',
+ 'needExtend': False,
+ 'optional': 'false',
+ 'path':
'/rhev/data-center/342d186f-3556-442e-b0b0-0b083403138d/6589d50f-9558-4377-b0e2-b2456d491866/images/c6cb49eb-612f-422c-89aa-a6a5d79198d3/734d94c2-ab45-479a-b1dd-52c799cabd92',
+ 'poolID':
'342d186f-3556-442e-b0b0-0b083403138d',
+ 'propagateErrors': 'off',
+ 'readonly': 'False',
+ 'reqsize': '0',
+ 'shared': 'false',
+ 'specParams': {},
+ 'truesize': '3354484736',
+ 'type': 'disk',
+ 'volumeChain': [{'domainID':
'6589d50f-9558-4377-b0e2-b2456d491866',
+ 'imageID':
'c6cb49eb-612f-422c-89aa-a6a5d79198d3',
+ 'path':
'/rhev/data-center/342d186f-3556-442e-b0b0-0b083403138d/6589d50f-9558-4377-b0e2-b2456d491866/images/c6cb49eb-612f-422c-89aa-a6a5d79198d3/734d94c2-ab45-479a-b1dd-52c799cabd92',
+ 'volumeID':
'734d94c2-ab45-479a-b1dd-52c799cabd92'}],
+ 'volumeID':
'734d94c2-ab45-479a-b1dd-52c799cabd92'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x1',
+ 'slot': '0x01',
+ 'type': 'pci'},
+ 'alias': 'ide0',
+ 'device': 'ide',
+ 'type': 'controller'},
+ {'address': {'bus': '0x00',
+ 'domain': '0x0000',
+ 'function': '0x0',
+ 'slot': '0x04',
+ 'type': 'pci'},
+ 'alias': 'virtio-serial0',
+ 'device': 'virtio-serial',
+ 'type': 'controller'},
+ {'address': {'bus': '0',
+ 'controller': '0',
+ 'port': '1',
+ 'type': 'virtio-serial'},
+ 'alias': 'channel0',
+ 'device': 'unix',
+ 'type': 'channel'},
+ {'address': {'bus': '0',
+ 'controller': '0',
+ 'port': '2',
+ 'type': 'virtio-serial'},
+ 'alias': 'channel1',
+ 'device': 'unix',
+ 'type': 'channel'}],
+ 'display': 'vnc',
+ 'displayIp': '0',
+ 'displayPort': '5900',
+ 'displaySecurePort': '-1',
+ 'emulatedMachine': 'pc-0.14',
+ 'guestIPs': '',
+ 'keyboardLayout': 'en-us',
+ 'kvmEnable': 'true',
+ 'memSize': 1024,
+ 'nicModel': 'rtl8139,pv',
+ 'nice': '0',
+ 'pauseCode': 'NOERR',
+ 'pid': '30508',
+ 'pitReinjection': 'false',
+ 'smp': '1',
+ 'smpCoresPerSocket': '1',
+ 'status': 'Up',
+ 'tabletEnable': 'true',
+ 'timeOffset': '0',
+ 'transparentHugePages': 'true',
+ 'username': 'Unknown',
+ 'vmId': 'ebe00e6e-386f-4705-a92f-d5f497bd2a1e',
+ 'vmName': 'cloudy-1',
+ 'vmType': 'kvm'}]})
+]
+
+testVolumes_apidata = [
+ APIData('Global', 'getConnectedStoragePools',
+ {'poollist': ['342d186f-3556-442e-b0b0-0b083403138d'],
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('Global', 'getStorageDomains',
+ {'domlist': ['6589d50f-9558-4377-b0e2-b2456d491866',
+ 'ee8e704f-dc3f-418f-806c-8826cb0d07ba'],
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('StorageDomain', 'getImages',
+ {'imageslist': ['bfbd5999-fd32-43b5-a85f-58cb9b37c628',
+ '4f21e899-0cb8-47de-a632-8feeaac34652',
+ 'c6cb49eb-612f-422c-89aa-a6a5d79198d3',
+ '1fe9495b-592c-4b37-997c-70d35f7cfee4'],
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('Image', 'getVolumes',
+ {'status': {'code': 0, 'message': 'OK'},
+ 'uuidlist': ['734d94c2-ab45-479a-b1dd-52c799cabd92']}),
+ APIData('Volume', 'getInfo',
+ {'info': {'apparentsize': '8589934592',
+ 'capacity': '8589934592',
+ 'children': [],
+ 'ctime': '1345143109',
+ 'description': '',
+ 'disktype': '2',
+ 'domain': '6589d50f-9558-4377-b0e2-b2456d491866',
+ 'format': 'RAW',
+ 'image': 'c6cb49eb-612f-422c-89aa-a6a5d79198d3',
+ 'legality': 'LEGAL',
+ 'mtime': '1345143109',
+ 'parent': '00000000-0000-0000-0000-000000000000',
+ 'pool': '',
+ 'status': 'OK',
+ 'truesize': '3369029632',
+ 'type': 'SPARSE',
+ 'uuid': '734d94c2-ab45-479a-b1dd-52c799cabd92',
+ 'voltype': 'LEAF'},
+ 'status': {'code': 0, 'message': 'OK'}}),
+ APIData('Volume', 'getSize',
+ {'apparentsize': '8589934592',
+ 'status': {'code': 0, 'message': 'OK'},
+ 'truesize': '3369156608'}),
+]
diff --git a/tests/apiTests.py b/tests/apiTests.py
new file mode 100644
index 0000000..afd8cbb
--- /dev/null
+++ b/tests/apiTests.py
@@ -0,0 +1,239 @@
+#
+# Copyright 2012 Adam Litke, IBM Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+import logging
+import os
+import os.path
+
+from testrunner import VdsmTestCase as TestCaseBase
+from vdsm import constants
+import apiData
+from gi.repository import vdsm as libvdsm
+from gi.repository import GObject
+
+ip = '0.0.0.0'
+port = 9824
+_fakeret = {}
+
+api_whitelist = ('StorageDomain.Classes', 'StorageDomain.Types',
+ 'Volume.Formats', 'Volume.Types', 'Volume.Roles',
'Image.DiskTypes')
+
+
+def getFakeAPI():
+ """
+ Create a Mock API module for testing. Mock API will return data from
+ the _fakeret global variable instead of calling into vdsm. _fakeret is
+ expected to have the following format:
+
+ {
+ '<class1>': {
+ '<func1>': [ <ret1>, <ret2>, ... ],
+ '<func2>': [ ... ],
+ }, '<class2>': {
+ ...
+ }
+ }
+ """
+ class FakeObj(object):
+ def __new__(cls, *args, **kwargs):
+ return object.__new__(cls)
+
+ def default(self, *args, **kwargs):
+ try:
+ return _fakeret[self.type][self.lastFunc].pop(0)
+ except (KeyError, IndexError):
+ raise Exception("No API data avilable for %s.%s" % \
+ (self.type, self.lastFunc))
+
+ def __getattr__(self, name):
+ # While we are constructing the API module, use the normal getattr
+ if 'API' not in sys.modules:
+ return object.__getattr__(name)
+ self.lastFunc = name
+ return self.default
+
+ import sys
+ import imp
+ from new import classobj
+
+ _API = __import__('API', globals(), locals(), {}, -1)
+ _newAPI = imp.new_module('API')
+
+ for obj in ('Global', 'ConnectionRefs', 'StorageDomain',
'Image', 'Volume',
+ 'Task', 'StoragePool', 'VM'):
+ cls = classobj(obj, (FakeObj,), {'type': obj})
+ setattr(_newAPI, obj, cls)
+
+ # Apply the whitelist to our version of API
+ for name in api_whitelist:
+ parts = name.split('.')
+ dst_obj = _newAPI
+ src_obj = _API
+ # Walk the object hierarchy copying each component of the whitelisted
+ # attribute from the real API to our fake one
+ for obj in parts:
+ src_obj = getattr(src_obj, obj)
+ try:
+ dst_obj = getattr(dst_obj, obj)
+ except AttributeError:
+ setattr(dst_obj, obj, src_obj)
+
+ # Install our fake API into the module table for use by the whole program
+ sys.modules['API'] = _newAPI
+
+
+def findSchema():
+ """
+ Find the API schema file whether we are running tests from the source dir
+ or from the tests install location
+ """
+ scriptdir = os.path.dirname(__file__)
+ localpath = os.path.join(scriptdir, '../vdsm_api/vdsmapi-schema.json')
+ installedpath = os.path.join(constants.P_VDSM, 'vdsmapi-schema.json')
+ for f in localpath, installedpath:
+ if os.access(f, os.R_OK):
+ return f
+ raise Exception("Unable to find schema in %s or %s",
+ localpath, installedpath)
+
+
+def setUpModule():
+ """
+ Set up the environment for all tests:
+ 1. Override the API so we can program our own return values
+ 2. Start an embedded server to process our requests
+ """
+ GObject.threads_init()
+
+ log = logging.getLogger('apiTests')
+ handler = logging.StreamHandler()
+ fmt_str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
+ formatter = logging.Formatter(fmt_str)
+ handler.setFormatter(formatter)
+ handler.setLevel(logging.INFO)
+ log.addHandler(handler)
+
+ schema = findSchema()
+ getFakeAPI()
+ import BindingJsonRpc
+ import Bridge
+ bridge = Bridge.DynamicBridge(schema)
+ server = BindingJsonRpc.BindingJsonRpc(bridge, log, ip, port)
+ server.start()
+
+
+class APITestBase(TestCaseBase):
+ def expectAPI(self, obj, meth, retval):
+ global _fakeret
+ if obj not in _fakeret:
+ _fakeret[obj] = {}
+ if meth not in _fakeret[obj]:
+ _fakeret[obj][meth] = []
+ _fakeret[obj][meth].append(retval)
+
+ def programAPI(self, key):
+ key += '_apidata'
+ for item in getattr(apiData, key):
+ self.expectAPI(item.obj, item.meth, item.data)
+
+ def clearAPI(self):
+ global _fakeret
+ _fakeret = {}
+
+
+class APITest(APITestBase):
+ def setUp(self):
+ self.host = libvdsm.Host.new(ip, port, True)
+ self.host.connect()
+ self.clearAPI()
+
+ def tearDown(self):
+ self.host.disconnect()
+ self.host = None
+
+ def testPing(self):
+ self.programAPI('testPing')
+ self.host.ping()
+
+ def testCapabilities(self):
+ self.programAPI('testCapabilities')
+ caps = self.host.getCapabilities()
+ self.assertEquals('4.10', caps.get_software_version())
+ self.assertTrue(caps.get_kvmEnabled())
+
+ networks = caps.get_networks()
+ ovirtNet = networks['ovirtmgmt']
+ self.assertTrue(ovirtNet.get_bridged())
+ ovirtBrigedNet = ovirtNet.get_NetInfoBridgedNetwork()
+ self.assertTrue('eth0' in ovirtBrigedNet.get_ports())
+
+ def testStorageDomains(self):
+ self.programAPI('testStorageDomains')
+ spList = self.host.getConnectedStoragePools()
+ spUUID = spList[0].get_storagepoolID()
+ sdList = self.host.getStorageDomains(spUUID, 0, 0, None)
+
+ expected = [('data2', 23935705088, 44233609216),
+ ('isos', 23935844352, 44233654272)]
+ for (i, sd) in enumerate(sdList):
+ name, free, total = expected[i]
+ stats = sd.getStats()
+ info = sd.getInfo()
+ self.assertEquals(name, info.get_name())
+ self.assertEquals(free, stats.get_diskfree())
+ self.assertEquals(total, stats.get_disktotal())
+
+ def testStats(self):
+ self.programAPI('testStats')
+ stats = self.host.getStats()
+ self.assertEquals(0.54, stats.get_cpuLoad())
+ # XXX: bindings do not seem to support the to_string method for enums
+ # stats.get_thpState().to_string()
+ self.assertEquals('always', stats.get_thpState().value_nick)
+
+ def testVMs(self):
+ self.programAPI('testVMs')
+ vms = self.host.getVMList([])
+ self.assertEquals(1, len(vms))
+ info = vms[0].getInfo()
+ self.assertEquals('cloudy-1', info.get_vmName())
+ self.assertEquals('up', info.get_status().value_nick)
+
+ def testVolumes(self):
+ self.programAPI('testVolumes')
+ spList = self.host.getConnectedStoragePools()
+ spUUID = spList[0].get_storagepoolID()
+ sdList = self.host.getStorageDomains(spUUID, 0, 0, None)
+ self.assertEquals(2, len(sdList))
+ sd = sdList[0]
+ imgList = sd.getImages()
+ self.assertEquals(4, len(imgList))
+ img = imgList[2]
+ volList = img.getVolumes()
+ self.assertEquals(1, len(volList))
+ vol = volList[0]
+ info = vol.getInfo()
+ self.assertEquals('raw', info.get_format().value_nick)
+ self.assertEquals('sparse', info.get_allocType().value_nick)
+ self.assertEquals(8589934592, info.get_apparentsize())
+
+ # Test return value rewriting
+ sizeInfo = vol.getSize()
+ self.assertEquals(3369156608, sizeInfo.get_truesize())
diff --git a/tests/run_tests.sh.in b/tests/run_tests.sh.in
index e00beeb..7e74994 100644
--- a/tests/run_tests.sh.in
+++ b/tests/run_tests.sh.in
@@ -1,3 +1,6 @@
#!/bin/sh
prefix="@prefix@"
-LC_ALL=C PYTHONPATH="@datarootdir@/vdsm" @PYTHON@
@top_srcdir(a)/tests/testrunner.py $@
+exec_prefix="@exec_prefix@"
+LC_ALL=C PYTHONPATH="@datarootdir@/vdsm" \
+GI_TYPELIB_PATH="@vdsmtypelibdir@" \
+@PYTHON@ @top_srcdir(a)/tests/testrunner.py $@
diff --git a/tests/run_tests_local.sh.in b/tests/run_tests_local.sh.in
index fc4ac37..0206de6 100644
--- a/tests/run_tests_local.sh.in
+++ b/tests/run_tests_local.sh.in
@@ -1,2 +1,8 @@
#!/bin/sh
-PYTHONDONTWRITEBYTECODE=1 LC_ALL=C
PYTHONPATH="@builddir@/vdsm:@top_srcdir@/vdsm:@top_srcdir@/vdsm_cli:$PYTHONPATH"
@PYTHON@ @top_srcdir(a)/tests/testrunner.py --local-modules $@
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+PYTHONDONTWRITEBYTECODE=1 LC_ALL=C \
+PYTHONPATH="@builddir@/vdsm:@top_srcdir@/vdsm:@top_srcdir@/vdsm_cli:@top_srcdir@/vdsm_api:$PYTHONPATH"
\
+GI_TYPELIB_PATH="@top_srcdir@/vdsm_api:@vdsmtypelibdir@" \
+LD_LIBRARY_PATH="@top_srcdir(a)/vdsm_api/.libs" \
+@PYTHON@ @top_srcdir(a)/tests/testrunner.py --local-modules $@
diff --git a/vdsm_api/Bridge.py b/vdsm_api/Bridge.py
index dd105dc..8af72c4 100644
--- a/vdsm_api/Bridge.py
+++ b/vdsm_api/Bridge.py
@@ -239,8 +239,12 @@
return {'params': ret['params'], 'migrationPort':
ret['migrationPort']}
-def XXX(ret):
- return None
+def Volume_getsize_Ret(ret):
+ """
+ Merge the two sizes into a single dictionary result.
+ """
+ return {'truesize': ret['truesize'], 'apparentsize':
ret['apparentsize']}
+
##
# Possible ways to override a command:
@@ -310,7 +314,7 @@
'Volume_delete': {'ret': 'uuid'},
'Volume_getInfo': {'ret': 'info'},
'Volume_getPath': {'ret': 'path'},
- 'Volume_getSize': {'ret': XXX},
+ 'Volume_getSize': {'ret': Volume_getsize_Ret},
'Host_getAllTasks': {'ret': 'TasksDetails'},
}
--
To view, visit
http://gerrit.ovirt.org/8406
To unsubscribe, visit
http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifbf032ed569a42a4eceeedfa536e737a2f8ded6b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Adam Litke <agl(a)us.ibm.com>