def test_block_threshold_stale_path(self): conf = drive_config(diskType=DISK_TYPE.BLOCK, path='/new/path') drive = Drive(self.log, **conf) drive.threshold_state = BLOCK_THRESHOLD.SET drive.on_block_threshold('/old/path') self.assertEqual(drive.threshold_state, BLOCK_THRESHOLD.SET)
def test_parse_volume_chain_network(self): volume_chain = [ {'path': 'server:/vol/11111111-1111-1111-1111-111111111111', 'volumeID': '11111111-1111-1111-1111-111111111111'}, {'path': 'server:/vol/22222222-2222-2222-2222-222222222222', 'volumeID': '22222222-2222-2222-2222-222222222222'} ] conf = drive_config(volumeChain=volume_chain) drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **conf) disk_xml = etree.fromstring(""" <disk> <source name='server:/vol/11111111-1111-1111-1111-111111111111'/> <backingStore type='network' index='1'> <source name='server:/vol/22222222-2222-2222-2222-222222222222'/> <backingStore/> </backingStore> </disk>""") chain = drive.parse_volume_chain(disk_xml) expected = [ storage.VolumeChainEntry( path='server:/vol/22222222-2222-2222-2222-222222222222', allocation=None, uuid='22222222-2222-2222-2222-222222222222', index=1), storage.VolumeChainEntry( path='server:/vol/11111111-1111-1111-1111-111111111111', allocation=None, uuid='11111111-1111-1111-1111-111111111111', index=None) ] self.assertEqual(chain, expected)
def test_migrate_network_to_block(self): conf = drive_config(diskType=DISK_TYPE.NETWORK, path='pool/volume') drive = Drive(self.log, **conf) # Migrate drive to block domain... drive.path = '/blockdomain/volume' drive.diskType = DISK_TYPE.BLOCK self.assertEqual(DISK_TYPE.BLOCK, drive.diskType)
def test_migrate_from_block_to_network(self): conf = drive_config(path='/blockdomain/volume') drive = Drive(self.log, diskType=DISK_TYPE.BLOCK, **conf) # Migrate drive to network disk... drive.path = "pool/volume" drive.diskType = DISK_TYPE.NETWORK self.assertEqual(DISK_TYPE.NETWORK, drive.diskType)
def test_migrate_from_block_to_file(self): conf = drive_config(path='/blockdomain/volume') drive = Drive(self.log, diskType=DISK_TYPE.BLOCK, **conf) # Migrate drive to file domain... drive.diskType = DISK_TYPE.FILE drive.path = "/filedomain/volume" self.assertEqual(DISK_TYPE.FILE, drive.diskType)
def test_path_change_reset_threshold_state(self): conf = drive_config(diskType=DISK_TYPE.BLOCK, path='/old/path') drive = Drive(self.log, **conf) # Simulating drive in SET state drive.threshold_state = BLOCK_THRESHOLD.SET drive.path = '/new/path' self.assertEqual(drive.threshold_state, BLOCK_THRESHOLD.UNSET)
def test_block_threshold_set_state(self): path = '/old/path' conf = drive_config(diskType=DISK_TYPE.BLOCK, path=path) drive = Drive(self.log, **conf) drive.threshold_state = BLOCK_THRESHOLD.SET drive.on_block_threshold(path) self.assertEqual(drive.threshold_state, BLOCK_THRESHOLD.EXCEEDED)
def test_migrate_network_to_block(self): conf = drive_config(diskType=DISK_TYPE.NETWORK, path='pool/volume') drive = Drive(self.log, **conf) self.assertTrue(drive.networkDev) # Migrate drive to block domain... drive.path = '/blockdomain/volume' drive.diskType = None self.assertTrue(drive.blockDev)
def test_migrate_from_block_to_network(self): conf = drive_config(path='/blockdomain/volume') drive = Drive(self.log, **conf) self.assertTrue(drive.blockDev) # Migrate drive to network disk... drive.path = "pool/volume" drive.diskType = DISK_TYPE.NETWORK self.assertFalse(drive.blockDev)
def test_migrate_from_block_to_file(self): conf = drive_config(path='/blockdomain/volume') drive = Drive(self.log, **conf) self.assertTrue(drive.blockDev) # Migrate drive to file domain... utils.isBlockDevice = lambda path: False drive.path = "/filedomain/volume" self.assertFalse(drive.blockDev)
def test_set_iotune(self, iotune): conf = drive_config( serial='54-a672-23e5b495a9ea', ) drive = Drive(self.log, **conf) with self.assertRaises(Exception): drive.iotune = iotune
def test_file(self): drive = Drive(self.log, **self.conf) expected = """ <disk name='vda' snapshot='external' type='file'> <source file='/image' type='file'/> </disk> """ snap_info = {'path': '/image', 'device': 'disk'} actual = drive.get_snapshot_xml(snap_info) self.assertXMLEqual(vmxml.format_xml(actual), expected)
def check_leases(self, conf): drive = Drive(self.log, **conf) leases = list(drive.getLeasesXML()) self.assertEqual(1, len(leases)) xml = """ <lease> <key>vol_id</key> <lockspace>dom_id</lockspace> <target offset="0" path="path" /> </lease> """ self.assertXMLEqual(vmxml.format_xml(leases[0]), xml)
def test_block(self): drive = Drive(self.log, **self.conf) drive._blockDev = True expected = """ <disk name='vda' snapshot='external' type='block'> <source dev='/dev/dm-1' type='block'/> </disk> """ snap_info = {'path': '/dev/dm-1', 'device': 'disk'} actual = drive.get_snapshot_xml(snap_info) self.assertXMLEqual(vmxml.format_xml(actual), expected)
def check_leases(self, conf): drive = Drive(self.log, diskType=DISK_TYPE.FILE, **conf) leases = list(drive.getLeasesXML()) self.assertEqual(1, len(leases)) xml = """ <lease> <key>vol_id</key> <lockspace>dom_id</lockspace> <target offset="0" path="path" /> </lease> """ self.assertXMLEqual(xmlutils.tostring(leases[0]), xml)
def make_env(self): with namedTemporaryDir() as tmpdir: """ Below we imitate that behaviour by providing two different directories under /rhv/data-center root and one of those directories is a symlink to another one. We fill VolumeChain with real directory and use symlinked directory in XML, emulating libvirt reply. """ dc_base = os.path.join(tmpdir, "dc") run_base = os.path.join(tmpdir, "run") images_path = os.path.join(dc_base, "images") os.makedirs(images_path) os.symlink(dc_base, run_base) dc_top_vol = os.path.join( images_path, "11111111-1111-1111-1111-111111111111") dc_base_vol = os.path.join( images_path, "22222222-2222-2222-2222-222222222222") make_file(dc_top_vol) make_file(dc_base_vol) run_top_vol = os.path.join( run_base, "images", "11111111-1111-1111-1111-111111111111") run_base_vol = os.path.join( run_base, "images", "22222222-2222-2222-2222-222222222222") volume_chain = [ {'path': dc_top_vol, 'volumeID': '11111111-1111-1111-1111-111111111111'}, {'path': dc_base_vol, 'volumeID': '22222222-2222-2222-2222-222222222222'} ] conf = drive_config(volumeChain=volume_chain) drive = Drive(self.log, **conf) drive._blockDev = True yield VolumeChainEnv( drive, run_top_vol, run_base_vol )
def test_block(self): drive = Drive(self.log, diskType=DISK_TYPE.BLOCK, **self.conf) expected = """ <disk name='vda' snapshot='external' type='block'> <source dev='/dev/dm-1' type='block'> <seclabel model="dac" relabel="no" type="none" /> </source> </disk> """ snap_info = {'path': '/dev/dm-1', 'device': 'disk'} actual = drive.get_snapshot_xml(snap_info) self.assertXMLEqual(xmlutils.tostring(actual), expected)
def test_parse_volume_chain_network(self): volume_chain = [{ 'path': 'server:/vol/11111111-1111-1111-1111-111111111111', 'volumeID': '11111111-1111-1111-1111-111111111111' }, { 'path': 'server:/vol/22222222-2222-2222-2222-222222222222', 'volumeID': '22222222-2222-2222-2222-222222222222' }] conf = drive_config(volumeChain=volume_chain) drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **conf) disk = etree.fromstring(""" <disk type='network'> <source name='server:/vol/11111111-1111-1111-1111-111111111111' index='1'> <seclabel model="dac" relabel="no" type="none" /> </source> <backingStore type='network' index='3'> <source name='server:/vol/22222222-2222-2222-2222-222222222222'/> <backingStore/> </backingStore> </disk>""") chain = drive.parse_volume_chain(disk) expected = [ storage.VolumeChainEntry( path='server:/vol/22222222-2222-2222-2222-222222222222', uuid='22222222-2222-2222-2222-222222222222', index=3), storage.VolumeChainEntry( path='server:/vol/11111111-1111-1111-1111-111111111111', uuid='11111111-1111-1111-1111-111111111111', index=1) ] assert chain == expected
def test_network(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, protocol='gluster', **self.conf) expected = """ <disk name='vda' snapshot='external' type='network'> <source protocol='gluster' name='volume/11111111-1111-1111-1111-111111111111' type='network'> <host name="brick1.example.com" port="49152" transport="tcp"/> <host name="brick2.example.com" port="49153" transport="tcp"/> </source> </disk> """ snap_info = { 'protocol': 'gluster', 'path': 'volume/11111111-1111-1111-1111-111111111111', 'diskType': 'network', 'device': 'disk', 'hosts': [ { 'name': 'brick1.example.com', 'port': '49152', 'transport': 'tcp' }, { 'name': 'brick2.example.com', 'port': '49153', 'transport': 'tcp' } ] } actual = drive.get_snapshot_xml(snap_info) self.assertXMLEqual(xmlutils.tostring(actual), expected)
def make_env(self, disk_type): with namedTemporaryDir() as tmpdir: """ Below we imitate that behaviour by providing two different directories under /rhv/data-center root and one of those directories is a symlink to another one. We fill VolumeChain with real directory and use symlinked directory in XML, emulating libvirt reply. """ dc_base = os.path.join(tmpdir, "dc") run_base = os.path.join(tmpdir, "run") images_path = os.path.join(dc_base, "images") os.makedirs(images_path) os.symlink(dc_base, run_base) dc_top_vol = os.path.join(images_path, "11111111-1111-1111-1111-111111111111") dc_base_vol = os.path.join(images_path, "22222222-2222-2222-2222-222222222222") make_file(dc_top_vol) make_file(dc_base_vol) run_top_vol = os.path.join(run_base, "images", "11111111-1111-1111-1111-111111111111") run_base_vol = os.path.join( run_base, "images", "22222222-2222-2222-2222-222222222222") volume_chain = [{ 'path': dc_top_vol, 'volumeID': '11111111-1111-1111-1111-111111111111' }, { 'path': dc_base_vol, 'volumeID': '22222222-2222-2222-2222-222222222222' }] conf = drive_config(volumeChain=volume_chain) drive = Drive(self.log, diskType=disk_type, **conf) yield VolumeChainEnv(drive, run_top_vol, run_base_vol)
def make_drive(log, drive_conf, block_info): cfg = utils.picklecopy(drive_conf) cfg['path'] = block_info['path'] cfg['alias'] = 'alias_%d' % cfg["index"] add_uuids(cfg["index"], cfg) if 'diskReplicate' in cfg: add_uuids(cfg["index"] + REPLICA_BASE_INDEX, cfg['diskReplicate']) cfg["volumeChain"] = [{"path": cfg["path"], "volumeID": cfg["volumeID"]}] drive = Drive(log, **cfg) if (drive.format == "raw" and block_info["physical"] != block_info["capacity"]): raise RuntimeError("Invalid test data - " "raw disk capacity != physical: %s" % block_info) return drive
def make_drive(log, dom, irs, index, conf, block_info): cfg = utils.picklecopy(conf) cfg['index'] = index cfg['path'] = '/{iface}/{index}'.format(iface=cfg['iface'], index=cfg['index']) add_uuids(index, cfg) if 'diskReplicate' in cfg: add_uuids(index + REPLICA_BASE_INDEX, cfg['diskReplicate']) drive = Drive(log, **cfg) dom.block_info[drive.path] = utils.picklecopy(block_info) if (drive.format == "raw" and block_info["physical"] != block_info["capacity"]): raise RuntimeError("Invalid test data - " "raw disk capacity != physical: %s" % block_info) irs.set_drive_size(drive, block_info['physical']) return drive
def test_drive_exceeded_time(monkeypatch): conf = drive_config(diskType=DISK_TYPE.BLOCK, path="/path") drive = Drive(log, **conf) # Exceeded time not set yet. assert drive.exceeded_time is None # Setting threshold state does not set exceeded time. drive.threshold_state = BLOCK_THRESHOLD.SET assert drive.exceeded_time is None # Getting threshold event sets exceeded time. monkeypatch.setattr(time, "monotonic_time", lambda: 123.0) drive.on_block_threshold("/path") assert drive.exceeded_time == 123.0 # Changing threshold clears exceeded time. drive.threshold_state = BLOCK_THRESHOLD.SET assert drive.exceeded_time is None
def check_no_leases(self, conf): drive = Drive(self.log, diskType=DISK_TYPE.FILE, **conf) leases = list(drive.getLeasesXML()) self.assertEqual([], leases)
def test_floppy_file(self): conf = drive_config(device="floppy") drive = Drive(self.log, diskType=DISK_TYPE.FILE, **conf) assert DISK_TYPE.FILE == drive.diskType
def test_block_cdrom(self): conf = drive_config(device='cdrom') drive = Drive(self.log, diskType=DISK_TYPE.BLOCK, **conf) assert DISK_TYPE.BLOCK == drive.diskType
def test_next_size_limit(self, cursize): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) self.assertEqual(drive.getNextVolumeSize(cursize, self.CAPACITY), drive.getMaxVolumeSize(self.CAPACITY))
def test_set_none_type(self): conf = drive_config(diskType=DISK_TYPE.NETWORK, path='pool/volume') drive = Drive(self.log, **conf) with pytest.raises(exception.UnsupportedOperation): drive.diskType = None
def test_need_replica_chunked_threshold_unset(self): conf = drive_config(diskType=DISK_TYPE.FILE, format="cow") drive = Drive(self.log, **conf) drive.diskReplicate = replica(DISK_TYPE.BLOCK, format="cow") assert drive.needs_monitoring(events_enabled=True)
def check(self, device_conf, xml, diskType=DISK_TYPE.FILE): drive = Drive(self.log, diskType=diskType, **device_conf) self.assertXMLEqual(xmlutils.tostring(drive.getReplicaXML()), xml)
def test_floppy_set_invalid_diskType(self, diskType): conf = drive_config(device='floppy') drive = Drive(self.log, **conf) with pytest.raises(exception.UnsupportedOperation): drive.diskType = diskType
def test_base_not_found(self): drive = Drive(self.log, diskType=DISK_TYPE.FILE, **self.conf) with self.assertRaises(storage.VolumeNotFound): drive.volume_target("FFFFFFFF-FFFF-FFFF-FFFF-111111111111", self.actual_chain)
def test_top_volume(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) actual = drive.volume_target( "00000000-0000-0000-0000-000000000000", self.actual_chain) self.assertEqual(actual, None)
def test_replica(self, diskType, format, chunked): conf = drive_config(diskReplicate=replica(diskType, format=format), diskType=diskType) drive = Drive(self.log, **conf) assert drive.replicaChunked == chunked
def test_drive(self, device, diskType, format, chunked): conf = drive_config(device=device, format=format) drive = Drive(self.log, diskType=diskType, **conf) assert drive.chunked == chunked
def test_create_invalid_type(self): conf = drive_config(diskType='bad', path='pool/volume') with pytest.raises(exception.UnsupportedOperation): Drive(self.log, **conf)
def test_network_disk(self): conf = drive_config(diskType=DISK_TYPE.NETWORK) drive = Drive(self.log, **conf) assert DISK_TYPE.NETWORK == drive.diskType
def check(self, **kw): conf = drive_config(**kw) drive = Drive(self.log, **conf) with pytest.raises(ValueError): drive.getXML()
def test_need_replica_chunked_threshold_exceeded(self): conf = drive_config(diskType=DISK_TYPE.FILE, format="cow") drive = Drive(self.log, **conf) drive.diskReplicate = replica(DISK_TYPE.BLOCK, format="cow") drive.threshold_state = BLOCK_THRESHOLD.EXCEEDED assert drive.needs_monitoring(events_enabled=True)
def check(self, device_conf, xml): drive = Drive(self.log, **device_conf) self.assertXMLEqual(xmlutils.tostring(drive.getXML()), xml)
def test_file_disk(self): conf = drive_config(device='disk') drive = Drive(self.log, diskType=DISK_TYPE.FILE, **conf) assert DISK_TYPE.FILE == drive.diskType
def test_floppy_set_invalid_diskType(self, diskType): conf = drive_config(device='floppy') drive = Drive(self.log, **conf) with self.assertRaises(exception.UnsupportedOperation): drive.diskType = diskType
def test_max_size(self): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) size = utils.round(self.CAPACITY * drive.VOLWM_COW_OVERHEAD, MiB) assert drive.getMaxVolumeSize(self.CAPACITY) == size
def check_no_leases(self, conf): drive = Drive(self.log, diskType=DISK_TYPE.FILE, **conf) leases = list(drive.getLeasesXML()) assert [] == leases
def test_set_none_type(self): conf = drive_config(diskType=DISK_TYPE.NETWORK, path='pool/volume') drive = Drive(self.log, **conf) with self.assertRaises(exception.UnsupportedOperation): drive.diskType = None
def test_base_not_found(self): drive = Drive(self.log, diskType=DISK_TYPE.FILE, **self.conf) with pytest.raises(storage.VolumeNotFound): drive.volume_target("FFFFFFFF-FFFF-FFFF-FFFF-111111111111", self.actual_chain)
def test_no_need_chunked_threshold_set(self): conf = drive_config(diskType=DISK_TYPE.BLOCK, format="cow") drive = Drive(self.log, **conf) drive.threshold_state = BLOCK_THRESHOLD.SET assert not drive.needs_monitoring(events_enabled=True)
def test_internal_volume(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) actual = drive.volume_target("11111111-1111-1111-1111-111111111111", self.actual_chain) assert actual == "vda[1]"
def test_next_size(self, cursize): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) self.assertEqual(drive.getNextVolumeSize(cursize, self.CAPACITY), cursize + drive.volExtensionChunk)
def test_top_volume(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) actual = drive.volume_target("00000000-0000-0000-0000-000000000000", self.actual_chain) assert actual is None
def test_max_size(self): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) size = utils.round(self.CAPACITY * drive.VOLWM_COW_OVERHEAD, constants.MEGAB) self.assertEqual(drive.getMaxVolumeSize(self.CAPACITY), size)
def test_volume_missing(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) with pytest.raises(storage.VolumeNotFound): drive.volume_target("FFFFFFFF-FFFF-FFFF-FFFF-000000000000", self.actual_chain)
def test_no_replica(self): conf = drive_config(diskType=DISK_TYPE.FILE) drive = Drive(self.log, **conf) assert drive.replicaChunked is False
def check(self, shared, expected): conf = drive_config(diskType=DISK_TYPE.FILE) if shared: conf['shared'] = shared drive = Drive(self.log, **conf) assert drive.extSharedState == expected
def test_internal_volume(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) actual = drive.volume_target( "11111111-1111-1111-1111-111111111111", self.actual_chain) self.assertEqual(actual, "vda[1]")
def test_next_size(self, cursize): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) assert drive.getNextVolumeSize(cursize, self.CAPACITY) == \ cursize + drive.volExtensionChunk
def test_volume_missing(self): drive = Drive(self.log, diskType=DISK_TYPE.NETWORK, **self.conf) with self.assertRaises(storage.VolumeNotFound): drive.volume_target( "FFFFFFFF-FFFF-FFFF-FFFF-000000000000", self.actual_chain)
def test_next_size_limit(self, cursize): conf = drive_config(format='cow', diskType=DISK_TYPE.BLOCK) drive = Drive(self.log, **conf) assert drive.getNextVolumeSize(cursize, self.CAPACITY) == \ drive.getMaxVolumeSize(self.CAPACITY)