Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | r""" |
| 4 | See redfish_plus class prolog below for details. |
| 5 | """ |
| 6 | |
| 7 | from redfish.rest.v1 import HttpClient |
| 8 | import gen_print as gp |
Michael Walsh | 2477e09 | 2019-05-17 15:48:56 -0500 | [diff] [blame] | 9 | import func_args as fa |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 10 | |
| 11 | |
| 12 | def valid_http_status_code(status, valid_status_codes): |
| 13 | r""" |
| 14 | Raise exception if status is not found in the valid_status_codes list. |
| 15 | |
| 16 | Description of argument(s): |
| 17 | status An HTTP status code (e.g. 200, 400, etc.). |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 18 | valid_status_codes A list of status codes that the caller considers acceptable. If this is |
| 19 | a null list, then any status code is considered acceptable. Note that |
| 20 | for the convenience of the caller, valid_status_codes may be either a |
| 21 | python list or a string which can be evaluated to become a python list |
| 22 | (e.g. "[200]"). |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 23 | """ |
| 24 | |
| 25 | if type(valid_status_codes) is not list: |
| 26 | valid_status_codes = eval(valid_status_codes) |
| 27 | if len(valid_status_codes) == 0: |
| 28 | return |
| 29 | if status in valid_status_codes: |
| 30 | return |
| 31 | |
| 32 | message = "The HTTP status code was not valid:\n" |
| 33 | message += gp.sprint_vars(status, valid_status_codes) |
| 34 | raise ValueError(message) |
| 35 | |
| 36 | |
| 37 | class redfish_plus(HttpClient): |
| 38 | r""" |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 39 | redfish_plus is a wrapper for redfish rest that provides the following benefits vs. using redfish |
| 40 | directly: |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 41 | |
| 42 | For rest_request functions (e.g. get, put, post, etc.): |
| 43 | - Function-call logging to stdout. |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 44 | - Automatic valid_status_codes processing (i.e. an exception will be raised if the rest response |
| 45 | status code is not as expected. |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 46 | - Easily used from robot programs. |
| 47 | """ |
| 48 | |
| 49 | ROBOT_LIBRARY_SCOPE = 'TEST SUITE' |
| 50 | |
| 51 | def rest_request(self, func, *args, **kwargs): |
| 52 | r""" |
| 53 | Perform redfish rest request and return response. |
| 54 | |
| 55 | This function provides the following additional functionality. |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 56 | - The calling function's call line is logged to standard out (provided that global variable "quiet" |
| 57 | is not set). |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 58 | - The caller may include a valid_status_codes argument. |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 59 | - Callers may include inline python code strings to define arguments. This predominantly benefits |
| 60 | robot callers. |
Michael Walsh | 2477e09 | 2019-05-17 15:48:56 -0500 | [diff] [blame] | 61 | |
| 62 | For example, instead of calling like this: |
| 63 | ${data}= Create Dictionary HostName=${hostname} |
| 64 | Redfish.patch ${REDFISH_NW_PROTOCOL_URI} body=&{data} |
| 65 | |
| 66 | Callers may do this: |
| 67 | |
| 68 | Redfish.patch ${REDFISH_NW_PROTOCOL_URI} |
| 69 | ... body=[('HostName', '${hostname}')] |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 70 | |
| 71 | Description of argument(s): |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 72 | func A reference to the parent class function which is to be called (e.g. get, |
| 73 | put, etc.). |
| 74 | args This is passed directly to the function referenced by the func argument |
| 75 | (see the documentation for the corresponding redfish HttpClient method |
| 76 | for details). |
| 77 | kwargs This is passed directly to the function referenced by the func argument |
| 78 | (see the documentation for the corresponding redfish HttpClient method |
| 79 | for details) with the following exception: If kwargs contains a |
| 80 | valid_status_codes key, it will be removed from kwargs and processed by |
| 81 | this function. This allows the caller to indicate what rest status codes |
| 82 | are acceptable. The default value is [200]. See the |
| 83 | valid_http_status_code function above for details. |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 84 | |
| 85 | Example uses: |
| 86 | |
| 87 | From a python program: |
| 88 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 89 | response = bmc_redfish.get("/redfish/v1/Managers/bmc/EthernetInterfaces", [200, 201]) |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 90 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 91 | If this call to the get method generates a response.status equal to anything other than 200 or 201, |
| 92 | an exception will be raised. |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 93 | |
| 94 | From a robot program: |
| 95 | |
| 96 | BMC_Redfish.logout |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 97 | ${response}= BMC_Redfish.Get /redfish/v1/Managers/bmc/EthernetInterfaces valid_status_codes=[401] |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 98 | |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 99 | As part of a robot test, the programmer has logged out to verify that the get request will generate a |
| 100 | status code of 401 (i.e. "Unauthorized"). |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 101 | """ |
| 102 | gp.qprint_executing(stack_frame_ix=3, style=gp.func_line_style_short) |
Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 103 | # Convert python string object definitions to objects (mostly useful for robot callers). |
Michael Walsh | 2477e09 | 2019-05-17 15:48:56 -0500 | [diff] [blame] | 104 | args = fa.args_to_objects(args) |
| 105 | kwargs = fa.args_to_objects(kwargs) |
Michael Walsh | 35139f9 | 2019-03-01 15:58:05 -0600 | [diff] [blame] | 106 | valid_status_codes = kwargs.pop('valid_status_codes', [200]) |
| 107 | response = func(*args, **kwargs) |
| 108 | valid_http_status_code(response.status, valid_status_codes) |
| 109 | return response |
| 110 | |
| 111 | # Define rest function wrappers. |
| 112 | def get(self, *args, **kwargs): |
| 113 | return self.rest_request(super(redfish_plus, self).get, *args, |
| 114 | **kwargs) |
| 115 | |
| 116 | def head(self, *args, **kwargs): |
| 117 | return self.rest_request(super(redfish_plus, self).head, *args, |
| 118 | **kwargs) |
| 119 | |
| 120 | def post(self, *args, **kwargs): |
| 121 | return self.rest_request(super(redfish_plus, self).post, *args, |
| 122 | **kwargs) |
| 123 | |
| 124 | def put(self, *args, **kwargs): |
| 125 | return self.rest_request(super(redfish_plus, self).put, *args, |
| 126 | **kwargs) |
| 127 | |
| 128 | def patch(self, *args, **kwargs): |
| 129 | return self.rest_request(super(redfish_plus, self).patch, *args, |
| 130 | **kwargs) |
| 131 | |
| 132 | def delete(self, *args, **kwargs): |
| 133 | return self.rest_request(super(redfish_plus, self).delete, *args, |
| 134 | **kwargs) |
| 135 | |
| 136 | def __del__(self): |
| 137 | del self |