Skip to content

Commit

Permalink
NAS-132193 / 25.04 / Improve api2.test_262_iscsi_alua (#15251)
Browse files Browse the repository at this point in the history
* Add some SYNCHRONIZE CACHE (10) calls

* Add test__synchronize_cache

* Add some sleep to settle
  • Loading branch information
bmeagherix authored Dec 20, 2024
1 parent e22e643 commit 2d758a1
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
41 changes: 41 additions & 0 deletions tests/api2/test_261_iscsi_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2994,3 +2994,44 @@ def test__target_delete_extents(iscsi_running):
# Ensure the extent does not exist
extents = call('iscsi.extent.query', [['id', '=', target3_config['extent']['id']]])
assert len(extents) == 0, extents


@pytest.mark.parametrize('extent_type', ["FILE", "VOLUME"])
def test__synchronize_cache(iscsi_running, extent_type):
"""
Test that a SCSI SYNCHRONIZE CACHE command actually ensures data is
written to stable storage.
"""
def test_empty(path, extent_size_mb=5):
# Use dd to ensure we don't end up with stuff from page cache, plus we want
# to check what's actually ON DISK.
output = ssh(f'dd if={path} iflag=nocache oflag=nocache | od -a -', False)
return output.split() == ['0000000',
'nul', 'nul', 'nul', 'nul', 'nul', 'nul', 'nul', 'nul',
'nul', 'nul', 'nul', 'nul', 'nul', 'nul', 'nul', 'nul',
'*', oct(extent_size_mb * MB)[2:]]

name = f'{target_name}{extent_type.lower()}'
deadbeef = bytearray.fromhex('deadbeef') * 128
zeros = bytearray(512)
with initiator_portal() as config:
with configured_target(config, name, extent_type, extent_size_mb=5) as config:
if extent_type == 'FILE':
test_path = config['extent']['path']
else:
test_path = os.path.join('/dev', config['extent']['disk'])
iqn = f'{basename}:{name}'

# Ensure that to start the volume has NULL data
assert test_empty(test_path), 'Initial data is not empty'

with iscsi_scsi_connection(truenas_server.ip, iqn) as s:
# Write data SYNCHRONIZE and check the volume has non-NULL data
s.write16(0, 1, deadbeef)
s.synchronizecache10(0, 1)
assert test_empty(test_path) is False, 'Expected deadbeef data'

# Zero data SYNCHRONIZE and check the volume has NULL data again
s.write16(0, 1, zeros)
s.synchronizecache16(0, 1)
assert test_empty(test_path) is True, 'Expected zero data'
7 changes: 4 additions & 3 deletions tests/api2/test_262_iscsi_alua.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ def zero_luns(self, ip, config):
def zero_lun(s, target_num, lun, lun_config):
# Write zeros using WRITE SAME (16)
s.writesame16(0, self.BLOCKS, self.ZEROS)
s.synchronizecache10(0, self.BLOCKS)
self.visit_luns(ip, config, zero_lun)

def check_zero_luns(self, ip, config):
Expand Down Expand Up @@ -365,6 +366,7 @@ def page_pattern(self, target_num, lun):
def write_patterns(self, ip, config):
def write_pattern(s, target_num, lun, lun_config):
s.writesame16(1, 2, self.page_pattern(target_num, lun))
s.synchronizecache10(1, 2)
self.visit_luns(ip, config, write_pattern)

def check_patterns(self, ip, config):
Expand Down Expand Up @@ -465,12 +467,14 @@ def test_failover_complex_alua_config(self, fix_write_patterns, fix_get_domain):
if self.VERBOSE:
print('Powering off VM', domain)
poweroff_vm(domain)
sleep(3)

# Wait for the new MASTER to come up
newnode = self.wait_for_new_master(node)

# Wait for the failover event to complete
self.wait_for_failover_in_progress()
sleep(5)

if newnode == 'A':
new_ip = truenas_server.nodea_ip
Expand All @@ -484,9 +488,6 @@ def test_failover_complex_alua_config(self, fix_write_patterns, fix_get_domain):
print(f'Validate data pattern seen by Node {newnode}...')
self.check_patterns(new_ip, fix_write_patterns)

if self.VERBOSE:
print(f'Validate data pattern seen by Node {newnode}...')

@pytest.mark.timeout(900)
def test_boot_complex_alua_config(self, fix_write_patterns, fix_get_domain, fix_orig_active_node):
"""
Expand Down

0 comments on commit 2d758a1

Please sign in to comment.