summaryrefslogtreecommitdiffstats
path: root/stafd.py
blob: 6701499e449b5d8388d5cf35cdf45563c3cdf192 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/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,
            subsysnqn: str,
            host_traddr: str,
            host_iface: str,
            host_nqn: str,
            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
        def tron(self, value):
            '''@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)

        def controller_info(  # pylint: disable=too-many-arguments
            self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
        ) -> str:
            '''@brief D-Bus method used to return information about a controller'''
            controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
            return json.dumps(controller.info()) if controller else '{}'

        def get_log_pages(  # pylint: disable=too-many-arguments
            self, transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn
        ) -> list:
            '''@brief D-Bus method used to retrieve the discovery log pages from one controller'''
            controller = STAF.get_controller(transport, traddr, trsvcid, subsysnqn, host_traddr, host_iface, host_nqn)
            return controller.log_pages() if controller else list()

        def get_all_log_pages(self, detailed) -> str:
            '''@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)

        def list_controllers(self, detailed) -> list:
            '''@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()