1#!/usr/bin/env python3
2
3import requests
4import websocket
5import json
6import ssl
7import gen_valid as gv
8import gen_print as gp
9
10
11class event_notification():
12    r"""
13    Main class to subscribe and receive event notifications.
14    """
15
16    def __init__(self, host, username, password):
17        r"""
18        Initialize instance variables.
19
20        Description of argument(s):
21        host        The IP or host name of the system to subscribe to.
22        username    The username for the host system.
23        password    The password for the host system.
24        """
25        self.__host = host
26        self.__user = username
27        self.__password = password
28
29    def __del__(self):
30        try:
31            self.__websocket.close()
32        except AttributeError:
33            pass
34
35    def login(self):
36        r"""
37        Login and return session object.
38        """
39        http_header = {'Content-Type': 'application/json'}
40        session = requests.session()
41        response = session.post('https://' + self.__host + '/login',
42                                headers=http_header,
43                                json={"data": [self.__user, self.__password]},
44                                verify=False, timeout=30)
45        gv.valid_value(response.status_code, valid_values=[200])
46        login_response = json.loads(response.text)
47        gp.qprint_var(login_response)
48        gv.valid_value(login_response['status'], valid_values=['ok'])
49        return session
50
51    def subscribe(self, dbus_path, enable_trace=False):
52
53        r"""
54        Subscribe to the given path and return a list of event notifications.
55
56        For more details on "subscribe" and "events" go to
57        https://github.com/openbmc/docs/blob/master/rest-api.md#event-subscription-protocol
58
59        Example robot code:
60        ${event_notifications}=  Subscribe  /xyz/openbmc_project/sensors
61        Rprint Vars  event_notifications
62
63        Example output:
64        event_notifications:
65          [0]:
66            [interface]:             xyz.openbmc_project.Sensor.Value
67            [path]:                  /xyz/openbmc_project/sensors/temperature/ambient
68            [event]:                 PropertiesChanged
69            [properties]:
70              [Value]:               23813
71
72        Description of argument(s):
73        dbus_path              The subscribing event's path (e.g.
74                               "/xyz/openbmc_project/sensors").
75        enable_trace           Enable or disable trace.
76        """
77
78        session = self.login()
79        cookies = session.cookies.get_dict()
80        # Convert from dictionary to a string of the following format:
81        # key=value;key=value...
82        cookies = gp.sprint_var(cookies, fmt=gp.no_header() | gp.strip_brackets(),
83                                col1_width=0, trailing_char="",
84                                delim="=").replace("\n", ";")
85
86        websocket.enableTrace(enable_trace)
87        self.__websocket = websocket.create_connection("wss://{host}/subscribe".format(host=self.__host),
88                                                       sslopt={"cert_reqs": ssl.CERT_NONE},
89                                                       cookie=cookies)
90        dbus_path = [path.strip() for path in dbus_path.split(',')]
91        dbus_path = {"paths": dbus_path}
92
93        self.__websocket.send(json.dumps(dbus_path))
94        event_notifications = json.loads(self.__websocket.recv())
95        self.__websocket.close()
96        return event_notifications
97