DMTF/python-redfish-library

Can't terminate a redfish session via .logout()

Closed this issue · 13 comments

I'm using the redfish library to manage the Cisco IMC on class C UCS servers. The .logout() function fails both if I call it explicitly or if it is invoked via context manager. Strangely, I can terminate the session just fine via custom code with requests.

from redfish.rest.v1 import HttpClient
from requests import delete
from urllib3 import disable_warnings, exceptions

disable_warnings(exceptions.InsecureRequestWarning)


class CIMC(HttpClient):
    def __enter__(self):
        self.login()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        try:
            self.logout()
        except Exception as e:
            print(e)
            d = delete(url=f'{self.get_base_url() + self.get_session_location()}',
                       headers={'X-Auth-Token': self.get_session_key()}, verify=False)
            if d.status_code in [200, 202, 204]:
                print('Logged out via requests')
            else:
                print(d.reason)
        else:
            print('Logged out via redfish library')


login_host = "https://x.x.x.x"
login_account = "user"
login_password = "password"

with CIMC(base_url=login_host, username=login_account, password=login_password, max_retry=2) as cimc_cx:
    b = cimc_cx.get("/redfish/v1/Managers/CIMC")
    print(b)

This is only a workaround, but I would like to know why the native logout() function fails.

Here is the printout my context manager __exit__ function:

Invalid session resource: /redfish/v1/SessionService/Sessions/3336, return code: 404
Logged out via requests

As you can tell, logout was performed via requests using the parameters that would be used via the native logout() function. I doubt that the issue is the redfish implementation on the CIMC.

Unfortunately I don't have access to a Cisco system. I am curious if this could be another redirect issue with the library.

Could you please add allow_redirects=False to your delete call? I'm wondering what the behavior is in this case.

Could you also please provide the output of pip show redfish so I can confirm your library version?

That didn't change anything

d = requests.delete(url=f'{self.get_base_url() + self.get_session_location()}', headers={'X-Auth-Token': self.get_session_key()}, verify=False, allow_redirects=False)
.
.
Invalid session resource: /redfish/v1/SessionService/Sessions/3467, return code: 404
Logged out via requests
Name: redfish
Version: 3.0.1
Summary: Redfish Python Library
Home-page: https://github.com/DMTF/python-redfish-library
Author: DMTF, https://www.dmtf.org/standards/feedback
Author-email: None
License: BSD 3-clause "New" or "Revised License"
Location: c:\users\......\appdata\local\programs\python\python39\lib\site-packages
Requires: jsonpatch, jsonpath-rw, jsonpointer
Required-by:

Great, thanks for checking that for me. I'll work on ways to debug and root cause what's going on.

By the way, there is a CIMC Emulator that can be deployed virtually, but when I used it to develop my script, I noticed that it didn't return a session location.

I'll take a look at that, but I'd be worried about the fact that session info isn't used for the emulator.

I've been looking at the debug logging capabilities in the library and we can instrument your script to use it. One of the things that's missing in the debug logging is adding traces for request headers (it logs response headers, just not request headers). Would you be able to install the changes on branch "add-request-headers-to-debug"?

Once you do that, can you add the following to your script:

After from urllib3 import disable_warnings, exceptions, add:

import logging
from redfish import redfish_logger

After login_password = "password", add:

LOGGERFILE = "trace.log"
LOGGERFORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
LOGGER = redfish_logger(LOGGERFILE, LOGGERFORMAT, logging.DEBUG)

When you run the script again, we can inspect trace.log to see what's happening exactly in the library for HTTP requests/responses. Please note that it does show the contents of the POST operation to the session collection, which includes the username and password. So, if you'd like to hide that, please edit that out of the logfile prior to posting.

Please see attached
trace.log

@mraineri Here are the differences in the redfish lib's headers vs the ones sent by the requests lib:

2021/06/28 17:24:08 map[Accept:[*/*] Accept-Encoding:[identity] Connection:[Keep-Alive] Odata-Version:[4.0] X-Auth-Token:[e34e63e060bba9b3506bb00653063905]]
2021/06/28 17:24:08 map[Accept:[*/*] Accept-Encoding:[gzip, deflate] Connection:[keep-alive] Content-Length:[0] User-Agent:[python-requests/2.22.0] X-Auth-Token:[e34e63e060bba9b3506bb00653063905]]

@azuniga88 thanks for providing that info. Based on @pboyd04's testing, I'm inclined to think that the service is expecting the Content-Length header in the request. It really shouldn't be necessary, but I'd like to experiment with it if possible. I've updated the "add-request-headers-to-debug" branch to include the Content-Length header even if there is no request body. Could you please test this for me?

I'm also reaching out to other contacts to help with the investigation; hopefully they can confirm the behavior.

@mraineri, thanks for sticking with this one. Unfortunately, that still didn't work. I've attached the trace file.

trace.log

Please reach out to Cisco TAC for further help.

@iamadan1 please try reaching out to Cisco as @sphuong1 has suggested. Unfortunately I think we need help from their support team.

@adan-zuniga were you able to get support from Cisco? There have also been improvements to the library to change a lot of the lower layer to use requests as opposed to duplicating the work.

Closing; no updates for additional feedback based on changes to the library and reaching Cisco reps for support. If the latest version of the library still hits this issue, please reopen.