diff --git a/confluent_server/aiohmi/ipmi/oem/lenovo/config.py b/confluent_server/aiohmi/ipmi/oem/lenovo/config.py index 7ae16c66..35e72d3b 100644 --- a/confluent_server/aiohmi/ipmi/oem/lenovo/config.py +++ b/confluent_server/aiohmi/ipmi/oem/lenovo/config.py @@ -147,8 +147,12 @@ def _eval_conditional(expression, cfg, setting): class LenovoFirmwareConfig(object): def __init__(self, xc, useipmi=True): if not etree: - raise Exception("python-lxml and python-eficompressor required " - "for this function") + # Not a bare Exception. Confluent has no handler for one, so a + # missing optional dependency showed as "Unexpected Error" and hid + # the message below, which already names what to install. + raise pygexc.UnsupportedFunctionality( + "python-lxml and python-eficompressor required " + "for this function") if useipmi: self.connection = xc.ipmicmd else: diff --git a/confluent_server/aiohmi/redfish/oem/generic.py b/confluent_server/aiohmi/redfish/oem/generic.py index b44bc253..ba739fb4 100644 --- a/confluent_server/aiohmi/redfish/oem/generic.py +++ b/confluent_server/aiohmi/redfish/oem/generic.py @@ -1794,7 +1794,14 @@ class OEMHandler(object): errmsg = ','.join(errmsg) raise exc.RedfishError(errmsg) except (ValueError, KeyError): - raise exc.PyghmiException(str(url) + ":" + res[0]) + # Reached by an html 404 page, or anything else that is not + # the JSON error document. res[0] is bytes there, so building + # the message crashed and the caller saw that TypeError + # instead of the status and the body. + body = res[0] + if isinstance(body, bytes): + body = body.decode('utf-8', errors='replace') + raise exc.PyghmiException('{0}:{1}'.format(url, body)) if payload is None and method is None: self._urlcache[url] = { 'contents': res[0],