George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | r""" |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 4 | See class prolog below for details. |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 5 | """ |
| 6 | |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 7 | import sys |
| 8 | import re |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 9 | from redfish_plus import redfish_plus |
George Keishing | 2296e8c | 2019-02-01 05:49:58 -0600 | [diff] [blame] | 10 | from robot.libraries.BuiltIn import BuiltIn |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 11 | |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 12 | import func_args as fa |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 13 | import gen_print as gp |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 14 | |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 15 | |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 16 | class bmc_redfish(redfish_plus): |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 17 | r""" |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 18 | bmc_redfish is a child class of redfish_plus that is designed to provide |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 19 | benefits specifically for using redfish to communicate with an OpenBMC. |
| 20 | |
| 21 | See the prologs of the methods below for details. |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 22 | """ |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 23 | |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 24 | def __init__(self, *args, **kwargs): |
| 25 | r""" |
| 26 | Do BMC-related redfish initialization. |
| 27 | |
| 28 | Presently, older versions of BMC code may not support redfish |
| 29 | requests. This can lead to unsightly error text being printed out for |
| 30 | programs that may use lib/bmc_redfish_resource.robot even though they |
| 31 | don't necessarily intend to make redfish requests. |
| 32 | |
| 33 | This class method will make an attempt to tolerate this situation. At |
| 34 | some future point, when all BMCs can be expected to support redfish, |
| 35 | this class method may be considered for deletion. If it is deleted, |
| 36 | the self.__inited__ test code in the login() class method below should |
| 37 | likewise be deleted. |
| 38 | """ |
| 39 | self.__inited__ = False |
| 40 | try: |
| 41 | super(bmc_redfish, self).__init__(*args, **kwargs) |
| 42 | self.__inited__ = True |
| 43 | except ValueError as get_exception: |
| 44 | except_type, except_value, except_traceback = sys.exc_info() |
| 45 | regex = r"The HTTP status code was not valid:[\r\n]+status:[ ]+502" |
| 46 | result = re.match(regex, str(except_value), flags=re.MULTILINE) |
| 47 | if not result: |
| 48 | gp.lprint_var(except_type) |
| 49 | gp.lprint_varx("except_value", str(except_value)) |
| 50 | raise(get_exception) |
| 51 | |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 52 | def login(self, *args, **kwargs): |
| 53 | r""" |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 54 | Assign BMC default values for username, password and auth arguments |
| 55 | and call parent class login method. |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 56 | |
| 57 | Description of argument(s): |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 58 | args See parent class method prolog for details. |
| 59 | kwargs See parent class method prolog for details. |
George Keishing | e62d8b0 | 2018-11-29 12:01:56 -0600 | [diff] [blame] | 60 | """ |
George Keishing | 4c39401 | 2019-02-01 06:03:02 -0600 | [diff] [blame] | 61 | |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 62 | if not self.__inited__: |
Michael Walsh | 707ed0e | 2019-05-17 15:27:25 -0500 | [diff] [blame] | 63 | message = "bmc_redfish.__init__() was never successfully run. It " |
| 64 | message += "is likely that the target BMC firmware code level " |
| 65 | message += "does not support redfish.\n" |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 66 | raise ValueError(message) |
George Keishing | 97c9394 | 2019-03-04 12:45:07 -0600 | [diff] [blame] | 67 | # Assign default values for username, password, auth where necessary. |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 68 | openbmc_username = BuiltIn().get_variable_value("${OPENBMC_USERNAME}") |
| 69 | openbmc_password = BuiltIn().get_variable_value("${OPENBMC_PASSWORD}") |
| 70 | username, args, kwargs = fa.pop_arg(openbmc_username, *args, **kwargs) |
| 71 | password, args, kwargs = fa.pop_arg(openbmc_password, *args, **kwargs) |
| 72 | auth, args, kwargs = fa.pop_arg('session', *args, **kwargs) |
George Keishing | 4c39401 | 2019-02-01 06:03:02 -0600 | [diff] [blame] | 73 | |
Michael Walsh | ce7c4b5 | 2019-03-20 17:33:15 -0500 | [diff] [blame] | 74 | super(bmc_redfish, self).login(username, password, auth, |
| 75 | *args, **kwargs) |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 76 | |
| 77 | def get_properties(self, *args, **kwargs): |
| 78 | r""" |
| 79 | Return dictionary of attributes for a given path. |
| 80 | |
| 81 | The difference between calling this function and calling get() |
| 82 | directly is that this function returns ONLY the dictionary portion of |
| 83 | the response object. |
| 84 | |
| 85 | Example robot code: |
| 86 | |
| 87 | ${properties}= Get Properties /redfish/v1/Systems/system/ |
Michael Walsh | 39c0051 | 2019-07-17 10:54:06 -0500 | [diff] [blame] | 88 | Rprint Vars properties |
Michael Walsh | 5cc8919 | 2019-03-12 16:43:38 -0500 | [diff] [blame] | 89 | |
| 90 | Output: |
| 91 | |
| 92 | properties: |
| 93 | [PowerState]: Off |
| 94 | [Processors]: |
| 95 | [@odata.id]: /redfish/v1/Systems/system/Processors |
| 96 | [SerialNumber]: 1234567 |
| 97 | ... |
| 98 | |
| 99 | Description of argument(s): |
| 100 | args See parent class get() prolog for details. |
| 101 | kwargs See parent class get() prolog for details. |
| 102 | """ |
| 103 | |
| 104 | resp = self.get(*args, **kwargs) |
| 105 | return resp.dict if hasattr(resp, 'dict') else {} |
| 106 | |
| 107 | def get_attribute(self, path, attribute, default=None, *args, **kwargs): |
| 108 | r""" |
| 109 | Get and return the named attribute from the properties for a given |
| 110 | path. |
| 111 | |
| 112 | This method has the following advantages over calling get_properties |
| 113 | directly: |
| 114 | - The caller can specify a default value to be returned if the |
| 115 | attribute does not exist. |
| 116 | |
| 117 | Example robot code: |
| 118 | |
| 119 | ${attribute}= Get Attribute /redfish/v1/AccountService |
| 120 | ... MaxPasswordLength default=600 |
| 121 | Rprint Vars attribute |
| 122 | |
| 123 | Output: |
| 124 | |
| 125 | attribute: 31 |
| 126 | |
| 127 | Description of argument(s): |
| 128 | path The path (e.g. |
| 129 | "/redfish/v1/AccountService"). |
| 130 | attribute The name of the attribute to be retrieved |
| 131 | (e.g. "MaxPasswordLength"). |
| 132 | default The default value to be returned if the |
| 133 | attribute does not exist (e.g. ""). |
| 134 | args See parent class get() prolog for details. |
| 135 | kwargs See parent class get() prolog for details. |
| 136 | """ |
| 137 | |
| 138 | return self.get_properties(path, *args, **kwargs).get(attribute, |
| 139 | default) |
| 140 | |
| 141 | def get_session_info(self): |
| 142 | r""" |
| 143 | Get and return session info as a tuple consisting of session_key and |
| 144 | session_location. |
| 145 | """ |
| 146 | |
| 147 | return self.get_session_key(), self.get_session_location() |