From 04e57d28e351f3fea6ebc95ba5e21a5711cfb571 Mon Sep 17 00:00:00 2001 From: Anatoly Pugachev Date: Wed, 28 Apr 2021 17:17:19 +0300 Subject: [PATCH] [facts] add hpux fc info, refactor aix and solaris code (#57406) * correctly parse device from string * check for command presence before running them * check for command presence and return code for solaris and aix as well * add changelog --- changelogs/fragments/57406-hpux-fc-info.yml | 2 + .../module_utils/facts/network/fc_wwn.py | 84 ++++++++++++------- .../module_utils/facts/network/test_fc_wwn.py | 47 ++++++++++- 3 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 changelogs/fragments/57406-hpux-fc-info.yml diff --git a/changelogs/fragments/57406-hpux-fc-info.yml b/changelogs/fragments/57406-hpux-fc-info.yml new file mode 100644 index 00000000000..63cf531309a --- /dev/null +++ b/changelogs/fragments/57406-hpux-fc-info.yml @@ -0,0 +1,2 @@ +minor_changes: + - facts - add fiber channel facts for HP-UX (https://github.com/ansible/ansible/pull/57406) diff --git a/lib/ansible/module_utils/facts/network/fc_wwn.py b/lib/ansible/module_utils/facts/network/fc_wwn.py index 9d9bfc5bc03..77e015d9c92 100644 --- a/lib/ansible/module_utils/facts/network/fc_wwn.py +++ b/lib/ansible/module_utils/facts/network/fc_wwn.py @@ -49,35 +49,61 @@ class FcWwnInitiatorFactCollector(BaseFactCollector): TBD (not implemented): on solaris 9 use `prtconf -pv` """ cmd = module.get_bin_path('fcinfo') - cmd = cmd + " hba-port" - rc, fcinfo_out, err = module.run_command(cmd) - """ - # fcinfo hba-port | grep "Port WWN" - HBA Port WWN: 10000090fa1658de - """ - if fcinfo_out: - for line in fcinfo_out.splitlines(): - if 'Port WWN' in line: - data = line.split(' ') - fc_facts['fibre_channel_wwn'].append(data[-1].rstrip()) + if cmd: + cmd = cmd + " hba-port" + rc, fcinfo_out, err = module.run_command(cmd) + """ + # fcinfo hba-port | grep "Port WWN" + HBA Port WWN: 10000090fa1658de + """ + if rc == 0 and fcinfo_out: + for line in fcinfo_out.splitlines(): + if 'Port WWN' in line: + data = line.split(' ') + fc_facts['fibre_channel_wwn'].append(data[-1].rstrip()) elif sys.platform.startswith('aix'): - # get list of available fibre-channel devices (fcs) cmd = module.get_bin_path('lsdev') - cmd = cmd + " -Cc adapter -l fcs*" - rc, lsdev_out, err = module.run_command(cmd) - if lsdev_out: - lscfg_cmd = module.get_bin_path('lscfg') - for line in lsdev_out.splitlines(): - # if device is available (not in defined state), get its WWN - if 'Available' in line: - data = line.split(' ') - cmd = lscfg_cmd + " -vl %s" % data[0] - rc, lscfg_out, err = module.run_command(cmd) - # example output - # lscfg -vpl fcs3 | grep "Network Address" - # Network Address.............10000090FA551509 - for line in lscfg_out.splitlines(): - if 'Network Address' in line: - data = line.split('.') - fc_facts['fibre_channel_wwn'].append(data[-1].rstrip()) + lscfg_cmd = module.get_bin_path('lscfg') + if cmd and lscfg_cmd: + # get list of available fibre-channel devices (fcs) + cmd = cmd + " -Cc adapter -l fcs*" + rc, lsdev_out, err = module.run_command(cmd) + if rc == 0 and lsdev_out: + for line in lsdev_out.splitlines(): + # if device is available (not in defined state), get its WWN + if 'Available' in line: + data = line.split(' ') + cmd = lscfg_cmd + " -vl %s" % data[0] + rc, lscfg_out, err = module.run_command(cmd) + # example output + # lscfg -vpl fcs3 | grep "Network Address" + # Network Address.............10000090FA551509 + if rc == 0 and lscfg_out: + for line in lscfg_out.splitlines(): + if 'Network Address' in line: + data = line.split('.') + fc_facts['fibre_channel_wwn'].append(data[-1].rstrip()) + elif sys.platform.startswith('hp-ux'): + cmd = module.get_bin_path('ioscan') + fcmsu_cmd = module.get_bin_path('fcmsutil', opt_dirs=['/opt/fcms/bin']) + # go ahead if we have both commands available + if cmd and fcmsu_cmd: + # ioscan / get list of available fibre-channel devices (fcd) + cmd = cmd + " -fnC FC" + rc, ioscan_out, err = module.run_command(cmd) + if rc == 0 and ioscan_out: + for line in ioscan_out.splitlines(): + line = line.strip() + if '/dev/fcd' in line: + dev = line.split(' ') + # get device information + cmd = fcmsu_cmd + " %s" % dev[0] + rc, fcmsutil_out, err = module.run_command(cmd) + # lookup the following line + # N_Port Port World Wide Name = 0x50060b00006975ec + if rc == 0 and fcmsutil_out: + for line in fcmsutil_out.splitlines(): + if 'N_Port Port World Wide Name' in line: + data = line.split('=') + fc_facts['fibre_channel_wwn'].append(data[-1].strip()) return fc_facts diff --git a/test/units/module_utils/facts/network/test_fc_wwn.py b/test/units/module_utils/facts/network/test_fc_wwn.py index b98ae3789e6..32a3a43d0a9 100644 --- a/test/units/module_utils/facts/network/test_fc_wwn.py +++ b/test/units/module_utils/facts/network/test_fc_wwn.py @@ -54,8 +54,43 @@ HBA Port WWN: 10000090fa1658de NPIV Not Supported """ +IOSCAN_OUT = """ +Class I H/W Path Driver S/W State H/W Type Description +================================================================== +fc 0 2/0/10/1/0 fcd CLAIMED INTERFACE HP AB379-60101 4Gb Dual Port PCI/PCI-X Fibre Channel Adapter (FC Port 1) + /dev/fcd0 +""" -def mock_get_bin_path(cmd, required=False): +FCMSUTIL_OUT = """ + Vendor ID is = 0x1077 + Device ID is = 0x2422 + PCI Sub-system Vendor ID is = 0x103C + PCI Sub-system ID is = 0x12D7 + PCI Mode = PCI-X 133 MHz + ISP Code version = 5.4.0 + ISP Chip version = 3 + Topology = PTTOPT_FABRIC + Link Speed = 4Gb + Local N_Port_id is = 0x010300 + Previous N_Port_id is = None + N_Port Node World Wide Name = 0x50060b00006975ed + N_Port Port World Wide Name = 0x50060b00006975ec + Switch Port World Wide Name = 0x200300051e046c0f + Switch Node World Wide Name = 0x100000051e046c0f + N_Port Symbolic Port Name = server1_fcd0 + N_Port Symbolic Node Name = server1_HP-UX_B.11.31 + Driver state = ONLINE + Hardware Path is = 2/0/10/1/0 + Maximum Frame Size = 2048 + Driver-Firmware Dump Available = NO + Driver-Firmware Dump Timestamp = N/A + TYPE = PFC + NPIV Supported = YES + Driver Version = @(#) fcd B.11.31.1103 Dec 6 2010 +""" + + +def mock_get_bin_path(cmd, required=False, opt_dirs=None): result = None if cmd == 'lsdev': result = '/usr/sbin/lsdev' @@ -63,6 +98,10 @@ def mock_get_bin_path(cmd, required=False): result = '/usr/sbin/lscfg' elif cmd == 'fcinfo': result = '/usr/sbin/fcinfo' + elif cmd == 'ioscan': + result = '/usr/bin/ioscan' + elif cmd == 'fcmsutil': + result = '/opt/fcms/bin/fcmsutil' return result @@ -74,6 +113,10 @@ def mock_run_command(cmd): result = LSCFG_OUTPUT elif 'fcinfo' in cmd: result = FCINFO_OUTPUT + elif 'ioscan' in cmd: + result = IOSCAN_OUT + elif 'fcmsutil' in cmd: + result = FCMSUTIL_OUT else: rc = 1 result = 'Error' @@ -87,7 +130,7 @@ def test_get_fc_wwn_info(mocker): mocker.patch.object(module, 'get_bin_path', side_effect=mock_get_bin_path) mocker.patch.object(module, 'run_command', side_effect=mock_run_command) - d = {'aix6': ['10000090FA551508'], 'sunos5': ['10000090fa1658de']} + d = {'aix6': ['10000090FA551508'], 'sunos5': ['10000090fa1658de'], 'hp-ux11': ['0x50060b00006975ec']} for key, value in d.items(): mocker.patch('sys.platform', key) wwn_expected = {"fibre_channel_wwn": value}