From ba1eb4aa99db7b78168ff2b0d19918924a0cb2aa Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Mon, 7 Nov 2016 15:36:04 +0100 Subject: [PATCH] Raise a reasonable error on non-nullable flags with empty text Now it fails with AttributeError: 'NoneType' object has no attribute 'strip'. Raise a new exception with proper explanation instead. Partial-Bug: #1550328 Change-Id: Ie9f9d212c934bb75e8224dd64ec8df7f788b86d3 --- dracclient/exceptions.py | 4 + dracclient/tests/test_utils.py | 15 ++++ dracclient/tests/utils.py | 3 +- .../wsman_mocks/cpu_view-enum-empty_flag.xml | 75 +++++++++++++++++++ dracclient/utils.py | 6 ++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 dracclient/tests/wsman_mocks/cpu_view-enum-empty_flag.xml diff --git a/dracclient/exceptions.py b/dracclient/exceptions.py index 0672129..2982930 100644 --- a/dracclient/exceptions.py +++ b/dracclient/exceptions.py @@ -35,6 +35,10 @@ class DRACUnexpectedReturnValue(DRACRequestFailed): '%(expected_return_value)s') +class DRACEmptyResponseField(BaseClientException): + msg_fmt = ("Attribute '%(attr)s' is not nullable, but no value received") + + class InvalidParameterValue(BaseClientException): msg_fmt = '%(reason)s' diff --git a/dracclient/tests/test_utils.py b/dracclient/tests/test_utils.py index e31df2c..a5e71f7 100644 --- a/dracclient/tests/test_utils.py +++ b/dracclient/tests/test_utils.py @@ -15,6 +15,7 @@ import re from lxml import etree +from dracclient import exceptions from dracclient.resources import uris from dracclient.tests import base from dracclient.tests import utils as test_utils @@ -63,3 +64,17 @@ class UtilsTestCase(base.BaseTest): allow_missing=True) self.assertIsNone(val) + + def test_get_wsman_resource_attr_missing_text(self): + expected_message = ("Attribute 'HyperThreadingEnabled' is not nullable" + ", but no value received") + doc = etree.fromstring( + test_utils.InventoryEnumerations[ + uris.DCIM_CPUView]['empty_flag']) + cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, + find_all=True) + + self.assertRaisesRegexp( + exceptions.DRACEmptyResponseField, re.escape(expected_message), + utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, + 'HyperThreadingEnabled', allow_missing=False) diff --git a/dracclient/tests/utils.py b/dracclient/tests/utils.py index 3dc8a77..1adcf8f 100644 --- a/dracclient/tests/utils.py +++ b/dracclient/tests/utils.py @@ -100,7 +100,8 @@ BIOSInvocations = { InventoryEnumerations = { uris.DCIM_CPUView: { 'ok': load_wsman_xml('cpu_view-enum-ok'), - 'missing_flags': load_wsman_xml('cpu_view-enum-missing_flags') + 'missing_flags': load_wsman_xml('cpu_view-enum-missing_flags'), + 'empty_flag': load_wsman_xml('cpu_view-enum-empty_flag'), }, uris.DCIM_MemoryView: { 'ok': load_wsman_xml('memory_view-enum-ok') diff --git a/dracclient/tests/wsman_mocks/cpu_view-enum-empty_flag.xml b/dracclient/tests/wsman_mocks/cpu_view-enum-empty_flag.xml new file mode 100644 index 0000000..f2ec203 --- /dev/null +++ b/dracclient/tests/wsman_mocks/cpu_view-enum-empty_flag.xml @@ -0,0 +1,75 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:dd7ea19a-8633-4fa4-a43a-66ae8220f689 + uuid:247e710c-29de-19de-93c9-f148d4fe83b0 + + + + + + B3 + 1 + 7 + 4 + 0 + 0 + 1 + 2 + 384 + 5 + 1 + 7 + 5 + 1 + 0 + 1 + 2 + 1536 + 5 + 1 + 14 + 5 + 2 + 0 + 1 + 2 + 15360 + 5 + 1 + 4 + 2400 + CPU 1 + 0 + 0 + 6400 + CPU.Socket.1 + + + CPU.Socket.1 + 20160107171416.000000+000 + 20151112172601.000000+000 + Intel + 4000 + Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz + 6 + 12 + 6 + 1 + 1 + 1 + 1 + 1 + 1.3 + + + + + + + diff --git a/dracclient/utils.py b/dracclient/utils.py index 61f9116..4f503da 100644 --- a/dracclient/utils.py +++ b/dracclient/utils.py @@ -15,6 +15,8 @@ Common functionalities shared between different DRAC modules. """ +from dracclient import exceptions + NS_XMLSchema_Instance = 'http://www.w3.org/2001/XMLSchema-instance' # ReturnValue constants @@ -59,6 +61,8 @@ def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False, AttributeError. :raises: AttributeError if the attribute is missing from the XML doc and allow_missing is False. + :raises: DRACEmptyResponseField if the attribute is present in the XML doc + but it has no text and nullable is False. :returns: value of the attribute """ item = find_xml(doc, attr_name, resource_uri) @@ -70,6 +74,8 @@ def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False, raise AttributeError("Could not find attribute '%s'" % (attr_name)) if not nullable: + if item.text is None: + raise exceptions.DRACEmptyResponseField(attr=attr_name) return item.text.strip() else: nil_attr = item.attrib.get('{%s}nil' % NS_XMLSchema_Instance)