CiscoUcs / ucsmsdk

Python SDK for Cisco UCSM
Other
80 stars 60 forks source link

Python 3.12 support or issue with ansible module call to ucsmsdk ?: #240

Open GregDuhamel opened 10 months ago

GregDuhamel commented 10 months ago

Hello,

thanks for python 3.11 support back in October.

Fedora 39 now use python 3.12 by default, would it be possible to have support for it ? Currently I've an error while using ucsmsdk through ansible module :

The full traceback is:
  File "/tmp/ansible_cisco.ucs.ucs_org_payload_l5k808zp/ansible_cisco.ucs.ucs_org_payload.zip/ansible_collections/cisco/ucs/plugins/module_utils/ucs.py", line 91, in login
    handle.login()
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucshandle.py", line 135, in login
    return self._login(auto_refresh, force, timeout=timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucssession.py", line 599, in _login
    response = self.post_elem(elem, timeout=timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucssession.py", line 315, in post_elem
    response_str = self.post_xml(xml_str, timeout=timeout)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucssession.py", line 264, in post_xml
    response_str = self.post(uri=ucsm_uri, data=xml_str, read=read, timeout=timeout)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucssession.py", line 243, in post
    response = self.__driver.post(uri=uri, data=data, read=read,
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucsdriver.py", line 262, in post
    response = opener.open(request, timeout=timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/urllib/request.py", line 515, in open
    response = self._open(req, data)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/urllib/request.py", line 532, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/urllib/request.py", line 492, in _call_chain
    result = func(*args)
             ^^^^^^^^^^^
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucsdriver.py", line 55, in https_open
    return self.do_open(TLSConnection, req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.12/urllib/request.py", line 1344, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib64/python3.12/http/client.py", line 1319, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1365, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1314, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1074, in _send_output
    self.send(msg)
  File "/usr/lib64/python3.12/http/client.py", line 1018, in send
    self.connect()
  File "/home/gduhamel/.local/lib/python3.12/site-packages/ucsmsdk/ucsdriver.py", line 87, in connect
    if self.key_file and self.cert_file:
       ^^^^^^^^^^^^^
fatal: [ucs-01]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "delegate_to": "localhost",
            "description": "",
            "hostname": "ucs-01",
            "org_name": "flexpod",
            "parent_org_path": "root",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": null,
            "proxy": null,
            "state": "present",
            "use_proxy": true,
            "use_ssl": false,
            "username": "admin"
        }
    },
    "msg": "'TLSConnection' object has no attribute 'key_file'"
}

Thanks a lot !

ekrichbaum commented 9 months ago

a lot more digging here. in ucsdriver.py, the code uses httplib. That library was updated:

Changed in version 3.12: The deprecated key_file, cert_file and check_hostname parameters have been removed.

This is probably above my abilities, but if I read this correctly, we need an additional check for version 3.12 that adjusts accordingly not to use key_file with the block at line 81. This would also add support for TLS1.3 potentially?? I'm also unclear on the TLS1Handler but key_file and cert_file both exist there as well.

ekrichbaum commented 9 months ago

not necessarily elegant and maybe incomplete but I just put a wrapper around the self.key_file segment:

        if sys.version_info >= (2, 7, 9):
            # Since python 2.7.9, tls 1.1 and 1.2 are supported via
            # SSLContext
            ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
            ssl_context.options |= ssl.OP_NO_SSLv2
            ssl_context.options |= ssl.OP_NO_SSLv3
            if sys.version_info <= (3, 7):
                if self.key_file and self.cert_file:
                    ssl_context.load_cert_chain(keyfile=self.key_file,
                        certfile=self.cert_file)
            self.sock = ssl_context.wrap_socket(sock)