blob: 2443bddc9707eee8c6ba5eca579f9b971ded2b9a [file] [log] [blame]
Michael Walshfdc5ced2017-08-17 13:15:15 -05001#!/usr/bin/env python
2
3r"""
4Companion file to utils.robot.
5"""
6
7import gen_print as gp
8import gen_robot_keyword as grk
Michael Walshf880ac62017-11-10 11:29:37 -06009import bmc_ssh_utils as bsu
10import var_funcs as vf
Michael Walshfdc5ced2017-08-17 13:15:15 -050011from robot.libraries.BuiltIn import BuiltIn
Michael Walshf880ac62017-11-10 11:29:37 -060012from robot.libraries import DateTime
Michael Walsh75575102018-10-04 15:10:44 -050013import json
Michael Walshf880ac62017-11-10 11:29:37 -060014try:
15 from robot.utils import DotDict
16except ImportError:
17 pass
18import collections
Michael Walshfdc5ced2017-08-17 13:15:15 -050019
20
Michael Walshfdc5ced2017-08-17 13:15:15 -050021def set_power_policy_method():
Michael Walshfdc5ced2017-08-17 13:15:15 -050022 r"""
23 Set the global bmc_power_policy_method to either 'Old' or 'New'.
24
25 The power policy data has moved from an 'org' location to an 'xyz'
26 location. This keyword will determine whether the new method of getting
27 the power policy is valid and will set the global bmc_power_policy_method
28 variable accordingly. If power_policy_setup is already set (by a prior
29 call to this function), this keyword will simply return.
30
31 If bmc_power_policy_method is "Old", this function will adjust the global
32 policy variables from data/variables.py: RESTORE_LAST_STATE,
33 ALWAYS_POWER_ON, ALWAYS_POWER_OFF.
34 """
35
36 # Retrieve global variables.
37 power_policy_setup = \
38 int(BuiltIn().get_variable_value("${power_policy_setup}",
39 default=0))
40 bmc_power_policy_method = \
41 BuiltIn().get_variable_value("${bmc_power_policy_method}",
42 default=0)
43 gp.dpvar(power_policy_setup)
44
45 # If this function has already been run once, we need not continue.
46 if power_policy_setup:
47 return
48
49 gp.dpvar(bmc_power_policy_method, 1)
50
51 # The user has not set bmc_power_policy_method via a -v parm so we will
52 # determine what it should be.
53 if bmc_power_policy_method == "":
54 status, ret_values = grk.run_key_u("New Get Power Policy", ignore=1)
55 if status == 'PASS':
56 bmc_power_policy_method = 'New'
57 else:
58 bmc_power_policy_method = 'Old'
59
60 gp.qpvar(bmc_power_policy_method)
61 # For old style, we will rewrite these global variable settings to old
62 # values.
63 if bmc_power_policy_method == "Old":
64 BuiltIn().set_global_variable("${RESTORE_LAST_STATE}",
65 "RESTORE_LAST_STATE")
66 BuiltIn().set_global_variable("${ALWAYS_POWER_ON}",
67 "ALWAYS_POWER_ON")
68 BuiltIn().set_global_variable("${ALWAYS_POWER_OFF}",
69 "ALWAYS_POWER_OFF")
70
71 # Set global variables to control subsequent calls to this function.
72 BuiltIn().set_global_variable("${bmc_power_policy_method}",
73 bmc_power_policy_method)
74 BuiltIn().set_global_variable("${power_policy_setup}", 1)
75
76
Michael Walshfdc5ced2017-08-17 13:15:15 -050077def translate_power_policy_value(policy):
Michael Walshfdc5ced2017-08-17 13:15:15 -050078 r"""
79 Translate the policy value and return the result.
80
81 Using old style functions, callers might call like this with a hard-
82 code value for policy:
83
George Keishingefc3ff22017-12-12 11:49:25 -060084 Set BMC Power Policy ALWAYS_POWER_OFF
Michael Walshfdc5ced2017-08-17 13:15:15 -050085
86 This function will get the value of the corresponding global variable (if
87 it exists) and return it.
88
89 This will allow the old style call to still work on systems using the new
90 method of storing the policy value.
91 """
92
93 valid_power_policy_vars = \
94 BuiltIn().get_variable_value("${valid_power_policy_vars}")
95
96 if policy not in valid_power_policy_vars:
97 return policy
98
99 status, ret_values = grk.run_key_u("Get Variable Value ${" + policy + "}",
100 quiet=1)
101 return ret_values
102
Michael Walshf880ac62017-11-10 11:29:37 -0600103
Michael Walshf880ac62017-11-10 11:29:37 -0600104def get_bmc_date_time():
Michael Walshf880ac62017-11-10 11:29:37 -0600105 r"""
106 Get date/time info from BMC and return as a dictionary.
107
108 Example of dictionary data returned by this keyword.
109 time_dict:
110 [local_time]: Fri 2017-11-03 152756 UTC
111 [local_time_seconds]: 1509740876
112 [universal_time]: Fri 2017-11-03 152756 UTC
113 [universal_time_seconds]: 1509740876
114 [rtc_time]: Fri 2016-05-20 163403
115 [rtc_time_seconds]: 1463780043
116 [time_zone]: n/a (UTC, +0000)
117 [network_time_on]: yes
118 [ntp_synchronized]: no
119 [rtc_in_local_tz]: no
120 """
121
122 out_buf, stderr, rc = bsu.bmc_execute_command('timedatectl')
123 # Example of output returned by call to timedatectl:
124 # Local time: Fri 2017-11-03 15:27:56 UTC
125 # Universal time: Fri 2017-11-03 15:27:56 UTC
126 # RTC time: Fri 2016-05-20 16:34:03
127 # Time zone: n/a (UTC, +0000)
128 # Network time on: yes
129 # NTP synchronized: no
130 # RTC in local TZ: no
131
132 # Convert the out_buf to a dictionary.
133 initial_time_dict = vf.key_value_outbuf_to_dict(out_buf)
134
135 # For each "_time" entry in the dictionary, we will create a corresponding
136 # "_time_seconds" entry. We create a new dictionary so that the entries
137 # are kept in a nice order for printing.
138 try:
139 result_time_dict = collections.OrderedDict()
140 except AttributeError:
141 result_time_dict = DotDict()
142
143 for key, value in initial_time_dict.items():
144 result_time_dict[key] = value
145 if not key.endswith("_time"):
146 continue
147 result_time_dict[key + '_seconds'] = \
148 int(DateTime.convert_date(value, result_format='epoch'))
149
150 return result_time_dict
151
Michael Walsh193743e2017-11-20 16:43:31 -0600152
153def get_bmc_df(df_parm_string=""):
Michael Walsh193743e2017-11-20 16:43:31 -0600154 r"""
155 Get df report from BMC and return as a report "object".
156
157 A df report object is a list where each entry is a dictionary whose keys
158 are the field names from the first entry in report_list.
159
160 Example df report object:
161
162 df_report:
163 df_report[0]:
164 [filesystem]: dev
165 [1k-blocks]: 247120
166 [used]: 0
167 [available]: 247120
168 [use%]: 0%
169 [mounted]: /dev
170 df_report[1]:
171 [filesystem]: dev
172 [1k-blocks]: 247120
173 [used]: 0
174 [available]: 247120
175 [use%]: 0%
176 [mounted]: /dev
177
178. Description of argument(s):
179 df_parm_string A string containing valid df command parms (e.g.
180 "-h /var").
181 """
182
183 out_buf, stderr, rc = bsu.bmc_execute_command("df " + df_parm_string)
184 return vf.outbuf_to_report(out_buf)
George Keishing6f407b92018-01-16 02:21:47 -0600185
186
187def get_sbe():
George Keishing6f407b92018-01-16 02:21:47 -0600188 r"""
189 Return CFAM value which contains such things as SBE side bit.
190 """
191
192 cmd_buf = "pdbg -d p9w -p0 getcfam 0x2808 | sed -re 's/.* = //g'"
193 out_buf, stderr, rc = bsu.bmc_execute_command(cmd_buf)
194
195 return int(out_buf, 16)
196
George Keishingbf724772018-02-21 08:57:16 -0600197
Gunnar Mills096cd562018-03-26 10:19:12 -0500198def compare_mac_address(sys_mac_addr, user_mac_addr):
George Keishingbf724772018-02-21 08:57:16 -0600199 r"""
200 Return 1 if the MAC value matched, otherwise 0.
201
202. Description of argument(s):
203 sys_mac_addr A valid system MAC string (e.g. "70:e2:84:14:2a:08")
204 user_mac_addr A user provided MAC string (e.g. "70:e2:84:14:2a:08")
205 """
206
207 index = 0
208 # Example: ['70', 'e2', '84', '14', '2a', '08']
209 mac_list = user_mac_addr.split(":")
210 for item in sys_mac_addr.split(":"):
211 if int(item, 16) == int(mac_list[index], 16):
212 index = index + 1
213 continue
214 return 0
215
216 return 1
Michael Walsh7847ece2018-04-12 11:37:45 -0500217
218
219def get_os_ethtool(interface_name):
220 r"""
221 Get OS 'ethtool' output for the given interface_name and return it as a
222 dictionary.
223
224 Settings for enP52p1s0f0:
225 Supported ports: [ TP ]
226 Supported link modes: 10baseT/Half 10baseT/Full
227 100baseT/Half 100baseT/Full
228 1000baseT/Half 1000baseT/Full
229 Supported pause frame use: No
230 Supports auto-negotiation: Yes
231 Supported FEC modes: Not reported
232 Advertised link modes: 10baseT/Half 10baseT/Full
233 100baseT/Half 100baseT/Full
234 1000baseT/Half 1000baseT/Full
235 Advertised pause frame use: Symmetric
236 Advertised auto-negotiation: Yes
237 Advertised FEC modes: Not reported
238 Speed: Unknown!
239 Duplex: Unknown! (255)
240 Port: Twisted Pair
241 PHYAD: 1
242 Transceiver: internal
243 Auto-negotiation: on
244 MDI-X: Unknown
245 Supports Wake-on: g
246 Wake-on: g
247 Current message level: 0x000000ff (255)
248 drv probe link timer ifdown ifup rx_err tx_err
249 Link detected: no
250
251 Given that data, this function will return the following dictionary.
252
253 ethtool_dict:
254 [supported_ports]: [ TP ]
255 [supported_link_modes]:
256 [supported_link_modes][0]: 10baseT/Half 10baseT/Full
257 [supported_link_modes][1]: 100baseT/Half 100baseT/Full
258 [supported_link_modes][2]: 1000baseT/Half 1000baseT/Full
259 [supported_pause_frame_use]: No
260 [supports_auto-negotiation]: Yes
261 [supported_fec_modes]: Not reported
262 [advertised_link_modes]:
263 [advertised_link_modes][0]: 10baseT/Half 10baseT/Full
264 [advertised_link_modes][1]: 100baseT/Half 100baseT/Full
265 [advertised_link_modes][2]: 1000baseT/Half 1000baseT/Full
266 [advertised_pause_frame_use]: Symmetric
267 [advertised_auto-negotiation]: Yes
268 [advertised_fec_modes]: Not reported
269 [speed]: Unknown!
270 [duplex]: Unknown! (255)
271 [port]: Twisted Pair
272 [phyad]: 1
273 [transceiver]: internal
274 [auto-negotiation]: on
275 [mdi-x]: Unknown
276 [supports_wake-on]: g
277 [wake-on]: g
278 [current_message_level]: 0x000000ff (255)
279 [drv_probe_link_timer_ifdown_ifup_rx_err_tx_err]:<blank>
280 [link_detected]: no
281 """
282
283 # Using sed and tail to massage the data a bit before running
284 # key_value_outbuf_to_dict.
285 cmd_buf = "ethtool " + interface_name +\
286 " | sed -re 's/(.* link modes:)(.*)/\\1\\n\\2/g' | tail -n +2"
287 stdout, stderr, rc = bsu.os_execute_command(cmd_buf)
288 result = vf.key_value_outbuf_to_dict(stdout, process_indent=1, strip=" \t")
289
290 return result
Michael Walsh75575102018-10-04 15:10:44 -0500291
292
293def to_json_ordered(json_str):
294 r"""
295 Parse the JSON string data and return an ordered JSON dictionary object.
296
297 Description of argument(s):
298 json_str The string containing the JSON data.
299 """
300
George Keishing36efbc02018-12-12 10:18:23 -0600301 try:
302 return json.loads(json_str, object_pairs_hook=DotDict)
303 except TypeError:
304 return json.loads(json_str.decode("utf-8"), object_pairs_hook=DotDict)
Michael Walsh35d78f22020-01-14 15:01:57 -0600305
306
307def get_bmc_release_info():
308 r"""
309 Get release info from the BMC and return as a dictionary.
310
311 Example:
312
313 ${release_info}= Get BMC Release Info
314 Rprint Vars release_info
315
316 Output:
317
318 release_info:
319 [id]: openbmc-phosphor
320 [name]: Phosphor OpenBMC (Phosphor OpenBMC Project Reference...
321 [version]: 2.8.0-dev
322 [version_id]: 2.8.0-dev-1083-g8954c3505
323 [pretty_name]: Phosphor OpenBMC (Phosphor OpenBMC Project Reference...
324 [build_id]: 2.8.0-dev
325 [openbmc_target_machine]: witherspoon
326 """
327
328 out_buf, stderr, rc = bsu.bmc_execute_command('cat /etc/os-release')
329 return vf.key_value_outbuf_to_dict(out_buf, delim="=", strip='"')
330
331
332def get_os_release_info():
333 r"""
334 Get release info from the OS and return as a dictionary.
335
336 Example:
337
338 ${release_info}= Get OS Release Info
339 Rprint Vars release_info
340
341 Output:
342 release_info:
343 [name]: Red Hat Enterprise Linux Server
344 [version]: 7.6 (Maipo)
345 [id]: rhel
346 [id_like]: fedora
347 [variant]: Server
348 [variant_id]: server
349 [version_id]: 7.6
350 [pretty_name]: Red Hat Enterprise Linux Server 7.6 (Maipo)
351 [ansi_color]: 0;31
352 [cpe_name]: cpe:/o:redhat:enterprise_linux:7.6:GA:server
353 [home_url]: https://www.redhat.com/
354 [bug_report_url]: https://bugzilla.redhat.com/
355 [redhat_bugzilla_product]: Red Hat Enterprise Linux 7
356 [redhat_bugzilla_product_version]: 7.6
357 [redhat_support_product]: Red Hat Enterprise Linux
358 [redhat_support_product_version]: 7.6
359 """
360
361 out_buf, stderr, rc = bsu.os_execute_command('cat /etc/os-release')
362 return vf.key_value_outbuf_to_dict(out_buf, delim="=", strip='"')