Whamcloud - gitweb
LU-10973 lnet: LUTF Multi-Rail test suite 58/39458/54
authorAmir Shehata <ashehata@whamcloud.com>
Mon, 20 Jul 2020 21:04:32 +0000 (14:04 -0700)
committerOleg Drokin <green@whamcloud.com>
Tue, 4 Oct 2022 19:34:09 +0000 (19:34 +0000)
Added a test suite which covers various Multi-Rail functionality.

Test-Parameters: @lnet
Signed-off-by: Amir Shehata <ashehata@whamcloud.com>
Change-Id: I0480e59ebd97c943669194acbb1c80222e202a6e
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/39458
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: jsimmons <jsimmons@infradead.org>
Reviewed-by: Serguei Smirnov <ssmirnov@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
44 files changed:
lustre/tests/lutf/Makefile.am
lustre/tests/lutf/python/tests/suite_multi-rail/callbacks.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0005.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0015.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0020.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0025.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0030.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0035.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0040.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0045.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0050.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0055.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0070.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0090.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0095.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0096.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0105.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0110.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0115.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0120.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0125.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0131.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0145.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0155.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0165.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0170.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0171.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0172.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0173.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0175.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0176.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0185.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0190.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0195.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0205.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0210.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0215.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0220.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0225.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0230.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0235.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0245.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0260.py [new file with mode: 0644]
lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0310.py [new file with mode: 0644]

index c3b600f..8dd1190 100644 (file)
@@ -18,6 +18,7 @@ nobase_noinst_SCRIPTS += $(wildcard python/tests/*.py)
 nobase_noinst_SCRIPTS += $(wildcard python/tests-infra/*.py)
 nobase_noinst_SCRIPTS += $(wildcard python/tests/suite_dlc/*.py)
 nobase_noinst_SCRIPTS += $(wildcard python/tests/suite_samples/*.py)
+nobase_noinst_SCRIPTS += $(wildcard python/tests/suite_multi-rail/*.py)
 nobase_noinst_SCRIPTS += $(wildcard python/tests/suite_dynamic-discovery/*.py)
 nobase_noinst_SCRIPTS += $(wildcard python/tests/suite_dynamic-nids/*.py)
 EXTRA_DIST=$(nobase_noinst_DATA) $(nobase_noinst_SCRIPTS)
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/callbacks.py b/lustre/tests/lutf/python/tests/suite_multi-rail/callbacks.py
new file mode 100644 (file)
index 0000000..d02f7e2
--- /dev/null
@@ -0,0 +1,6 @@
+from lnet_cleanup import clean_lnet
+from lustre_cleanup import clean_lustre
+
+def lutf_clean_setup():
+       clean_lustre()
+       clean_lnet()
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0005.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0005.py
new file mode 100644 (file)
index 0000000..a374201
--- /dev/null
@@ -0,0 +1,41 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: The DLC APIs shall provide a method by which Multiple NIs can be added or removed dynamically on the same network
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure all the interfaces (more than one) on the same network
+- sanitize the YAML output to make sure that networks were configured properly
+- use the YAML output to delete the configuration
+- use the YAML configuration to reconfigure the system
+- verify configuration is correct
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               intfs = t.get_available_devs()
+               # configure/unconfigure_net does un/configuration and verification
+               t.configure_net('tcp', intfs)
+               netcfg = t.get_nets()
+               t.unconfigure_net('tcp')
+               t.configure_net('tcp', pycfg=netcfg)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0015.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0015.py
new file mode 100644 (file)
index 0000000..4a8af84
--- /dev/null
@@ -0,0 +1,57 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: The DLC APIs shall provide a method by which Multiple NIs can be added or removed dynamically on the same network
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure more than one interface
+- ensure that configuration is correct
+- delete one interface
+- ensure that configuration is correct
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               intfs = t.get_available_devs()
+               if len(intfs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               t.api_config_ni('tcp', intfs)
+               # verify config
+               rc = t.get_nets(net='tcp', wrapper=True)
+               if len(rc['local NI(s)']) != len(intfs):
+                       return lutfrc(LUTF_TEST_FAIL, "number of interfaces don't match", requested=intfs, configured=rc['local NI(s)'])
+               for intf in rc['local NI(s)']:
+                       if not intf['interfaces'][0] in intfs:
+                               return lutfrc(LUTF_TEST_FAIL, "interfaces don't match", requested=intfs, configured=rc['local NI(s)'])
+               # delete some random interface
+               intf_idx = random.randint(0, len(intfs) - 1)
+               intf_rm = [intfs[intf_idx]]
+               del(intfs[intf_idx])
+               t.api_del_ni('tcp', intf_rm)
+               # verify config
+               rc = t.get_nets(net='tcp', wrapper=True)
+               if len(rc['local NI(s)']) != len(intfs):
+                       return lutfrc(LUTF_TEST_FAIL, "number of interfaces don't match", requested=intfs, configured=rc['local NI(s)'])
+               for intf in rc['local NI(s)']:
+                       if not intf['interfaces'][0] in intfs:
+                               return lutfrc(LUTF_TEST_FAIL, "interfaces don't match", requested=intfs, configured=rc['local NI(s)'])
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0020.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0020.py
new file mode 100644 (file)
index 0000000..efe9df8
--- /dev/null
@@ -0,0 +1,68 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: The DLC APIs shall provide a method by which Multiple NIs can be added or removed dynamically on the same network
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- split the list of interfaces into two lists
+- Configure 1 list on tcp1 and the 2nd list on tcp2
+- verify configuration
+- delete all NIs from 1st list
+- verify configuration. There should be no more tcp1
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       if len(rc['local NI(s)']) != len(intfs):
+               return 'FAILV', rc
+       for intf in rc['local NI(s)']:
+               if not intf['interfaces'][0] in intfs:
+                       return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               intfs = t.get_available_devs()
+               if len(intfs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               tcp1intf = intfs[:int(len(intfs)/2)]
+               tcp2intf = intfs[int(len(intfs)/2):]
+
+               t.api_config_ni('tcp1', tcp1intf)
+               rc, cfg = verify_config(t, 'tcp1', tcp1intf)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+
+               t.api_config_ni('tcp2', tcp2intf)
+               rc, cfg = verify_config(t, 'tcp2', tcp2intf)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               # delete some random interface
+               t.api_del_ni('tcp1', tcp1intf)
+               # verify config
+               rc, cfg = verify_config(t, 'tcp1', tcp1intf)
+               if rc != 'NOT_FOUND':
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to remove interfaces", remove=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0025.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0025.py
new file mode 100644 (file)
index 0000000..1b28d7e
--- /dev/null
@@ -0,0 +1,85 @@
+"""
+@PRIMARY: cfg-025
+@PRIMARY_DESC: The DLC API shall provide a method by which an NI can be associated with a CPT.
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- unconfigure LNet
+- unload LNet
+- modify the /etc/modprobe.d/lustre.conf file to contain
+       options libcfs cpu_npartitions=4 cpu_pattern="0[0] 1[1] 2[2] 3[3]"
+- Look up the interfaces on the system
+- configure intf1 on CPT 0, 2
+- configure intf2 on CPT 1, 3
+- sanitize configuration
+"""
+
+import os
+import yaml, random, re
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       if len(rc['local NI(s)']) != len(intfs):
+               return 'FAILV', rc
+       for intf in rc['local NI(s)']:
+               if not intf['interfaces'][0] in intfs:
+                       return 'FAILV', rc
+               if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                       return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               intfs = t.get_available_devs()
+               if len(intfs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+
+               t.unconfigure_lnet()
+               t.configure_lnet()
+               tcp1intf = intfs[:int(len(intfs)/2)]
+               tcp2intf = intfs[int(len(intfs)/2):]
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.api_config_ni('tcp1', tcp1intf, global_cpts=cpt1)
+               rc, cfg = verify_config(t, 'tcp1', tcp1intf, cpt1)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+
+               t.api_config_ni('tcp2', tcp2intf, global_cpts=cpt2)
+               rc, cfg = verify_config(t, 'tcp2', tcp2intf, cpt2)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0030.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0030.py
new file mode 100644 (file)
index 0000000..85ab48d
--- /dev/null
@@ -0,0 +1,93 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- unconfigure LNet
+- unload LNet
+- modify the /etc/modprobe.d/lustre.conf file to contain
+       options libcfs cpu_npartitions=4 cpu_pattern="0[0] 1[1] 2[2] 3[3]"
+- Look up the interfaces on the system
+- configure intf1 on CPT 0, 2
+- configure intf2 on CPT 1, 3
+- configure intf3 on all CPTS.
+- sanitize configuration
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       found = False
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               intfs = t.get_available_devs()
+               if len(intfs) < 3:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+
+               t.unconfigure_lnet()
+
+               t.configure_lnet()
+               intf0 = [intfs[0]]
+               intf1 = [intfs[1]]
+               intf2 = [intfs[2]]
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.api_config_ni('tcp1', intf0, global_cpts=cpt1)
+               rc, cfg = verify_config(t, 'tcp1', intf0, cpt1)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf0, configured=cfg)
+               t.api_config_ni('tcp1', intf1, global_cpts=cpt2)
+               rc, cfg = verify_config(t, 'tcp1', intf1, cpt2)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf1, configured=cfg)
+               t.api_config_ni('tcp1', intf2)
+               rc, cfg = verify_config(t, 'tcp1', intf2, cpt1+cpt2)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf2, configured=cfg)
+
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0035.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0035.py
new file mode 100644 (file)
index 0000000..f94fceb
--- /dev/null
@@ -0,0 +1,57 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure a NID using ip2nets
+- sanitize
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       if len(rc['local NI(s)']) != len(intfs):
+               return 'FAILV', rc
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               intfs = t.get_available_intfs()
+               if len(devs) < 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               devip =  intfs['interfaces'][devs[0]]['ip']
+               t.configure_lnet()
+               ip2nets = 'tcp3(' + devs[0] + ')' + ' ' + devip
+               t.api_config_ni('tcp3', ip2nets=ip2nets)
+               rc, cfg = verify_config(t, 'tcp3', [devs[0]])
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS, cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0040.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0040.py
new file mode 100644 (file)
index 0000000..4e12ecc
--- /dev/null
@@ -0,0 +1,76 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure a NID using ip2nets
+       tcp(eth0[1,3]) <eth0 IP>
+- sanitize
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       if len(rc['local NI(s)']) != len(intfs):
+               return 'FAILV', rc
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               intfs = t.get_available_intfs()
+               if len(devs) < 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               devip =  intfs['interfaces'][devs[0]]['ip']
+               t.configure_lnet()
+               ip2nets = 'tcp3(' + devs[0]+str(cpt1)+ ')' + ' ' + devip
+               t.api_config_ni('tcp3', ip2nets=ip2nets)
+               rc, cfg = verify_config(t, 'tcp3', [devs[0]], cpt1)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS, cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0045.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0045.py
new file mode 100644 (file)
index 0000000..db8ba59
--- /dev/null
@@ -0,0 +1,79 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure a NID using ip2nets
+       tcp(eth0, eth1[1,3]) *.*.*.*
+- sanitize
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               intfs = t.get_available_intfs()
+               if len(devs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.configure_lnet()
+               ip2nets = 'tcp3(' + devs[0]+','+devs[1]+ str(cpt1) + ') *.*.*.*'
+               print(ip2nets)
+               t.api_config_ni('tcp3', ip2nets=ip2nets)
+               rc, cfg = verify_config(t, 'tcp3', [devs[0]], cpt1+cpt2)
+               if rc != 'SUCCESS':
+                       print('failed 1', ip2nets)
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               rc, cfg = verify_config(t, 'tcp3', [devs[1]], cpt1)
+               if rc != 'SUCCESS':
+                       print('failed 2')
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS, cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0050.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0050.py
new file mode 100644 (file)
index 0000000..5a1b9cc
--- /dev/null
@@ -0,0 +1,76 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure a NID using ip2nets
+       tcp(eth0[0,2], eth1[1,3]) *.*.*.*
+- sanitize
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               intfs = t.get_available_intfs()
+               if len(devs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.configure_lnet()
+               ip2nets = 'tcp3(' + devs[0]+str(cpt1)+','+devs[1]+str(cpt2) + ') *.*.*.*'
+               t.api_config_ni('tcp3', ip2nets=ip2nets)
+               rc, cfg = verify_config(t, 'tcp3', [devs[0]], cpt1)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               rc, cfg = verify_config(t, 'tcp3', [devs[1]], cpt2)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               return lutfrc(LUTF_TEST_PASS, cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0055.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0055.py
new file mode 100644 (file)
index 0000000..f0734ea
--- /dev/null
@@ -0,0 +1,66 @@
+"""
+@PRIMARY: cfg-060
+@PRIMARY_DESC: lnetctl utility shall provide a command line front end interface to configure local NIs by calling the DLC APIs
+@SECONDARY: cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- Configure net using lnetctl (This is done via the LNet class)
+- verify configuration
+- Delete an interface
+- verify configuration
+- set numa range
+- verify configuration
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       l = TheLNet(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               if len(devs) < 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               t.configure_lnet()
+               l.add_ni('tcp', devs[0])
+               rc, cfg = verify_config(t, 'tcp', [devs[0]])
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               l.del_ni('tcp', devs[0])
+               # This is expected to fail
+               rc, cfg = verify_config(t, 'tcp', [devs[0]])
+               if rc == 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               t.set_numa_range(900)
+               rc = t.get_globals()
+               if rc['global']['numa_range'] != 900:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to set numa range", requested=900, configured=rc['global']['numa_range'])
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0070.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0070.py
new file mode 100644 (file)
index 0000000..626ea61
--- /dev/null
@@ -0,0 +1,61 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- Configure all interfaces on tcp0 network
+- Configure two of interfaces on tcp1 network
+- dump the YAML output
+- sanitize the YAML output to make sure that networks were configured properly
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       if len(rc['local NI(s)']) != len(intfs):
+               return 'FAILV', rc
+       for intf in rc['local NI(s)']:
+               if not intf['interfaces'][0] in intfs:
+                       return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               intfs = t.get_available_devs()
+               if len(intfs) < 3:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               t.configure_lnet()
+               tcp1intfs = [intfs[0], intfs[1]]
+               tcp2intfs = [intfs[1], intfs[2]]
+
+               t.api_config_ni('tcp1', tcp1intfs)
+               rc, cfg = verify_config(t, 'tcp1', tcp1intfs)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf0, configured=cfg)
+               t.api_config_ni('tcp2', tcp2intfs)
+               rc, cfg = verify_config(t, 'tcp2', tcp2intfs)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf1, configured=cfg)
+
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0090.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0090.py
new file mode 100644 (file)
index 0000000..325bdec
--- /dev/null
@@ -0,0 +1,38 @@
+"""
+@PRIMARY: cfg-060
+@PRIMARY_DESC: lnetctl utility shall provide a command line front end interface to configure local NIs by calling the DLC APIs
+@SECONDARY:
+@DESIGN: N/A
+@TESTCASE:
+- Configure a non-existant interface on tcp1
+- sanitize this configuration fails with bad parameter
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               try:
+                       t.api_config_ni('tcp1', ['amir'])
+               except:
+                       t.uninit()
+                       return lutfrc(LUTF_TEST_PASS)
+
+               return lutfrc(LUTF_TEST_FAIL, "Configured an unknown interface")
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0095.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0095.py
new file mode 100644 (file)
index 0000000..cb8fc80
--- /dev/null
@@ -0,0 +1,92 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- unconfigure LNet
+- modify the /etc/modprobe.d/lustre.conf file to contain
+       options libcfs cpu_npartitions=4 cpu_pattern="0[0] 1[1] 2[2] 3[3]"
+- Look up the interfaces on the system
+- configure intf1 on CPT 0, 2
+- configure intf2 on CPT 1, 3
+- configuring an NI on a bad cpt should fail
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       found = False
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               intfs = t.get_available_devs()
+               if len(intfs) < 3:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+               t.unconfigure_lnet()
+
+               t.configure_lnet()
+               intf0 = [intfs[0]]
+               intf1 = [intfs[1]]
+               intf2 = [intfs[2]]
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.api_config_ni('tcp1', intf0, global_cpts=cpt1)
+               rc, cfg = verify_config(t, 'tcp1', intf0, cpt1)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf0, configured=cfg)
+               t.api_config_ni('tcp1', intf1, global_cpts=cpt2)
+               rc, cfg = verify_config(t, 'tcp1', intf1, cpt2)
+               if rc != 'SUCCESS':
+                       return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf1, configured=cfg)
+               try:
+                       t.api_config_ni('tcp1', intf2, global_cpts=[11,14])
+                       rc, cfg = verify_config(t, 'tcp1', intf2, [11,14])
+                       if rc == 'SUCCESS':
+                               return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=intf2, configured=cfg)
+               except:
+                       t.uninit()
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "Configuration with wrong cpt worked", cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0096.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0096.py
new file mode 100644 (file)
index 0000000..21519a6
--- /dev/null
@@ -0,0 +1,80 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- configure a NID using ip2nets
+       tcp(eth0, eth1)[1,3] *.*.*.*
+- sanitize this configuration fails due to wrong syntax
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def verify_config(t, net, intfs, cpts):
+       try:
+               rc = t.get_nets(net=net, wrapper=True)
+       except:
+               return 'NOT_FOUND', None
+       found = False
+       for intf in rc['local NI(s)']:
+               if intf['interfaces'][0] in intfs:
+                       found = True
+                       if yaml.load(intf['CPT'], Loader=yaml.FullLoader) != cpts:
+                               return 'FAILV', rc
+       if not found:
+               return 'FAILV', rc
+       return 'SUCCESS', rc
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               devs = t.get_available_devs()
+               intfs = t.get_available_intfs()
+               if len(devs) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough interfaces for the test")
+               num_partitions = me.get_cpuinfo()['NUMA node(s)']
+               path = os.path.join(os.sep, 'etc', 'modprobe.d')
+               f = LutfFile(path, full_path=True, target=la[0])
+               count, line = f.get("cpu_npartitions=")
+               if count >= 1:
+                       try:
+                               num_partitions = int(line[0].split('cpu_npartitions=')[1].split()[0])
+                       except:
+                               pass
+               if num_partitions <= 1:
+                       return lutfrc(LUTF_TEST_SKIP, "not enough CPTs for this test. Require more than 1")
+
+               cpts = list(range(0, num_partitions))
+               cpt1 = cpts[:int(len(cpts)/2)]
+               cpt2 = cpts[int(len(cpts)/2):]
+
+               t.configure_lnet()
+               ip2nets = 'tcp3(' + devs[0]+','+devs[1] + ') ' + str(cpt1) + ' *.*.*.*'
+               try:
+                       t.api_config_ni('tcp3', ip2nets=ip2nets)
+                       rc, cfg = verify_config(t, 'tcp3', [devs[0]], cpt1)
+                       if rc == 'SUCCESS':
+                               return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+                       rc, cfg = verify_config(t, 'tcp3', [devs[1]], cpt2)
+                       if rc == 'SUCCESS':
+                               return lutfrc(LUTF_TEST_FAIL, "Net configuration failed", requested=tcp1intf, configured=cfg)
+               except:
+                       t.uninit()
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, cfg=cfg)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0105.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0105.py
new file mode 100644 (file)
index 0000000..3bf638c
--- /dev/null
@@ -0,0 +1,40 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: The DLC APIs shall provide a method by which Multiple NIs can be added or removed dynamically on the same network
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- Delete a non existent network.
+- Validate that this returns an error
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               intfs = t.get_available_devs()
+               # configure/unconfigure_net does un/configuration and verification
+               t.configure_net('tcp', intfs)
+               try:
+                       t.api_del_ni('tcp3', [intfs[0]])
+               except:
+                       t.uninit()
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "deleting an unknown net succeeded")
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0110.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0110.py
new file mode 100644 (file)
index 0000000..973eba9
--- /dev/null
@@ -0,0 +1,41 @@
+"""
+@PRIMARY: cfg-020
+@PRIMARY_DESC: The DLC APIs shall provide a method by which Multiple NIs can be added or removed dynamically on the same network
+@SECONDARY: cfg-005, cfg-010, cfg-015,cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- Look up the interfaces on the system
+- configure all interfaces under the same net
+- attempt to delete a non existing NI
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               intfs = t.get_available_devs()
+               # configure/unconfigure_net does un/configuration and verification
+               t.api_config_ni('tcp', intfs)
+               try:
+                       t.api_del_ni('tcp', ['amir'])
+               except:
+                       t.uninit()
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "deleting an unknown ni succeeded")
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0115.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0115.py
new file mode 100644 (file)
index 0000000..ede9ac3
--- /dev/null
@@ -0,0 +1,121 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Test the syntax through multiple different peer adds
+- add a peer with one NI using the API
+- show the peer
+- validate peer is correct
+- delete the peer using the API
+- add the peer again using YAML
+- validate peer is correct
+- delete the peer using YAML
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               # TODO test proper syntax
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.0.[12-15]@tcp')
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               #----
+
+               try:
+                       rc, info = t.api_config_peer(nids='192.168.0.[12-15]@tcp')
+                       t.api_del_peer(prim_nid='192.168.0.12@tcp')
+               except:
+                       rc = False
+                       info = []
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "Empty primary NID succeeded. Expected failure.", info=info)
+               #----
+               t.api_config_peer(prim_nid='192.168.0.12@tcp', nids='192.168.0.[12-15]@tcp,192.168.0.16@tcp')
+               t.api_del_peer(prim_nid='192.168.0.12@tcp')
+               #----
+               t.api_config_peer(prim_nid='192.168.0.12@tcp', nids='192.168.0.[12-15,16]@tcp')
+               t.api_del_peer(prim_nid='192.168.0.12@tcp')
+               #----
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.0.11@tcp,192.168.0.13@tcp,192.168.0.14@tcp')
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               #----
+               try:
+                       rc, info = t.api_config_peer(prim_nid='', nids='192.168.0.12@tcp,192.168.0.13@tcp,192.168.0.14@tcp')
+               except:
+                       rc = 0
+                       info = []
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "Empty primary NID succeeded. Expected failure.", info=info)
+               #----
+               try:
+                       t.api_config_peer(prim_nid='192.168.122.[11-12]@tcp', nids='192.168.0.12@tcp,192.168.0.13@tcp,192.168.0.14@tcp')
+               except:
+                       rc = 0
+                       info = []
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "Bad primary NID format succeeded. Expected failure.", info=info)
+               t.api_config_peer(prim_nid='192.168.0.15@tcp', nids='192.168.0.15@tcp,192.168.0.16@tcp,192.168.0.17@tcp')
+               # delete non primary nid
+               try:
+                       rc, info = t.api_del_peer(prim_nid='192.168.17@tcp')
+               except:
+                       rc = 0
+                       info = []
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "Deleting non-primary nid succeeded. Expected failure.", info=info)
+               t.api_del_peer(prim_nid='192.168.0.15@tcp')
+
+               # configure with bad parameters
+               try:
+                       rc, info = t.api_config_peer()
+               except:
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "Expected failure. Got success.", info=info)
+               try:
+                       rc, info = t.api_config_peer(prim_nid='192.168.122.11@tcpX')
+               except:
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "configuring peer with bad net succeeded. Expected failure", info=info)
+               try:
+                       rc, info = t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.0.12@tcp,192.168.0.13@tcp,192.168.0.14@tcpX')
+               except:
+                       pass
+               if rc:
+                       return lutfrc(LUTF_TEST_FAIL, "configuring peer with bad net succeeded. Expected failure", info=info)
+               #----
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.0.11@tcp,192.168.0.13@tcp,192.168.0.14@tcp')
+               peers = t.get_peers()
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               t.import_config(peers)
+               peers2 = t.get_peers()
+               if peers != peers2:
+                       return lutfrc(LUTF_TEST_FAIL, "peers were not configured properly from YAML", requested=peers, configured=peers2)
+               #----
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0120.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0120.py
new file mode 100644 (file)
index 0000000..2a66c47
--- /dev/null
@@ -0,0 +1,63 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add a peer with one NI using the API
+- show the peer config and store
+- add another peer NI
+- show the peer config and store
+- validate peer is correct
+- delete the second peer NI using the API
+- delete the primary NI using the API
+- peer should be gone by this time
+- add the peer with 1 NI again using YAML
+- add the peer with 2nd NI using YAML
+- show the peer.
+- validate peer is correct
+- delete the peer using YAML
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               # TODO test proper syntax
+               t.api_config_peer(prim_nid='192.168.122.11@tcp')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp')
+               peers = t.get_peers()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.13@tcp')
+               peers2 = t.get_peers()
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.13@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               t.import_config(peers)
+               t.api_verify_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp')
+               t.import_config(peers2)
+               t.api_verify_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp,192.168.122.13@tcp')
+               peers = t.get_peers()
+               t.import_del(peers)
+               peers = t.get_peers()
+               if peers and len(peers) > 0:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to delete peers via YAML.", peers=peers)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0125.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0125.py
new file mode 100644 (file)
index 0000000..56306a1
--- /dev/null
@@ -0,0 +1,54 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add a peer with multiple NI using the API
+- store the YAML show to use later
+- validate peer is correct
+- delete non-primary NIDs one by one using the API
+- re-add the exact same peer
+- validate
+- delete using YAML
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp')
+               peers = t.get_peers()
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.13@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.14@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.15@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp')
+               peers2 = t.get_peers()
+               if peers != peers2:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to delete peers configure YAML.", peers=peers2)
+               t.import_del(peers)
+               peers = t.get_peers()
+               if peers and len(peers) > 0:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to delete peers via YAML.", peers=peers)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0131.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0131.py
new file mode 100644 (file)
index 0000000..d56e175
--- /dev/null
@@ -0,0 +1,38 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add a peer with multiple NI using the API
+- validate peer is correct
+- delete primary NID using the API
+- validate
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp')
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0145.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0145.py
new file mode 100644 (file)
index 0000000..e30047e
--- /dev/null
@@ -0,0 +1,52 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add a peer with multiple NI using the API
+- store the YAML show to use later
+- validate peer is correct
+- delete all NIDs but primary using the API
+- re-add multiple NIDs in one shot
+- validate
+- delete using YAML
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp')
+               peers = t.get_peers()
+               #t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp', all=False)
+               t.api_del_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.12@tcp,192.168.122.13@tcp,192.168.122.14@tcp,192.168.122.15@tcp', all=False)
+               peers2 = t.get_peers()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[12-15]@tcp')
+               peers2 = t.get_peers()
+               if peers != peers2:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to delete peers configure YAML.", peers=peers2)
+               t.import_del(peers)
+               peers = t.get_peers()
+               if peers and len(peers) > 0:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to delete peers via YAML.", peers=peers)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0155.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0155.py
new file mode 100644 (file)
index 0000000..f0e8afb
--- /dev/null
@@ -0,0 +1,43 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add a peer with 33 NIs using the API
+- validate peer is correct
+- delete the peer via API in one shot
+- add a peer with 130 NIs using the API
+- validate failure because of passing maximum number of NIDs
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[1-34]@tcp')
+               t.api_del_peer(prim_nid='192.168.122.11@tcp')
+               try:
+                       t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[1-133]@tcp')
+               except:
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "Configuring more than 128 NIDs passed. Unexpected", peers=peers)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0165.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0165.py
new file mode 100644 (file)
index 0000000..7dbd4af
--- /dev/null
@@ -0,0 +1,46 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs using the API
+- add peer 2 with 3 NIs using the API
+- validate peer is correct
+- delete both peers via YAML
+- validate
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp', nids='192.168.1.[2-3]@tcp')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[2-4]@tcp')
+               peer1 = t.get_peers(nid='192.168.1.11@tcp')
+               peer2 = t.get_peers(nid='192.168.122.11@tcp')
+               t.import_del(peer1)
+               t.import_del(peer2)
+               peers = t.get_peers()
+               if peers and len(peers) > 0:
+                       lutfrc(LUTF_TEST_FAIL, "Failed to delete all the peers", peers=peers)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0170.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0170.py
new file mode 100644 (file)
index 0000000..9eceadd
--- /dev/null
@@ -0,0 +1,43 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs using the API
+- add peer 2 with 3 NIs using the API
+- validate peer is correct
+- deinitialize LNet
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp', nids='192.168.1.[2-3]@tcp')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp', nids='192.168.122.[2-4]@tcp')
+               try:
+                       t.uninit()
+                       t.unconfigure_lnet()
+               except:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to unconfigure lnet with peers configured")
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0171.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0171.py
new file mode 100644 (file)
index 0000000..f8c35c8
--- /dev/null
@@ -0,0 +1,64 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs to tcp1 using the API
+- add peer 2 with 3 NIs to tcp1 using the API
+- validate peer is correct
+- check ref count on the NIs in peer 1 and 2 == 2
+- check credits == 0
+- add tcp1.
+- check ref count on the NIs in peer 1 and 2 == 1
+- check credits != 0
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def check_peer_info(nid, t, refcount, credits):
+       peer = t.get_peers(nid=nid, detailed=True)
+       for e in peer['peer']:
+               for peerni in e['peer ni']:
+                       if (peerni['refcount'] != refcount and peerni['nid'] != nid) or peerni['max_ni_tx_credits'] != credits:
+                               return False, peer
+       return True, peer
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp1', nids='192.168.1.[2-3]@tcp1')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp1', nids='192.168.122.[2-4]@tcp1')
+               rc, peer = check_peer_info('192.168.1.11@tcp1', t, 2, 0)
+               if not rc:
+                       lutfrc(LUTF_TEST_FAIL, "peer refcount(2) and peer credits(0) are wrong", peer=peer)
+               rc, peer = check_peer_info('192.168.122.11@tcp1', t, 2, 0)
+               if not rc:
+                       lutfrc(LUTF_TEST_FAIL, "peer refcount(2) and peer credits(0) are wrong", peer=peer)
+               intfs = t.get_available_devs()
+               t.configure_net('tcp1')
+               rc, peer = check_peer_info('192.168.1.11@tcp1', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(8) are wrong", peer=peer)
+               rc, peer = check_peer_info('192.168.122.11@tcp1', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(8) are wrong", peer=peer)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0172.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0172.py
new file mode 100644 (file)
index 0000000..75f9e95
--- /dev/null
@@ -0,0 +1,65 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs to tcp1 using the API
+- add peer 2 with 3 NIs to tcp2 using the API
+- validate peer is correct
+- add tcp1 and tcp2 networks
+- remove the tcp1 network
+- check that the entire peer is removed
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def check_peer_info(nid, t, refcount, credits):
+       peer = t.get_peers(nid=nid, detailed=True)
+       for e in peer['peer']:
+               for peerni in e['peer ni']:
+                       if (peerni['refcount'] != refcount and peerni['nid'] != nid) or peerni['max_ni_tx_credits'] != credits:
+                               return False, peer
+       return True, peer
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp1', nids='192.168.1.[2-3]@tcp1')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp2', nids='192.168.122.[2-4]@tcp2')
+               t.configure_net('tcp1')
+               t.configure_net('tcp2')
+               rc, peer = check_peer_info('192.168.1.11@tcp1', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(128) are wrong", peer=peer)
+               rc, peer = check_peer_info('192.168.122.11@tcp2', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(128) are wrong", peer=peer)
+               t.unconfigure_net('tcp1')
+               try:
+                       peers = t.get_peers(nid='192.168.1.11@tcp1')
+                       if peers and len(peers) > 0:
+                               return lutfrc(LUTF_TEST_FAIL, "peer on deleted network didn't go away", peer=peers)
+               except:
+                       # it is expected that the peer has been removed,
+                       # so we won't find it.
+                       pass
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0173.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0173.py
new file mode 100644 (file)
index 0000000..a421fdb
--- /dev/null
@@ -0,0 +1,65 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs to tcp1 using the API
+- add peer 2 with 3 NIs to tcp2 using the API
+- validate peer is correct
+- add tcp1 and tcp2 networks
+- remove the tcp2 network
+- check that the entire peer is removed
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def check_peer_info(nid, t, refcount, credits):
+       peer = t.get_peers(nid=nid, detailed=True)
+       for e in peer['peer']:
+               for peerni in e['peer ni']:
+                       if (peerni['refcount'] != refcount and peerni['nid'] != nid) or peerni['max_ni_tx_credits'] != credits:
+                               return False, peer
+       return True, peer
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp1', nids='192.168.1.[2-3]@tcp1')
+               t.api_config_peer(prim_nid='192.168.122.11@tcp2', nids='192.168.122.[2-4]@tcp2')
+               t.configure_net('tcp1')
+               t.configure_net('tcp2')
+               rc, peer = check_peer_info('192.168.1.11@tcp1', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(128) are wrong", peer=peer)
+               rc, peer = check_peer_info('192.168.122.11@tcp2', t, 1, 128)
+               if not rc:
+                       return lutfrc(LUTF_TEST_FAIL, "peer refcount(1) and peer credits(128) are wrong", peer=peer)
+               t.unconfigure_net('tcp2')
+               try:
+                       peers = t.get_peers(nid='192.168.122.11@tcp2')
+                       if peers and len(peers) > 0:
+                               return lutfrc(LUTF_TEST_FAIL, "peer on deleted network didn't go away", peer=peers)
+               except:
+                       # it is expected that the peer has been removed,
+                       # so we won't find it.
+                       pass
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0175.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0175.py
new file mode 100644 (file)
index 0000000..745416e
--- /dev/null
@@ -0,0 +1,85 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add tcp1
+- add a peer NI to tcp1 using the API on both peers
+- validate peer is correct
+- send traffic over the peer NI
+- validate traffic is distributed evenly
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       la = agents.keys()
+       if len(la) < 2:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t1 = LNetHelpers(target=la[0])
+       st1 = LNetSelfTest(target=la[0])
+       t2 = LNetHelpers(target=la[1])
+       st2 = LNetSelfTest(target=la[1])
+       try:
+               t1.configure_lnet()
+               t1.configure_net('tcp1')
+               t1.set_discovery(0)
+               peer_nids1 = t1.list_nids()
+               t2.configure_lnet()
+               t2.configure_net('tcp1')
+               t2.set_discovery(0)
+               peer_nids2 = t2.list_nids()
+               nids = ','.join(peer_nids2[1:])
+               t1.api_config_peer(prim_nid=peer_nids2[0], nids=nids)
+               nids = ','.join(peer_nids1[1:])
+               t2.api_config_peer(prim_nid=peer_nids1[0], nids=nids)
+               st1.load()
+               st2.load()
+               st1.start(peer_nids1[0], peer_nids2[0])
+               st1.unload()
+               st2.unload()
+               stats = t1.get_peer_stats(peer_nids2[0])
+               # verify traffic is distributed across the nis
+               range = 50
+               first_send = 0
+               num_nids = len(peer_nids2)
+               count_bad_nids = 0
+               for e in stats:
+                       for lpni in e['peer ni']:
+                               lpnistats = lpni['statistics']
+                               if not first_send:
+                                       first_send = lpnistats['send_count']
+                                       if first_send <= 0:
+                                               return lutfrc(LUTF_TEST_FAIL, "no traffic was sent",
+                                                       stats=stats)
+                               else:
+                                       send_count = lpnistats['send_count']
+                                       delta = lpnistats['send_count'] * (range/100)
+                                       upper_range = first_send + delta
+                                       lower_range = first_send - delta
+                                       if send_count > upper_range or send_count < lower_range:
+                                               count_bad_nids += 1
+                                               # tolerate 30 % of the
+                                               # NIDs having send count
+                                               # out of range
+                                               if count_bad_nids <= int(num_nids * 0.3):
+                                                       continue
+                                               return lutfrc(LUTF_TEST_FAIL, "Traffic wasn't distributed evenly",
+                                                       stats=stats)
+               return lutfrc(LUTF_TEST_PASS, "Test Passed but with a loose range", range=range, stats=stats, bad_nids=count_bad_nids)
+       except Exception as e:
+               t1.uninit()
+               t2.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0176.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0176.py
new file mode 100644 (file)
index 0000000..0ab9fa2
--- /dev/null
@@ -0,0 +1,76 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add tcp
+- add peers on tcp using the API
+- validate peers are multi-rail
+- send traffic over the peer NI
+- delete the peers
+- validate peers recreated are non multi-rail
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run_lnet_traffic(st1, src, dst):
+       st1.start(src, dst)
+
+def run():
+       la = agents.keys()
+       if len(la) < 2:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t1 = LNetHelpers(target=la[0])
+       st1 = LNetSelfTest(target=la[0])
+       t2 = LNetHelpers(target=la[1])
+       st2 = LNetSelfTest(target=la[1])
+       try:
+               t1.configure_lnet()
+               t1.configure_net('tcp1')
+               t1.set_discovery(0)
+               peer_nids1 = t1.list_nids()
+               t2.configure_lnet()
+               t2.configure_net('tcp1')
+               t2.set_discovery(0)
+               peer_nids2 = t2.list_nids()
+               nids = ','.join(peer_nids2[1:])
+               t1.api_config_peer(prim_nid=peer_nids2[0], nids=nids)
+               nids = ','.join(peer_nids1[1:])
+               t2.api_config_peer(prim_nid=peer_nids1[0], nids=nids)
+               # check peer is multi-rail
+               peer = t1.get_peers(nid=peer_nids2[0])
+               if not peer['peer'][0]['Multi-Rail']:
+                       return lutfrc(LUTF_TEST_FAIL, "Peer should've been multi-rail", peer=peer)
+               st1.load()
+               st2.load()
+               # start a thread for traffic
+               traffic = threading.Thread(target=run_lnet_traffic, args=(st1, peer_nids1[0], peer_nids2[0]))
+               traffic.start()
+               time.sleep(5)
+               # delete the peer on t1
+               t1.api_del_peer(prim_nid=peer_nids2[0])
+               time.sleep(5)
+               peer = t1.get_peers(nid=peer_nids2[0])
+               if peer['peer'][0]['Multi-Rail']:
+                       traffic.join()
+                       return lutfrc(LUTF_TEST_FAIL, "Peer shouldn't been multi-rail", peer=peer)
+               traffic.join()
+               st1.unload()
+               st2.unload()
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t1.uninit()
+               t2.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0185.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0185.py
new file mode 100644 (file)
index 0000000..0cb759b
--- /dev/null
@@ -0,0 +1,41 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add peer 1 with 2 NIs to tcp1 using the API
+- validate peer is correct
+- delete a non-existent NID.
+- should fail
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp', nids='192.168.1.[2-3]@tcp')
+               try:
+                       t.api_del_peer(prim_nid='192.168.1.11@tcp', nids='192.168.1.6@tcp')
+               except:
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "Was able to delete a non existent peer nid")
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0190.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0190.py
new file mode 100644 (file)
index 0000000..ea498fb
--- /dev/null
@@ -0,0 +1,39 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- add peer 1 with NIDs A, B and C
+- add peer 2 with NIDs D, C and E
+- Adding NID C should fail
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               rc = True
+               t.configure_lnet()
+               t.api_config_peer(prim_nid='192.168.1.11@tcp', nids='192.168.1.[2-3]@tcp')
+               try:
+                       t.api_config_peer(prim_nid='192.168.2.11@tcp', nids='192.168.1.[3-5]@tcp')
+               except:
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "Was able to delete a non existent peer nid")
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0195.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0195.py
new file mode 100644 (file)
index 0000000..e0e62ee
--- /dev/null
@@ -0,0 +1,25 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- set NUMA range to 0
+- NI closest to message memory NUMA be picked
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0205.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0205.py
new file mode 100644 (file)
index 0000000..d0d5138
--- /dev/null
@@ -0,0 +1,25 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- set NUMA range to a large value
+- NIs are picked in Round-Robin
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0210.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0210.py
new file mode 100644 (file)
index 0000000..708463e
--- /dev/null
@@ -0,0 +1,38 @@
+"""
+@PRIMARY: cfg-060
+@PRIMARY_DESC: lnetctl utility shall provide a command line front end interface to configure local NIs by calling the DLC APIs
+@SECONDARY: cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- set NUMA range to -1
+- check config fails
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t = LNetHelpers(target=la[0])
+       try:
+               t.configure_lnet()
+               t.configure_net('tcp')
+               try:
+                       t.set_numa_range(-1)
+               except:
+                       return lutfrc(LUTF_TEST_PASS)
+               return lutfrc(LUTF_TEST_FAIL, "Numa range set to -1", cfg=t.get_globals())
+       except Exception as e:
+               t.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0215.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0215.py
new file mode 100644 (file)
index 0000000..c4503ff
--- /dev/null
@@ -0,0 +1,51 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- add tcp1 network with all interfaces on the system.
+- add peer 1 with 2 NIs to tcp1 using the API
+- set NUMA range to 100
+- check config
+- delete config using YAML
+- reconfigure using YAML
+- check config
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       la = agents.keys()
+       if len(la) < 1:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t1 = LNetHelpers(target=la[0])
+       try:
+               t1.configure_lnet()
+               t1.configure_net('tcp1')
+               t1.set_discovery(0)
+               t1.api_config_peer(prim_nid='192.168.122.34@tcp', nids='192.168.122.[35-36]@tcp')
+               t1.set_numa_range(100)
+               cfg = t1.get_config()
+               t1.uninit()
+               t1.unconfigure_lnet()
+               t1.configure_lnet()
+               t1.configure_yaml(cfg)
+               cfg2 = t1.get_config()
+               if cfg != cfg2:
+                       return lutfrc(LUTF_TEST_FAIL, "YAML config failed", required=cfg, implemented=cfg2)
+               return lutfrc(LUTF_TEST_PASS, required=cfg, implemented=cfg2)
+       except Exception as e:
+               t1.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0220.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0220.py
new file mode 100644 (file)
index 0000000..41d6a7c
--- /dev/null
@@ -0,0 +1,26 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 3 NIs with equadistant NUMA distance
+- Send three or more messages
+- check stats confirming each NI used to send messages
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0225.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0225.py
new file mode 100644 (file)
index 0000000..d6c72aa
--- /dev/null
@@ -0,0 +1,26 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 3 NIs closer to different NUMA nodes
+- Send traffic
+- Verify that each NI has the correct device CPT
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0230.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0230.py
new file mode 100644 (file)
index 0000000..b06a593
--- /dev/null
@@ -0,0 +1,26 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 3 NIs with different NUMA distance
+- Send three or more messages
+- check stats confirming messages sent over the nearest NI (NUMA wise)
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0235.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0235.py
new file mode 100644 (file)
index 0000000..3d268a6
--- /dev/null
@@ -0,0 +1,28 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 2 NIs with different NUMA distance
+- Send three or more messages
+- check stats confirming messages sent over the nearest NI (NUMA wise)
+- add another NI which is close NUMA wise than the current nearest
+- check stats confirming messages sent over the newly addded NI
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0245.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0245.py
new file mode 100644 (file)
index 0000000..faa5044
--- /dev/null
@@ -0,0 +1,29 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 3 NIs with different NUMA distance
+- Set the NUMA range to a higher value
+- Send three or more messages
+- check stats confirming all NIs being used to send messages
+- Delete an NI
+- check stats confirming deleted NI not being used and message drop count is 0
+"""
+
+import os
+import yaml, random, threading, time
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       return lutfrc(LUTF_TEST_SKIP, "NUMA tests currently not implemented")
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0260.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0260.py
new file mode 100644 (file)
index 0000000..f2c542e
--- /dev/null
@@ -0,0 +1,102 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure 3 NIs on the same network
+- Configure the peer with the same NIDs
+- Send 1 message which requires a response from peer NID
+- Confirm that responses are being sent to the same NI
+"""
+
+import os,re
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+from lustre_logs import LustreLog, LNET_TRACE_MSG_SEND, LNET_TRACE_MSG_RECV
+
+def run():
+       la = agents.keys()
+       if len(la) < 2:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t1 = LNetHelpers(target=la[0])
+       t2 = LNetHelpers(target=la[1])
+       try:
+               t1.configure_lnet()
+               t1.configure_net('tcp1')
+               t1.set_discovery(0)
+               peer_nids1 = t1.list_nids()
+               t2.configure_lnet()
+               t2.configure_net('tcp1')
+               t2.set_discovery(0)
+               peer_nids2 = t2.list_nids()
+               nids = ','.join(peer_nids2[1:])
+               t1.api_config_peer(prim_nid=peer_nids2[0], nids=nids)
+               nids = ','.join(peer_nids1[1:])
+               t2.api_config_peer(prim_nid=peer_nids1[0], nids=nids)
+               # enable logs
+               logs = LustreLog(target=la[0])
+               logs.add_level('net')
+               logs.start()
+               # send ping
+               t1.ping(peer_nids2[0])
+               # disable and extract log
+               rc = logs.stop()
+               parsed_logs = logs.get_log()
+               trace = logs.extract('TRACE', parsed_logs)
+               send_pattern = LNET_TRACE_MSG_SEND
+               recv_pattern = LNET_TRACE_MSG_RECV
+               # verify via TRACE that responses are correct
+               # I'm expected a GET followed by a reply. Let's find the
+               # GET
+               result = None
+               j = 0
+               for i in range(0, len(trace)):
+                       line = trace[i]
+                       j += 1
+                       if ": GET" in line and "lnet_handle_send" in line:
+                               result = re.search(send_pattern, line)
+                               break
+               if not result:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to parse the logs")
+               src_nid = result[11]
+               txni_nid = result[12]
+               sd_src_nid = result[13]
+               msg_dst_nid = result[14]
+               txpeer_lpni_nid = result[15]
+               sd_rtr_nid = result[16]
+               msg_type = result[17]
+               retr_count = result[18]
+               # find the REPLY
+               result = None
+               start = len(trace) - j
+               for i in range(start, len(trace)):
+                       line = trace[i]
+                       if 'REPLY' in line and "lnet_parse" in line:
+                               result = re.search(recv_pattern, line)
+                               break
+               if not result:
+                       return lutfrc(LUTF_TEST_FAIL, "Failed to parse the logs")
+               recv_dest_nid = result[11]
+               recv_ni_nid = result[12]
+               recv_src_nid = result[13]
+               recv_msg_type = result[14]
+               recv_path = result[15]
+
+               if src_nid != recv_dest_nid and msg_dst_nid != recv_src_nid:
+                       return lutfrc(LUTF_TEST_FAIL, "message send/recved on wrong NIDs", sentfrom=src_nid,
+                               receivedon=recv_dest_nid, sento=msg_dst_nid, receivedfrom=recv_src_nid)
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t1.uninit()
+               t2.uninit()
+               raise e
+
diff --git a/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0310.py b/lustre/tests/lutf/python/tests/suite_multi-rail/test_mr_UT_0310.py
new file mode 100644 (file)
index 0000000..0a547ca
--- /dev/null
@@ -0,0 +1,102 @@
+"""
+@PRIMARY: cfg-035
+@PRIMARY_DESC: If no CPT to NI mapping is configured via the DLC API, LNet shall associate the NI with all existing CPTs.
+@SECONDARY: cfg-040, cfg-045, cfg-055, cfg-060, cfg-065
+@DESIGN: N/A
+@TESTCASE:
+- initialize the system
+- Configure an MR system
+- Configure peers via DLC
+- Start traffic
+- Monitor traffic is being sent to all configured peers
+- Delete one of the peer NIs
+- Monitor traffic is no longer sent to that peer NI
+- No messages should be dropped
+"""
+
+import os
+import yaml, random
+import lnetconfig
+from lutf import agents, me
+from lutf_basetest import *
+from lnet import TheLNet
+from lutf_exception import LUTFError
+from lnet_helpers import LNetHelpers
+from lutf_file import LutfFile
+from lnet_selftest import LNetSelfTest
+
+def run():
+       la = agents.keys()
+       if len(la) < 2:
+               return lutfrc(LUTF_TEST_SKIP, "Not enough agents to run the test")
+       t1 = LNetHelpers(target=la[0])
+       st1 = LNetSelfTest(target=la[0])
+       t2 = LNetHelpers(target=la[1])
+       st2 = LNetSelfTest(target=la[1])
+       try:
+               t1.configure_lnet()
+               t1.configure_net('tcp1')
+               t1.set_discovery(0)
+               peer_nids1 = t1.list_nids()
+               t2.configure_lnet()
+               t2.configure_net('tcp1')
+               t2.set_discovery(0)
+               peer_nids2 = t2.list_nids()
+               if len(peer_nids1) < 2 or len(peer_nids2) < 2:
+                       return lutfrc(LUTF_TEST_SKIP, "Need more than 2 interfaces for this test")
+               nids = ','.join(peer_nids2[1:])
+               t1.api_config_peer(prim_nid=peer_nids2[0], nids=nids)
+               nids = ','.join(peer_nids1[1:])
+               t2.api_config_peer(prim_nid=peer_nids1[0], nids=nids)
+               st1.load()
+               st2.load()
+               st1.start(peer_nids1[0], peer_nids2[0])
+               st1.unload()
+               st2.unload()
+               stats = t1.get_peer_stats(peer_nids2[0])
+               # verify traffic is distributed across the nis
+               range = 50
+               first_send = 0
+               num_nids = len(peer_nids2)
+               count_bad_nids = 0
+               for e in stats:
+                       for lpni in e['peer ni']:
+                               lpnistats = lpni['statistics']
+                               if not first_send:
+                                       first_send = lpnistats['send_count']
+                                       if first_send <= 0:
+                                               return lutfrc(LUTF_TEST_FAIL, "no traffic was sent",
+                                                       stats=stats)
+                               else:
+                                       send_count = lpnistats['send_count']
+                                       delta = lpnistats['send_count'] * (range/100)
+                                       upper_range = first_send + delta
+                                       lower_range = first_send - delta
+                                       if send_count > upper_range or send_count < lower_range:
+                                               count_bad_nids += 1
+                                               # tolerate 30 % of the
+                                               # NIDs having send count
+                                               # out of range
+                                               if count_bad_nids <= int(num_nids * 0.3):
+                                                       continue
+                                               return lutfrc(LUTF_TEST_FAIL, "Traffic wasn't distributed evenly",
+                                                       stats=stats)
+               t1.api_del_peer(prim_nid=peer_nids2[0], nids=peer_nids2[1])
+               st1.load()
+               st2.load()
+               st1.start(peer_nids1[0], peer_nids2[0])
+               st1.unload()
+               st2.unload()
+               # check to make sure the peer ni we deleted isn't
+               # recreated
+               try:
+                       peers = t1.get_peers(nid=peer_nids2[1])
+                       return lutfrc(LUTF_TEST_FAIL, "peer on deleted network didn't go away", peer=peers)
+               except:
+                       pass
+               return lutfrc(LUTF_TEST_PASS)
+       except Exception as e:
+               t1.uninit()
+               t2.uninit()
+               raise e
+