DMTF/python-redfish-library

"python-redfish-library" is not able to follow HTTP: 303 (Location Header) sent by Redfish Server correctly

KarnikJain opened this issue ยท 23 comments

Used following snippet:

import redfish
redfish_host = "https://{}".format("192.168.40.141")
redfish_account = "root"
redfish_password = "root"

## get redfish handle
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
for i in range(1):
    r = redfish_obj.post("/redfish/v1/Systems/000000000000/Actions/ComputerSystem.Reset", body={})
    print r.status
    print r.dict

Now, Redfish Library doing POST correctly to Redfish Server and Server sending it a 303 (Redirection) Response with TaskMonitor URI (/redfish/v1/TaskMonit/92a8da74-d8e9-485f-ba5d-5bd82a87e706) in "Location Header" and Now as per HTTP:303 Rule, Redfish Library has to do "GET" on sent TaskMonitor URI by Redfish Server but instead its doing "POST" only on TaskMonitor URI to Server and end-up getting "Method Not Allowed" (HTTP:405).
(https://en.wikipedia.org/wiki/HTTP_303)

Is it a bug or really can be fixed by some alternatives, Please do let me know at very earliest.

Tried same with POSTMAN, redfishtool and CURL, everybody is able to tackle 303 correctly for Task Based POST but redfish library not and Hence Raising a BUG here.

e.g. CURL Response: (Expected Query/Responses)
curl -L -k -u root:fungible -i -H "Content-Type: application/json" -d {} https://192.168.40.141/redfish/v1/Systems/000000000000/Actions/ComputerSystem.Reset

HTTP/1.1 303 See Other
Location: /redfish/v1/TaskMonit/92a8da74-d8e9-485f-ba5d-5bd82a87e706
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
OData-Version: 4.0
Cache-Control: no-cache
Cache-Control: no-store, no-cache
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-UA-Compatible: IE=11
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Pragma: no-cache
Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://:/mi_ws_msg_service; img-src 'self'; child-src 'self'
Content-Length: 154
Date: Mon, 26 Jan 1987 04:09:49 GMT
Server: lighttpd/1.4.52

HTTP/1.1 202 Accepted
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
OData-Version: 4.0
Cache-Control: no-cache
Cache-Control: no-store, no-cache
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-UA-Compatible: IE=11
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Pragma: no-cache
Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://:/mi_ws_msg_service; img-src 'self'; child-src 'self'
Content-Length: 554
Date: Mon, 26 Jan 1987 04:09:49 GMT
Server: lighttpd/1.4.52

{"@odata.id":"/redfish/v1/TaskMonit/92a8da74-d8e9-485f-ba5d-5bd82a87e706","Id":"1","Name":"Task 1","TaskState":"Running","TaskStatus":"OK","TaskMonitor":"/redfish/v1/TaskMonit/92a8da74-d8e9-485f-ba5d-5bd82a87e706","Messages":[{"@odata.type":"#Message.v1_0_8.Message","MessageId":"Common.1.0.0.UpdateServiceUpdateProgress","Message":"Action: ๏ฟฝ+Z in Progress","MessageArgs":["๏ฟฝ+Z"],"Severity":"OK","Resolution":"None."}],"@odata.type":"#Task.v1_4_3.Task","@odata.context":"/redfish/v1/$metadata#Task.Task","@odata.etag":"ea3620b0509a49127ab30f3e993fe4a0"}

@KarnikJain Thanks for investigating and opening the issue. I create PR #99 for this issue. But I don't have access to a Redfish service that responds with a 303 redirect, so I can't test it.

Can you please try out the fix in PR #99 and confirm if it fixes the issue?

I'm a bit confused about this; I would expect the Location header in the 303 response to be for the redirected URI. However, it seems that the redirected location is for the task monitor. This doesn't really follow the semantics for Redfish task management; I would only expect the Location header to point to a task monitor for a 202 response.

I do see some usage for 303 to be used in other RESTful applications for things similar to tasks, but the Redfish spec is pretty clear in the usage of task management in that a 202 response code is to be used.

@KarnikJain Thanks for investigating and opening the issue. I create PR #99 for this issue. But I don't have access to a Redfish service that responds with a 303 redirect, so I can't test it.

Can you please try out the fix in PR #99 and confirm if it fixes the issue?

Thank you so much for quick fix. I would test the patch today at earliest and update you the behavior.

@KarnikJain Thanks for investigating and opening the issue. I create PR #99 for this issue. But I don't have access to a Redfish service that responds with a 303 redirect, so I can't test it.
Can you please try out the fix in PR #99 and confirm if it fixes the issue?

Thank you so much for quick fix. I would test the patch today at earliest and update you the behavior.

Patch UT Results:
++++++++++++++

  • Still not working.
  • Now redfish_obj.post return 400 HTTP Return Code always with your patched redfish library.
  • After Patch, Its not doing POST also looks like for certain actions and only seeing GET on /redfish/v1/SessionService/Sessions URI as last.
  • For Certain Task based action, seeing POST to desired URI on Server side getting received but not followed GET on TaskMonitor URI.
  • Can you please help me to understand, Am I missing something in below Python to provide arguments to Redfish Server to get correct response with your patch, which I am getting all the time with CURL/redfishtool as mentioned below for your reference?

:~$ python task.py
400
Traceback (most recent call last):
File "task.py", line 11, in
print r.dict
File "/usr/local/lib/python2.7/dist-packages/redfish/rest/v1.py", line 241, in dict
return json.loads(self.text)
File "/usr/lib/python2.7/json/init.py", line 339, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

:~$ cat task.py
import redfish
redfish_host = "https://{}".format("192.168.40.141")
redfish_account = "root"
redfish_password = "root"
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
for i in range(1):
    r = redfish_obj.post("Systems/DPU/Actions/ComputerSystem.Reset", body={})
    print r.status
    print r.dict

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Tried the same with CURL Equivalent and "redfishtool" than again found both are behaving correctly as below but not the redfish library:

Redfish Client Query -> Redfish Server Response
POST -> 303 with location header
GET on TaskMonitor URI -> 202 Response

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

% curl -L -k -u root:root -i -H "Content-Type: application/json" -d {}  https://192.168.40.141/redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
HTTP/1.1 303 See Other
Location: /redfish/v1/TaskMonit/6fb8b2c7-e92f-443d-9632-2ed08cea76ac
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
OData-Version: 4.0
Cache-Control: no-cache
Cache-Control: no-store, no-cache
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-UA-Compatible: IE=11
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Pragma: no-cache
Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
Content-Length: 154
Date: Sat, 31 Jan 1987 06:24:24 GMT
Server: lighttpd/1.4.52

HTTP/1.1 202 Accepted
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
OData-Version: 4.0
Cache-Control: no-cache
Cache-Control: no-store, no-cache
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-UA-Compatible: IE=11
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Pragma: no-cache
Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
Content-Length: 606
Date: Sat, 31 Jan 1987 06:24:24 GMT
Server: lighttpd/1.4.52

{"@odata.id":"/redfish/v1/TaskMonit/6fb8b2c7-e92f-443d-9632-2ed08cea76ac","Id":"22","Name":"Task 22","TaskState":"Running","TaskStatus":"OK","TaskMonitor":"/redfish/v1/TaskMonit/6fb8b2c7-e92f-443d-9632-2ed08cea76ac","Messages":[{"@odata.type":"#Message.v1_0_8.Message","MessageId":"Common.1.0.0.UpdateServiceUpdateProgress","Message":"Action: Actions/ComputerSystem.Reset in Progress","MessageArgs":["Actions/ComputerSystem.Reset"],"Severity":"OK","Resolution":"None."}],"@odata.type":"#Task.v1_4_3.Task","@odata.context":"/redfish/v1/$metadata#Task.Task","@odata.etag":"b7f13f9562543a252777e7296969a487"}

Redfishtool Command Usage:
++++++++++++++++++++++

$ python3 ./redfishtool.py -r 192.168.40.141 -u root -p root -A Basic -S Always raw POST  -d '{}' '/redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset'

$ echo $?
0

@mraineri

Please refer to https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.11.0.pdf

In 7.11. POST (Action), page 52
There is 202 Accepted, A Location response header set to the URI of a task monitor.

DMTF doesn't define 3XX but you can check standard HTTP Code definition/explanation at https://en.wikipedia.org/wiki/HTTP_303

"The HTTP response status code 303 See Other is a way to redirect web applications to a new URI, particularly after a HTTP POST has been performed"

I'm not sure why the request is getting a 400 response with the patch. Can you modify your script to enable debugging and post the output? That may help me understand what is happening.

import logging
import redfish
redfish_host = "https://{}".format("192.168.40.141")
redfish_account = "root"
redfish_password = "root"
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
logging.basicConfig(level=logging.DEBUG)
for i in range(1):
    r = redfish_obj.post("Systems/DPU/Actions/ComputerSystem.Reset", body={})
    print r.status
    print r.dict

+++++++++++++++++++++++++++++++++++++++++++++++
First experiment with same ComputerSystemReset TaskService:
+++++++++++++++++++++++++++++++++++++++++++++++

cat task_debug.py
import logging
import redfish
redfish_host = "https://{}".format("192.168.40.141");
redfish_account = "root"
redfish_password = "root"
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
logging.basicConfig(level=logging.DEBUG)
for i in range(1):
    r = redfish_obj.post("Systems/DPU/Actions/ComputerSystem.Reset", body={})
    print r.status
    print r.dict

Just tried above suggested python script and its found that for this Task, I am not able to receive POST itself for ComputerSystem.Reset URI and last received URI was GET for /redfish/v1/SessionService/Sessions that's all.

Output of the Shared python script for your reference with Debug ON as suggested:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

python task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
        PATH: Systems/DPU/Actions/ComputerSystem.Reset
        BODY: {}
INFO:redfish.rest.v1:Attempt 1 of Systems/DPU/Actions/ComputerSystem.Reset
INFO:redfish.rest.v1:Response Time to Systems/DPU/Actions/ComputerSystem.Reset: 0.000418 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for Systems/DPU/Actions/ComputerSystem.Reset:
Code: 400 Bad Request
Headers:
        date: Sat, 31 Jan 1987 20:26:52 GMT
        content-length: 345
        content-type: text/html
        connection: close
        server: lighttpd/1.4.52

Body Response of Systems/DPU/Actions/ComputerSystem.Reset: <?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>400 Bad Request</title>
 </head>
 <body>
  <h1>400 Bad Request</h1>
 </body>
</html>

400
Traceback (most recent call last):
  File "task_debug.py", line 13, in <module>
    print r.dict
  File "/usr/local/lib/python2.7/dist-packages/redfish/rest/v1.py", line 241, in dict
    return json.loads(self.text)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Redfish Server Side Only Received :
+++++++++++++++++++++++++++

  1. GET on /redfish/v1/ URI and Server returned HTTP 200 OK Response to Python Lib Client.
  2. GET on /redfish/v1/SessionService/Sessions URI and Server returned HTTP 200 OK Response to Python Lib Client.
  3. that's all

+++++++++++++++++++++++++++++++++++++++++++++++++++
Second experiment with another TaskService Chassis Upgrade:
+++++++++++++++++++++++++++++++++++++++++++++++++++

cat task_debug.py
import logging
import redfish
redfish_host = "https://{}".format("192.168.40.141");
redfish_account = "root"
redfish_password = "root"
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
logging.basicConfig(level=logging.DEBUG)
for i in range(1):
    r = redfish_obj.post("/redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle", body={})
    print r.status
    print r.dict

Output of the script for your reference:
+++++++++++++++++++++++++++++

python task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
        PATH: /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle
        BODY: {}
INFO:redfish.rest.v1:Attempt 1 of /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle
INFO:redfish.rest.v1:Response Time to /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle: 0.001676 seconds.
INFO:redfish.rest.v1:Response Time to /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle: 0.00045 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle:
Code: 400 Bad Request
Headers:
        date: Sat, 31 Jan 1987 20:39:02 GMT
        content-length: 345
        content-type: text/html
        connection: close
        server: lighttpd/1.4.52

Body Response of /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle: <?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>400 Bad Request</title>
 </head>
 <body>
  <h1>400 Bad Request</h1>
 </body>
</html>

400
Traceback (most recent call last):
  File "task_debug.py", line 13, in <module>
    print r.dict
  File "/usr/local/lib/python2.7/dist-packages/redfish/rest/v1.py", line 241, in dict
    return json.loads(self.text)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Redfish Server Side Only Received :
+++++++++++++++++++++++++++

  1. GET on /redfish/v1/ URI and Server returned HTTP 200 OK Response to Python Lib Client.
  2. GET on /redfish/v1/SessionService/Sessions URI and Server returned HTTP 200 OK Response to Python Lib Client.
  3. POST on /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle URI and Server returned HTTP 303 with TaskMonitor URI in location header.
  4. That's all

Let me know, if any further debug details required from Redfish Server side.

From your task_debug.py script:

r = redfish_obj.post("Systems/DPU/Actions/ComputerSystem.Reset", body={})

I didn't notice this previously, but this doesn't look right. Shouldn't it be the following?

r = redfish_obj.post("/redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset", body={}):

Yes, That was my mistake. I assumed that default_prefix='/redfish/v1' would add that as default prefix to each request.
Now after adding that prefix manually the Server response is still 400 only but now both reported behaviour is matching.

Used Script now:
+++++++++++++

import logging
import redfish
redfish_host = "https://{}".format("192.168.40.141");
redfish_account = "root"
redfish_password = "root"
redfish_obj = redfish.redfish_client(base_url=redfish_host, username=redfish_account, password=redfish_password, default_prefix='/redfish/v1')
redfish_obj.login(auth="basic")
logging.basicConfig(level=logging.DEBUG)
r = redfish_obj.post("/redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset", body={})
print r.status
print r.dict
REDFISH_OBJ.logout()

Output of the script for your reference:
+++++++++++++++++++++++++++++

python task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
        PATH: /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
        BODY: {}
INFO:redfish.rest.v1:Attempt 1 of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.002838 seconds.
INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.000498 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset:
Code: **400** Bad Request
Headers:
        date: Sun, 01 Feb 1987 00:21:14 GMT
        content-length: 345
        content-type: text/html
        connection: close
        server: lighttpd/1.4.52

Body Response of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: <?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
  <title>400 Bad Request</title>
 </head>
 <body>
  <h1>400 Bad Request</h1>
 </body>
</html>

400
Traceback (most recent call last):
  File "task_debug.py", line 14, in <module>
    print r.dict
  File "/usr/local/lib/python2.7/dist-packages/redfish/rest/v1.py", line 241, in dict
    return json.loads(self.text)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Redfish Server Side Only Received :
+++++++++++++++++++++++++++

  • GET on /redfish/v1/ URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • GET on /redfish/v1/SessionService/Sessions URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • POST on /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset URI and Server returned HTTP 303 with TaskMonitor URI in location header.
  • That's all and on Client side, you would see the 400 Bad Request Error like earlier for both Task Cases explained above.

Thanks. That helped. I added a small logic change and some more debug to the PR. Can you please try that test again with the updated PR and post the output?

And some of the debug I added requires python 3, so if you could, please run using python 3.

Also, note that the debug output will include the Authorization: Basic xxxxxxxx header, so you may need to sanitize that from the output.

Sure..Let me try now.

UT Results of new Patch:
===================

Redfish Server Side Received :
++++++++++++++++++++++++

  • GET on /redfish/v1/ URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • GET on /redfish/v1/SessionService/Sessions URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • POST on /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset URI and Server returned HTTP 303 with TaskMonitor URI in location header.
  • POST on /redfish/v1/TaskMonit/ab61f678-7af0-4d92-95e4-e7a54d2860b1 Task Monitor URI this time again like Pristine Lib code instead doing GET on Task Monitor URI (Same BUG) and Hence Redfish Server Responded with 405 Method Not Allowed HTTP Error.

Output of the script for your reference:
+++++++++++++++++++++++++++++

python3 task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
	PATH: /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
	BODY: {}
INFO:redfish.rest.v1:Attempt 1 of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.061697784811258316 seconds.
INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.01918938895687461 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset:
Code: 405 Method Not Allowed
Headers:
	Access-Control-Allow-Origin: *
	Content-Type: application/json; charset=utf-8
	OData-Version: 4.0
	Cache-Control: no-cache
	Cache-Control: no-store, no-cache
	Allow: GET,DELETE
	X-Content-Type-Options: nosniff
	Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
	X-UA-Compatible: IE=11
	X-Frame-Options: SAMEORIGIN
	X-XSS-Protection: 1; mode=block
	Pragma: no-cache
	Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
	Content-Length: 550
	Date: Tue, 06 Jan 1987 11:30:32 GMT
	Server: lighttpd/1.4.52

Body Response of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: b'{"error":{"code":"Base.1.1.0.GeneralError","message":"A general error has occurred. See ExtendedInfo for more information.","@Message.ExtendedInfo":[{"@odata.type":"#Message.v1_0_8.Message","MessageId":"Base.1.1.0.ActionNotSupported","Message":"The action POST is not supported by the resource.","MessageArgs":["POST"],"Severity":"Critical","Resolution":"The action supplied cannot be resubmitted to the implementation.  Perhaps the action was invalid, the wrong resource was the target or the implementation documentation may be of assistance."}]}}\n'
405
{'error': {'code': 'Base.1.1.0.GeneralError', 'message': 'A general error has occurred. See ExtendedInfo for more information.', '@Message.ExtendedInfo': [{'@odata.type': '#Message.v1_0_8.Message', 'MessageId': 'Base.1.1.0.ActionNotSupported', 'Message': 'The action POST is not supported by the resource.', 'MessageArgs': ['POST'], 'Severity': 'Critical', 'Resolution': 'The action supplied cannot be resubmitted to the implementation.  Perhaps the action was invalid, the wrong resource was the target or the implementation documentation may be of assistance.'}]}}

We had a discussion about this issue in the group. We think it would be okay to make changes to the library to handle redirections in a generic manner (not specific to 303 though).

However, that being said, there are things you'll need to follow up with in term of the current behavior of your Redfish service. Much of this stems from the following clause in the Redfish spec:

Request has been accepted for processing but the processing has not been completed. The Location header shall be set to the URI of a task monitor that can later be queried to determine the status of the operation. The response body may include a representation of the Task resource.

On the subsequent GET from the 303, the response containing "202 Accepted" is missing the "Location" header, which is supposed to contain the task monitor URI. If the 303 is handled internally to the library and the caller only gets back this response, they will not have a way to monitor the task. Existing clients that receive a 202 as the HTTP status code will poll the URI found in the Location header.

The body of the 202 response is also not completely correct. It contains a representation of a task resource, but the URIs all show the task monitor. The task monitor URI and task resource URI have different behaviors:

  • The task resource can be discovered via the task service, and provides an administrative interface for managing tasks that are in progress or completed.
  • A GET on a task monitor URI for an operation that's still in progress will return with 202 Accepted, and may have a body for the task resource, but if the operation is complete, a GET on the task monitor will return with the response of the original operation (such as 200 OK and a response body for an action).
  • A GET on a task resource will always return 200 OK and the response will contain the task resource.

Thanks for rerunning. Unfortunately, it appears this run did not use the code from my latest PR (which is why it is still doing the POST on the 303 redirected URI).

From your output above:

INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.061697784811258316 seconds.
INFO:redfish.rest.v1:Response Time to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.01918938895687461 seconds.

In the PR, that line of output should include the method called and the redirected URI:

        LOGGER.info('Response Time for %s to %s: %s seconds.' %
                               (method, reqpath, str(endtime-inittime)))

Can you double-check your python3 environment to be sure the PR is installed and try again?

Yeah. Really Sorry again. I have ignorantly used "pip" instead using "pip3" for installation with new patch.
Now it's working exactly as required. We are good to GO for commit of the patch !! ๐Ÿ‘

Output of the script for your reference:
+++++++++++++++++++++++++++++

python3 task_debug.py
kjain@karnik-vm1:~$ python3 task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
	PATH: /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
	BODY: {}
INFO:redfish.rest.v1:Attempt 1 of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset
INFO:redfish.rest.v1:Response Time for POST to /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: 0.06710832100361586 seconds.
send: b'GET /redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed HTTP/1.1\r\nHost: 10.1.40.141\r\nAccept-Encoding: identity\r\nAuthorization: Basic cm9vdDpmdW5naWJsZQ==\r\nAccept: */*\r\nConnection: Keep-Alive\r\nOData-Version: 4.0\r\n\r\n'
reply: 'HTTP/1.1 202 Accepted\r\n'
header: Access-Control-Allow-Origin: *
header: Content-Type: application/json; charset=utf-8
header: OData-Version: 4.0
header: Cache-Control: no-cache
header: Cache-Control: no-cache
header: X-Content-Type-Options: nosniff
header: Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
header: X-UA-Compatible: IE=11
header: X-Frame-Options: SAMEORIGIN
header: X-XSS-Protection: 1; mode=block
header: Pragma: no-cache
header: Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
header: Content-Length: 604
header: Date: Mon, 05 Jan 1987 18:59:34 GMT
header: Server: lighttpd/1.4.52
INFO:redfish.rest.v1:Response Time for GET to /redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed: 0.026223924942314625 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset:
Code: 202 Accepted
Headers:
	Access-Control-Allow-Origin: *
	Content-Type: application/json; charset=utf-8
	OData-Version: 4.0
	Cache-Control: no-cache
	Cache-Control: no-store, no-cache
	X-Content-Type-Options: nosniff
	Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
	X-UA-Compatible: IE=11
	X-Frame-Options: SAMEORIGIN
	X-XSS-Protection: 1; mode=block
	Pragma: no-cache
	Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
	Content-Length: 604
	Date: Mon, 05 Jan 1987 18:59:34 GMT
	Server: lighttpd/1.4.52

Body Response of /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset: b'{"@odata.id":"/redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed","Id":"2","Name":"Task 2","TaskState":"Running","TaskStatus":"OK","TaskMonitor":"/redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed","Messages":[{"@odata.type":"#Message.v1_0_8.Message","MessageId":"Common.1.0.0.UpdateServiceUpdateProgress","Message":"Action: Actions/ComputerSystem.Reset in Progress","MessageArgs":["Actions/ComputerSystem.Reset"],"Severity":"OK","Resolution":"None."}],"@odata.type":"#Task.v1_4_3.Task","@odata.context":"/redfish/v1/$metadata#Task.Task","@odata.etag":"6337d8870a81c2830646300bbd46ccd3"}\n'
202
{'@odata.id': '/redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed', 'Id': '2', 'Name': 'Task 2', 'TaskState': 'Running', 'TaskStatus': 'OK', 'TaskMonitor': '/redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed', 'Messages': [{'@odata.type': '#Message.v1_0_8.Message', 'MessageId': 'Common.1.0.0.UpdateServiceUpdateProgress', 'Message': 'Action: Actions/ComputerSystem.Reset in Progress', 'MessageArgs': ['Actions/ComputerSystem.Reset'], 'Severity': 'OK', 'Resolution': 'None.'}], '@odata.type': '#Task.v1_4_3.Task', '@odata.context': '/redfish/v1/$metadata#Task.Task', '@odata.etag': '6337d8870a81c2830646300bbd46ccd3'}

Another Task POST via same script: (Just to be double make sure ๐Ÿ‘ )
+++++++++++++++++++++++++++

python3 task_debug.py
DEBUG:redfish.rest.v1:HTTP REQUEST: POST
	PATH: /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle
	BODY: {}
INFO:redfish.rest.v1:Attempt 1 of /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle
INFO:redfish.rest.v1:Response Time for POST to /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle: 0.055616182275116444 seconds.
send: b'GET /redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6 HTTP/1.1\r\nHost: 10.1.40.141\r\nAccept-Encoding: identity\r\nAuthorization: Basic cm9vdDpmdW5naWJsZQ==\r\nAccept: */*\r\nConnection: Keep-Alive\r\nOData-Version: 4.0\r\n\r\n'
reply: 'HTTP/1.1 202 Accepted\r\n'
header: Access-Control-Allow-Origin: *
header: Content-Type: application/json; charset=utf-8
header: OData-Version: 4.0
header: Cache-Control: no-cache
header: Cache-Control: no-cache
header: X-Content-Type-Options: nosniff
header: Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
header: X-UA-Compatible: IE=11
header: X-Frame-Options: SAMEORIGIN
header: X-XSS-Protection: 1; mode=block
header: Pragma: no-cache
header: Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
header: Content-Length: 640
header: Date: Mon, 05 Jan 1987 19:20:34 GMT
header: Server: lighttpd/1.4.52
INFO:redfish.rest.v1:Response Time for GET to /redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6: 0.018306194804608822 seconds.
DEBUG:redfish.rest.v1:HTTP RESPONSE for /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle:
Code: 202 Accepted
Headers:
	Access-Control-Allow-Origin: *
	Content-Type: application/json; charset=utf-8
	OData-Version: 4.0
	Cache-Control: no-cache
	Cache-Control: no-store, no-cache
	X-Content-Type-Options: nosniff
	Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
	X-UA-Compatible: IE=11
	X-Frame-Options: SAMEORIGIN
	X-XSS-Protection: 1; mode=block
	Pragma: no-cache
	Content-Security-Policy: default-src 'none'; frame-src 'self' data:; style-src 'self'; font-src 'self'; script-src 'self'; object-src 'self'; connect-src 'self' wss://*:*/mi_ws_msg_service; img-src 'self'; child-src 'self'
	Content-Length: 640
	Date: Mon, 05 Jan 1987 19:20:34 GMT
	Server: lighttpd/1.4.52

Body Response of /redfish/v1/UpdateService/Actions/Oem/UpdateService.UpdateChassisBundle: b'{"@odata.id":"/redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6","Id":"1","Name":"Task 1","TaskState":"Running","TaskStatus":"OK","TaskMonitor":"/redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6","Messages":[{"@odata.type":"#Message.v1_0_8.Message","MessageId":"Common.1.0.0.UpdateServiceUpdateProgress","Message":"Action: /Actions/Oem/UpdateService.UpdateChassisBundle in Progress","MessageArgs":["/Actions/Oem/UpdateService.UpdateChassisBundle"],"Severity":"OK","Resolution":"None."}],"@odata.type":"#Task.v1_4_3.Task","@odata.context":"/redfish/v1/$metadata#Task.Task","@odata.etag":"ff615e88540af459403709faed9d0ea0"}\n'
202
{'@odata.id': '/redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6', 'Id': '1', 'Name': 'Task 1', 'TaskState': 'Running', 'TaskStatus': 'OK', 'TaskMonitor': '/redfish/v1/TaskMonit/5a828465-6dfd-456f-9c80-6994d92573c6', 'Messages': [{'@odata.type': '#Message.v1_0_8.Message', 'MessageId': 'Common.1.0.0.UpdateServiceUpdateProgress', 'Message': 'Action: /Actions/Oem/UpdateService.UpdateChassisBundle in Progress', 'MessageArgs': ['/Actions/Oem/UpdateService.UpdateChassisBundle'], 'Severity': 'OK', 'Resolution': 'None.'}], '@odata.type': '#Task.v1_4_3.Task', '@odata.context': '/redfish/v1/$metadata#Task.Task', '@odata.etag': 'ff615e88540af459403709faed9d0ea0'}

Redfish Server Side Received : (Its working as expected now ๐Ÿ‘)
+++++++++++++++++++++++

  • GET on /redfish/v1/ URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • GET on /redfish/v1/SessionService/Sessions URI and Server returned HTTP 200 OK Response to Python Lib Client.
  • POST on /redfish/v1/Systems/DPU/Actions/ComputerSystem.Reset URI and Server returned HTTP 303 with TaskMonitor URI in location header.
  • GET on /redfish/v1/TaskMonit/6e31286f-dca9-4673-8ef9-142c7fb396ed Task Monitor URI this time finally ๐Ÿ‘

@KarnikJain That's great. Thanks for testing.

@KarnikJain please see my recent comments about this issue; while we can generically add redirection support, there are some flaws with the service you're working with that need to be addressed. You will likely need to contact your service vendor for followup.

@mraineri Sure. will update them.
@billdodd May I know, when fix would be committed to master, so that I can share this to our team members to start using them?

@KarnikJain We will have our weekly meeting tomorrow (12/4/2020) to review PRs. If it is approved, it will get merged to master at that time. If there are concerns with the change or updates are requested, there will be some delay. I will know more after the meeting tomorrow.

sure. Thanks you

@KarnikJain PR #99 was approved and merged to master today.

@billdodd Thank you so much. Really appreciate your prompt help and support.
@mraineri Thank you.