Skip to content

Commit

Permalink
NAS-128506 / 24.10 / Fix test iscsi auth network (#13618)
Browse files Browse the repository at this point in the history
* Make tests capable less susceptible to network environment

* Add sudo before iscsiadm for non-root test runners

(cherry picked from commit dbbd64f)
  • Loading branch information
bmeagherix committed Apr 24, 2024
1 parent e981958 commit bd82486
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 37 deletions.
12 changes: 9 additions & 3 deletions src/middlewared/middlewared/test/integration/assets/iscsi.py
@@ -1,5 +1,6 @@
import contextlib
import json
import os
import time

from middlewared.test.integration.utils import call, run_on_runner, RunOnRunnerException, IS_LINUX
Expand Down Expand Up @@ -74,12 +75,17 @@ def target_login_test(portal_ip, target_name):

def target_login_test_linux(portal_ip, target_name):
try:
run_on_runner(['iscsiadm', '-m', 'discovery', '-t', 'sendtargets', '--portal', portal_ip])
run_on_runner(['iscsiadm', '-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--login'])
if os.geteuid():
# Non-root requires sudo
iscsiadm = ['sudo', 'iscsiadm']
else:
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'])
except RunOnRunnerException:
return False
else:
run_on_runner(['iscsiadm', '-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--logout'])
run_on_runner(iscsiadm + ['-m', 'node', '--targetname', target_name, '--portal', portal_ip, '--logout'])
return True


Expand Down
75 changes: 41 additions & 34 deletions tests/api2/test_iscsi_auth_network.py
@@ -1,32 +1,39 @@
import contextlib
import ipaddress
import os
import pytest
import socket
import sys

apifolder = os.getcwd()
sys.path.append(apifolder)
import pytest
from auto_config import ip

from middlewared.test.integration.assets.iscsi import target_login_test
from middlewared.test.integration.assets.pool import dataset
from middlewared.test.integration.utils import call, ssh

import contextlib
from auto_config import ip


def my_ip4(ipaddr=ip, port=80):
@pytest.fixture(scope="module")
def my_ip4():
"""See which of my IP addresses will be used to connect."""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((ipaddr,port))
assert result == 0
myip = sock.getsockname()[0]
sock.close()
# Check that we have an IPv4 address
socket.inet_pton(socket.AF_INET, myip)
return myip

# Things can be complicated e.g. my NAT between the test runner
# and the target system Therefore, first try using ssh into the
# remote system and see what it thinks our IP address is.
try:
myip = ipaddress.ip_address(ssh('echo $SSH_CLIENT').split()[0])
if myip.version != 4:
raise ValueError("Not a valid IPv4 address")
return str(myip)
except Exception:
# Fall back
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((ip, 80))
assert result == 0
myip = sock.getsockname()[0]
sock.close()
# Check that we have an IPv4 address
socket.inet_pton(socket.AF_INET, myip)
return myip


@contextlib.contextmanager
def portal():
portal_config = call('iscsi.portal.create', {'listen': [{'ip': ip}], 'discovery_authmethod': 'NONE'})
Expand Down Expand Up @@ -86,7 +93,7 @@ def configured_target_to_extent():
'initiator': initiator_config['id'],
'auth': None,
'authmethod': 'NONE'
}]
}]
) as target_config:
with extent('test_extent') as extent_config:
with target_extent(target_config['id'], extent_config['id'], 1):
Expand Down Expand Up @@ -123,28 +130,28 @@ def test_iscsi_auth_networks(valid):
f'{config["global"]["basename"]}:{config["target"]["name"]}',
) is valid


@pytest.mark.parametrize('valid', [True, False])
def test_iscsi_auth_networks_exact_ip(valid):
myip = my_ip4()
def test_iscsi_auth_networks_exact_ip(my_ip4, valid):
with configure_iscsi_service() as config:
call(
'iscsi.target.update',
config['target']['id'],
{'auth_networks': [f"{myip}/32"] if valid else ['8.8.8.8/32']}
{'auth_networks': [f"{my_ip4}/32"] if valid else ['8.8.8.8/32']}
)
portal_listen_details = config['portal']['listen'][0]
assert target_login_test(
f'{portal_listen_details["ip"]}:{portal_listen_details["port"]}',
f'{config["global"]["basename"]}:{config["target"]["name"]}',
) is valid


@pytest.mark.parametrize('valid', [True, False])
def test_iscsi_auth_networks_netmask_24(valid):
myip = my_ip4()
def test_iscsi_auth_networks_netmask_24(my_ip4, valid):
# good_ip will be our IP with the last byte cleared.
good_ip = '.'.join(myip.split('.')[:-1] + ['0'])
good_ip = '.'.join(my_ip4.split('.')[:-1] + ['0'])
# bad_ip will be our IP with the second last byte changed and last byte cleared
n = (int(myip.split('.')[2]) + 1) % 256
n = (int(my_ip4.split('.')[2]) + 1) % 256
bad_ip = '.'.join(good_ip.split('.')[:2] + [str(n), '0'])
with configure_iscsi_service() as config:
call(
Expand All @@ -158,16 +165,16 @@ def test_iscsi_auth_networks_netmask_24(valid):
f'{config["global"]["basename"]}:{config["target"]["name"]}',
) is valid


@pytest.mark.parametrize('valid', [True, False])
def test_iscsi_auth_networks_netmask_16(valid):
myip = my_ip4()
def test_iscsi_auth_networks_netmask_16(my_ip4, valid):
# good_ip will be our IP with the second last byte changed and last byte cleared
n = (int(myip.split('.')[2]) + 1) % 256
good_ip = '.'.join(myip.split('.')[:2] + [str(n), '0'])
n = (int(my_ip4.split('.')[2]) + 1) % 256
good_ip = '.'.join(my_ip4.split('.')[:2] + [str(n), '0'])
# bad_ip will be the good_ip with the second byte changed
l = good_ip.split('.')
n = (int(l[1]) + 1) % 256
bad_ip = '.'.join([l[0], str(n)] + l[-2:])
ip_list = good_ip.split('.')
n = (int(ip_list[1]) + 1) % 256
bad_ip = '.'.join([ip_list[0], str(n)] + ip_list[-2:])
with configure_iscsi_service() as config:
call(
'iscsi.target.update',
Expand Down

0 comments on commit bd82486

Please sign in to comment.