2025-02-16 12:41:59 +01:00
|
|
|
#!/usr/bin/python3
|
|
|
|
# Copyright (c) 2021, Dell Inc. or its subsidiaries. All rights reserved.
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# See the LICENSE file for details.
|
|
|
|
#
|
|
|
|
# This file is part of NVMe STorage Appliance Services (nvme-stas).
|
|
|
|
#
|
|
|
|
# Authors: Martin Belanger <Martin.Belanger@dell.com>
|
|
|
|
#
|
|
|
|
''' STorage Appliance Finder Daemon
|
|
|
|
'''
|
|
|
|
import sys
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
from staslib import defs
|
|
|
|
|
|
|
|
|
|
|
|
# ******************************************************************************
|
|
|
|
def parse_args(conf_file: str):
|
|
|
|
'''Parse command line options'''
|
|
|
|
parser = ArgumentParser(description='STorage Appliance Finder (STAF). Must be root to run this program.')
|
|
|
|
parser.add_argument(
|
|
|
|
'-f',
|
|
|
|
'--conf-file',
|
|
|
|
action='store',
|
|
|
|
help='Configuration file (default: %(default)s)',
|
|
|
|
default=conf_file,
|
|
|
|
type=str,
|
|
|
|
metavar='FILE',
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
'-s',
|
|
|
|
'--syslog',
|
|
|
|
action='store_true',
|
|
|
|
help='Send messages to syslog instead of stdout. Use this when running %(prog)s as a daemon. (default: %(default)s)',
|
|
|
|
default=False,
|
|
|
|
)
|
|
|
|
parser.add_argument('--tron', action='store_true', help='Trace ON. (default: %(default)s)', default=False)
|
|
|
|
parser.add_argument('-v', '--version', action='store_true', help='Print version, then exit', default=False)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
|
|
|
ARGS = parse_args(defs.STAFD_CONF_FILE)
|
|
|
|
|
|
|
|
if ARGS.version:
|
|
|
|
print(f'nvme-stas {defs.VERSION}')
|
|
|
|
print(f'libnvme {defs.LIBNVME_VERSION}')
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
|
|
# ******************************************************************************
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
import dasbus.server.interface
|
|
|
|
from staslib import log, service, stas, udev # pylint: disable=ungrouped-imports
|
|
|
|
|
|
|
|
# Before going any further, make sure the script is allowed to run.
|
|
|
|
stas.check_if_allowed_to_continue()
|
|
|
|
|
|
|
|
class Dbus:
|
|
|
|
'''This is the DBus interface that external programs can use to
|
|
|
|
communicate with stafd.
|
|
|
|
'''
|
|
|
|
|
|
|
|
__dbus_xml__ = stas.load_idl('stafd.idl')
|
|
|
|
|
|
|
|
@dasbus.server.interface.dbus_signal
|
|
|
|
def log_pages_changed( # pylint: disable=too-many-arguments
|
|
|
|
self,
|
|
|
|
transport: str,
|
|
|
|
traddr: str,
|
|
|
|
trsvcid: str,
|
2025-02-16 12:54:59 +01:00
|
|
|
subsysnqn: str,
|
2025-02-16 12:41:59 +01:00
|
|
|
host_traddr: str,
|
|
|
|
host_iface: str,
|
2025-02-16 12:54:59 +01:00
|
|
|
host_nqn: str,
|
2025-02-16 12:41:59 +01:00
|
|
|
device: str,
|
|
|
|
):
|
|
|
|
'''@brief Signal sent when log pages have changed.'''
|
|
|
|
|
|
|
|
@dasbus.server.interface.dbus_signal
|
|
|
|
def dc_removed(self):
|
|
|
|
'''@brief Signal sent when log pages have changed.'''
|
|
|
|
|
|
|
|
@property
|
|
|
|
def tron(self):
|
|
|
|
'''@brief Get Trace ON property'''
|
|
|
|
return STAF.tron
|
|
|
|
|
|
|
|
@tron.setter
|
2025-02-16 12:56:36 +01:00
|
|
|
def tron(self, value):
|
2025-02-16 12:41:59 +01:00
|
|
|
'''@brief Set Trace ON property'''
|
|
|
|
STAF.tron = value
|
|
|
|
|
|
|
|
@property
|
|
|
|
def log_level(self) -> str:
|
|
|
|
'''@brief Get Log Level property'''
|
|
|
|
return log.level()
|
|
|
|
|
|
|
|
def process_info(self) -> str:
|
|
|
|
'''@brief Get status info (for debug)
|
|
|
|
@return A string representation of a json object.
|
|
|
|
'''
|
|
|
|
info = {
|
|
|
|
'tron': STAF.tron,
|
|
|
|
'log-level': self.log_level,
|
|
|
|
}
|
|
|
|
info.update(STAF.info())
|
|
|
|
return json.dumps(info)
|
|
|
|
|
2025-02-16 12:56:36 +01:00
|
|
|
def controller_info( # pylint: disable=too-many-arguments
|
2025-02-16 12:54:59 +01:00
|
|
|
self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
|
2025-02-16 12:41:59 +01:00
|
|
|
) -> str:
|
|
|
|
'''@brief D-Bus method used to return information about a controller'''
|
2025-02-16 12:54:59 +01:00
|
|
|
controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
|
2025-02-16 12:41:59 +01:00
|
|
|
return json.dumps(controller.info()) if controller else '{}'
|
|
|
|
|
2025-02-16 12:56:36 +01:00
|
|
|
def get_log_pages( # pylint: disable=too-many-arguments
|
2025-02-16 12:54:59 +01:00
|
|
|
self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
|
2025-02-16 12:41:59 +01:00
|
|
|
) -> list:
|
|
|
|
'''@brief D-Bus method used to retrieve the discovery log pages from one controller'''
|
2025-02-16 12:54:59 +01:00
|
|
|
controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
|
2025-02-16 12:41:59 +01:00
|
|
|
return controller.log_pages() if controller else list()
|
|
|
|
|
2025-02-16 12:56:36 +01:00
|
|
|
def get_all_log_pages(self, detailed) -> str:
|
2025-02-16 12:41:59 +01:00
|
|
|
'''@brief D-Bus method used to retrieve the discovery log pages from all controllers'''
|
|
|
|
log_pages = list()
|
|
|
|
for controller in STAF.get_controllers():
|
|
|
|
log_pages.append(
|
|
|
|
{
|
|
|
|
'discovery-controller': controller.details() if detailed else controller.controller_id_dict(),
|
|
|
|
'log-pages': controller.log_pages(),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
return json.dumps(log_pages)
|
|
|
|
|
2025-02-16 12:56:36 +01:00
|
|
|
def list_controllers(self, detailed) -> list:
|
2025-02-16 12:41:59 +01:00
|
|
|
'''@brief Return the list of discovery controller IDs'''
|
|
|
|
return [
|
|
|
|
controller.details() if detailed else controller.controller_id_dict()
|
|
|
|
for controller in STAF.get_controllers()
|
|
|
|
]
|
|
|
|
|
|
|
|
log.init(ARGS.syslog)
|
|
|
|
STAF = service.Staf(ARGS, Dbus())
|
|
|
|
STAF.run()
|
|
|
|
|
|
|
|
STAF = None
|
|
|
|
ARGS = None
|
|
|
|
|
|
|
|
udev.shutdown()
|
|
|
|
|
|
|
|
logging.shutdown()
|