Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-127348 / 24.10 / Add iSCSI test test_33_no_lun_zero #13693

Merged
merged 1 commit into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions src/middlewared/middlewared/test/integration/assets/iscsi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import platform
import time
from pathlib import Path

from middlewared.test.integration.utils import call, run_on_runner, RunOnRunnerException

Expand Down Expand Up @@ -73,14 +74,15 @@ def iscsi_target(data):
call("iscsi.target.delete", target["id"])


def target_login_test(portal_ip, target_name):
def target_login_test(portal_ip, target_name, check_surfaced_luns=None):
if IS_LINUX:
return target_login_test_linux(portal_ip, target_name)
return target_login_test_linux(portal_ip, target_name, check_surfaced_luns)
else:
return target_login_test_freebsd(portal_ip, target_name)
return target_login_test_freebsd(portal_ip, target_name, check_surfaced_luns)


def target_login_test_linux(portal_ip, target_name):
def target_login_test_linux(portal_ip, target_name, check_surfaced_luns=None):
logged_in = False
try:
if os.geteuid():
# Non-root requires sudo
Expand All @@ -89,11 +91,27 @@ def target_login_test_linux(portal_ip, target_name):
iscsiadm = ['iscsiadm']
run_on_runner(iscsiadm + ['-m', 'discovery', '-t', 'sendtargets', '--portal', portal_ip])
run_on_runner(iscsiadm + ['-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--login'])
logged_in = True
if check_surfaced_luns is not None:
retries = 10
pattern = f'ip-{portal_ip}:3260-iscsi-{target_name}-lun-*'
by_path = Path('/dev/disk/by-path')
while retries:
luns = set(int(p.name.split('-')[-1]) for p in by_path.glob(pattern))
if luns == check_surfaced_luns:
break
time.sleep(1)
retries -= 1
assert check_surfaced_luns == luns, luns
except RunOnRunnerException:
return False
except AssertionError:
return False
else:
run_on_runner(iscsiadm + ['-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--logout'])
return True
finally:
if logged_in:
run_on_runner(iscsiadm + ['-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--logout'])


@contextlib.contextmanager
Expand All @@ -109,7 +127,7 @@ def iscsi_client_freebsd():
run_on_runner(['service', 'iscsid', 'onestop'])


def target_login_impl_freebsd(portal_ip, target_name):
def target_login_impl_freebsd(portal_ip, target_name, check_surfaced_luns=None):
run_on_runner(['iscsictl', '-A', '-p', portal_ip, '-t', target_name], check=False)
retries = 5
connected = False
Expand All @@ -128,11 +146,20 @@ def target_login_impl_freebsd(portal_ip, target_name):

assert connected is True, connected_clients

if check_surfaced_luns is not None:
luns = set()
for session in connected_clients.get('iscsictl', {}).get('session', []):
if session.get('name') == target_name and session.get('state') == 'Connected':
for lun in session.get('devices', {}).get('lun'):
if lun_val := lun.get('lun'):
luns.add(lun_val)
assert check_surfaced_luns == luns, luns


def target_login_test_freebsd(portal_ip, target_name):
def target_login_test_freebsd(portal_ip, target_name, check_surfaced_luns=None):
with iscsi_client_freebsd():
try:
target_login_impl_freebsd(portal_ip, target_name)
target_login_impl_freebsd(portal_ip, target_name, check_surfaced_luns)
except AssertionError:
return False
else:
Expand Down
37 changes: 29 additions & 8 deletions tests/api2/test_261_iscsi_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,21 @@
import ipaddress
import os
import random
import requests
import socket
import string
import sys
from time import sleep

import iscsi
import pyscsi
import pytest
from pyscsi.pyscsi.scsi_sense import sense_ascq_dict
from pytest_dependency import depends

apifolder = os.getcwd()
sys.path.append(apifolder)

import requests
from middlewared.service_exception import ValidationError, ValidationErrors
from middlewared.test.integration.assets.iscsi import target_login_test
from middlewared.test.integration.assets.pool import dataset, snapshot
from middlewared.test.integration.utils import call
from pyscsi.pyscsi.scsi_sense import sense_ascq_dict
from pytest_dependency import depends

from auto_config import ha, hostname, isns_ip, pool_name
from functions import SSH_TEST
from protocols import (initiator_name_supported, iscsi_scsi_connection,
Expand Down Expand Up @@ -2728,6 +2725,30 @@ def test_target_sizes(ipaddr):
test_target_sizes(controller2_ip)


def test_33_no_lun_zero():
"""
Verify that an iSCSI client can login to a target that is missing LUN 0 (and LUN 1)
and that report LUNs works as expected.
"""
iqn = f'{basename}:{target_name}'
with initiator_portal() as config:
portal_id = config['portal']['id']
with target(target_name, [{'portal': portal_id}]) as target_config:
target_id = target_config['id']
with dataset(dataset_name):
with file_extent(pool_name, dataset_name, "target.extent1", filesize=MB_100, extent_name="extent1") as extent1_config:
with file_extent(pool_name, dataset_name, "target.extent2", filesize=MB_256, extent_name="extent2") as extent2_config:
with target_extent_associate(target_id, extent1_config['id'], 100):
with target_extent_associate(target_id, extent2_config['id'], 101):
# libiscsi sends a TUR to the lun on connect, so cannot properly test using it.
# Let's actually login and check that the expected LUNs surface.
assert target_login_test(get_ip_addr(ip), iqn, {100, 101})

# With libiscsi we can also check that the expected LUNs are there
with iscsi_scsi_connection(ip, iqn, 100) as s:
_verify_luns(s, [100, 101])


def test_99_teardown(request):
# Disable iSCSI service
depends(request, ["iscsi_cmd_00"])
Expand Down
Loading