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