1#!/usr/bin/env python
2
3r"""
4Provide useful ipmi functions.
5"""
6
7import re
8import gen_print as gp
9import gen_misc as gm
10import gen_robot_keyword as grk
11import gen_robot_utils as gru
12import bmc_ssh_utils as bsu
13import var_funcs as vf
14import tempfile
15gru.my_import_resource("ipmi_client.robot")
16from robot.libraries.BuiltIn import BuiltIn
17
18
19def get_sol_info():
20    r"""
21    Get all SOL info and return it as a dictionary.
22
23    Example use:
24
25    Robot code:
26    ${sol_info}=  get_sol_info
27    Rpvars  sol_info
28
29    Output:
30    sol_info:
31      sol_info[Info]:                                SOL parameter 'Payload Channel (7)' not supported - defaulting to 0x0e
32      sol_info[Character Send Threshold]:            1
33      sol_info[Force Authentication]:                true
34      sol_info[Privilege Level]:                     USER
35      sol_info[Set in progress]:                     set-complete
36      sol_info[Retry Interval (ms)]:                 100
37      sol_info[Non-Volatile Bit Rate (kbps)]:        IPMI-Over-Serial-Setting
38      sol_info[Character Accumulate Level (ms)]:     100
39      sol_info[Enabled]:                             true
40      sol_info[Volatile Bit Rate (kbps)]:            IPMI-Over-Serial-Setting
41      sol_info[Payload Channel]:                     14 (0x0e)
42      sol_info[Payload Port]:                        623
43      sol_info[Force Encryption]:                    true
44      sol_info[Retry Count]:                         7
45    """
46
47    status, ret_values = grk.run_key_u("Run IPMI Standard Command  sol info")
48
49    # Create temp file path.
50    temp = tempfile.NamedTemporaryFile()
51    temp_file_path = temp.name
52
53    # Write sol info to temp file path.
54    text_file = open(temp_file_path, "w")
55    text_file.write(ret_values)
56    text_file.close()
57
58    # Use my_parm_file to interpret data.
59    sol_info = gm.my_parm_file(temp_file_path)
60
61    return sol_info
62
63
64def set_sol_setting(setting_name, setting_value):
65    r"""
66    Set SOL setting with given value.
67
68    # Description of argument(s):
69    # setting_name    SOL setting which needs to be set (e.g. "retry-count").
70    # setting_value   Value which needs to be set (e.g. "7").
71    """
72
73    status, ret_values = grk.run_key_u("Run IPMI Standard Command  sol set " +
74                                       setting_name + " " + setting_value)
75
76    return status
77
78
79def get_lan_print_dict():
80    r"""
81    Get IPMI 'lan print' output and return it as a dictionary.
82
83    Here is an example of the IPMI lan print output:
84
85    Set in Progress         : Set Complete
86    Auth Type Support       : MD5
87    Auth Type Enable        : Callback : MD5
88                            : User     : MD5
89                            : Operator : MD5
90                            : Admin    : MD5
91                            : OEM      : MD5
92    IP Address Source       : Static Address
93    IP Address              : x.x.x.x
94    Subnet Mask             : x.x.x.x
95    MAC Address             : xx:xx:xx:xx:xx:xx
96    Default Gateway IP      : x.x.x.x
97    802.1q VLAN ID          : Disabled
98    Cipher Suite Priv Max   : Not Available
99    Bad Password Threshold  : Not Available
100
101    Given that data, this function will return the following dictionary.
102
103    lan_print_dict:
104      [Set in Progress]:                              Set Complete
105      [Auth Type Support]:                            MD5
106      [Auth Type Enable]:
107        [Callback]:                                   MD5
108        [User]:                                       MD5
109        [Operator]:                                   MD5
110        [Admin]:                                      MD5
111        [OEM]:                                        MD5
112      [IP Address Source]:                            Static Address
113      [IP Address]:                                   x.x.x.x
114      [Subnet Mask]:                                  x.x.x.x
115      [MAC Address]:                                  xx:xx:xx:xx:xx:xx
116      [Default Gateway IP]:                           x.x.x.x
117      [802.1q VLAN ID]:                               Disabled
118      [Cipher Suite Priv Max]:                        Not Available
119      [Bad Password Threshold]:                       Not Available
120
121    """
122
123    IPMI_INBAND_CMD = BuiltIn().get_variable_value("${IPMI_INBAND_CMD}")
124
125    # Notice in the example of data above that 'Auth Type Enable' needs some
126    # special processing.  We essentially want to isolate its data and remove
127    # the 'Auth Type Enable' string so that key_value_outbuf_to_dict can
128    # process it as a sub-dictionary.
129    cmd_buf = IPMI_INBAND_CMD + " lan print | grep -E '^(Auth Type Enable)" +\
130        "?[ ]+: ' | sed -re 's/^(Auth Type Enable)?[ ]+: //g'"
131    stdout1, stderr, rc = bsu.os_execute_command(cmd_buf)
132
133    # Now get the remainder of the data and exclude the lines with no field
134    # names (i.e. the 'Auth Type Enable' sub-fields).
135    cmd_buf = IPMI_INBAND_CMD + " lan print | grep -E -v '^[ ]+: '"
136    stdout2, stderr, rc = bsu.os_execute_command(cmd_buf)
137
138    # Make auth_type_enable_dict sub-dictionary...
139    auth_type_enable_dict = vf.key_value_outbuf_to_dict(stdout1, to_lower=0,
140                                                        underscores=0)
141
142    # Create the lan_print_dict...
143    lan_print_dict = vf.key_value_outbuf_to_dict(stdout2, to_lower=0,
144                                                 underscores=0)
145    # Re-assign 'Auth Type Enable' to contain the auth_type_enable_dict.
146    lan_print_dict['Auth Type Enable'] = auth_type_enable_dict
147
148    return lan_print_dict
149
150
151def get_ipmi_power_reading(strip_watts=1):
152    r"""
153    Get IPMI power reading data and return it as a dictionary.
154
155    The data is obtained by issuing the IPMI "power reading" command.  An
156    example is shown below:
157
158    Instantaneous power reading:                   234 Watts
159    Minimum during sampling period:                234 Watts
160    Maximum during sampling period:                234 Watts
161    Average power reading over sample period:      234 Watts
162    IPMI timestamp:                           Thu Jan  1 00:00:00 1970
163    Sampling period:                          00000000 Seconds.
164    Power reading state is:                   deactivated
165
166    For the data shown above, the following dictionary will be returned.
167
168    result:
169      [instantaneous_power_reading]:              238 Watts
170      [minimum_during_sampling_period]:           238 Watts
171      [maximum_during_sampling_period]:           238 Watts
172      [average_power_reading_over_sample_period]: 238 Watts
173      [ipmi_timestamp]:                           Thu Jan  1 00:00:00 1970
174      [sampling_period]:                          00000000 Seconds.
175      [power_reading_state_is]:                   deactivated
176
177    Description of argument(s):
178    strip_watts  Strip all dictionary values of the trailing " Watts"
179                 substring.
180    """
181
182    status, ret_values = \
183        grk.run_key_u("Run IPMI Standard Command  dcmi power reading")
184    result = vf.key_value_outbuf_to_dict(ret_values)
185
186    if strip_watts:
187        result.update((k, re.sub(' Watts$', '', v)) for k, v in result.items())
188
189    return result
190
191
192def get_mc_info():
193    r"""
194    Get IPMI mc info data and return it as a dictionary.
195
196    The data is obtained by issuing the IPMI "mc info" command.  An
197    example is shown below:
198
199    Device ID                 : 0
200    Device Revision           : 0
201    Firmware Revision         : 2.01
202    IPMI Version              : 2.0
203    Manufacturer ID           : 42817
204    Manufacturer Name         : Unknown (0xA741)
205    Product ID                : 16975 (0x424f)
206    Product Name              : Unknown (0x424F)
207    Device Available          : yes
208    Provides Device SDRs      : yes
209    Additional Device Support :
210        Sensor Device
211        SEL Device
212        FRU Inventory Device
213        Chassis Device
214    Aux Firmware Rev Info     :
215        0x00
216        0x00
217        0x00
218        0x00
219
220    For the data shown above, the following dictionary will be returned.
221    mc_info:
222      [device_id]:                       0
223      [device_revision]:                 0
224      [firmware_revision]:               2.01
225      [ipmi_version]:                    2.0
226      [manufacturer_id]:                 42817
227      [manufacturer_name]:               Unknown (0xA741)
228      [product_id]:                      16975 (0x424f)
229      [product_name]:                    Unknown (0x424F)
230      [device_available]:                yes
231      [provides_device_sdrs]:            yes
232      [additional_device_support]:
233        [additional_device_support][0]:  Sensor Device
234        [additional_device_support][1]:  SEL Device
235        [additional_device_support][2]:  FRU Inventory Device
236        [additional_device_support][3]:  Chassis Device
237      [aux_firmware_rev_info]:
238        [aux_firmware_rev_info][0]:      0x00
239        [aux_firmware_rev_info][1]:      0x00
240        [aux_firmware_rev_info][2]:      0x00
241        [aux_firmware_rev_info][3]:      0x00
242    """
243
244    status, ret_values = \
245        grk.run_key_u("Run IPMI Standard Command  mc info")
246    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)
247
248    return result
249
250
251def get_sdr_info():
252    r"""
253    Get IPMI sdr info data and return it as a dictionary.
254
255    The data is obtained by issuing the IPMI "sdr info" command.  An
256    example is shown below:
257
258    SDR Version                         : 0x51
259    Record Count                        : 216
260    Free Space                          : unspecified
261    Most recent Addition                :
262    Most recent Erase                   :
263    SDR overflow                        : no
264    SDR Repository Update Support       : unspecified
265    Delete SDR supported                : no
266    Partial Add SDR supported           : no
267    Reserve SDR repository supported    : no
268    SDR Repository Alloc info supported : no
269
270    For the data shown above, the following dictionary will be returned.
271    mc_info:
272
273      [sdr_version]:                         0x51
274      [record_Count]:                        216
275      [free_space]:                          unspecified
276      [most_recent_addition]:
277      [most_recent_erase]:
278      [sdr_overflow]:                        no
279      [sdr_repository_update_support]:       unspecified
280      [delete_sdr_supported]:                no
281      [partial_add_sdr_supported]:           no
282      [reserve_sdr_repository_supported]:    no
283      [sdr_repository_alloc_info_supported]: no
284    """
285
286    status, ret_values = \
287        grk.run_key_u("Run IPMI Standard Command  sdr info")
288    result = vf.key_value_outbuf_to_dict(ret_values, process_indent=1)
289
290    return result
291