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 <[email protected]> --- 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@/tests/testrunner.py $@ +exec_prefix="@exec_prefix@" +LC_ALL=C PYTHONPATH="@datarootdir@/vdsm" \ +GI_TYPELIB_PATH="@vdsmtypelibdir@" \ +@PYTHON@ @top_srcdir@/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@/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@/vdsm_api/.libs" \ +@PYTHON@ @top_srcdir@/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 <[email protected]> _______________________________________________ vdsm-patches mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches
