From b87d729dcadd9d7b2066086d9bfc00d4e6533321 Mon Sep 17 00:00:00 2001 From: Chris Coyle Date: Wed, 6 Apr 2016 15:00:11 -0400 Subject: [PATCH] Add memory enumeration to InventoryManagement Change-Id: I0e58122a8d68d927b057aeedd2c127d62d9bae92 --- doc/source/client-api.rst | 10 +++++ dracclient/client.py | 12 ++++++ dracclient/resources/inventory.py | 36 +++++++++++++++++ dracclient/resources/uris.py | 3 ++ dracclient/tests/test_client.py | 27 +++++++++++++ dracclient/tests/utils.py | 6 +++ .../memory-enumeration-enum-ok.xml | 40 +++++++++++++++++++ 7 files changed, 134 insertions(+) create mode 100644 dracclient/tests/wsman_mocks/memory-enumeration-enum-ok.xml diff --git a/doc/source/client-api.rst b/doc/source/client-api.rst index 163d71f..4bdb405 100644 --- a/doc/source/client-api.rst +++ b/doc/source/client-api.rst @@ -159,6 +159,16 @@ Required parameters: * ``raid_controller``: id of the RAID controller. +Inventory Management +-------------------- + +list_cpus +~~~~~~~~~ +Returns a list of installed CPUs. + +list_memory +~~~~~~~~~~~ +Returns a list of installed memory modules. Job management -------------- diff --git a/dracclient/client.py b/dracclient/client.py index d5a4356..ef32f74 100644 --- a/dracclient/client.py +++ b/dracclient/client.py @@ -420,6 +420,18 @@ class DRACClient(object): """ return self._inventory_mgmt.list_cpus() + def list_memory(self): + """Returns a list of memory modules + + :returns: a list of Memory objects + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return self._inventory_mgmt.list_memory() + class WSManClient(wsman.Client): """Wrapper for wsman.Client with return value checking""" diff --git a/dracclient/resources/inventory.py b/dracclient/resources/inventory.py index 08b757b..7272236 100644 --- a/dracclient/resources/inventory.py +++ b/dracclient/resources/inventory.py @@ -21,6 +21,10 @@ CPU = collections.namedtuple( ['id', 'cores', 'speed', 'ht_enabled', 'model', 'status', 'turbo_enabled', 'vt_enabled']) +Memory = collections.namedtuple( + 'Memory', + ['id', 'size', 'speed', 'manufacturer', 'model', 'status']) + PrimaryStatus = { '0': 'Unknown', '1': 'OK', @@ -71,3 +75,35 @@ class InventoryManagement(object): def _get_cpu_attr(self, cpu, attr_name): return utils.get_wsman_resource_attr( cpu, uris.DCIM_CPUView, attr_name) + + def list_memory(self): + """Returns the list of installed memory + + :returns: a list of Memory objects + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + """ + + doc = self.client.enumerate(uris.DCIM_MemoryView) + + installed_memory = utils.find_xml(doc, 'DCIM_MemoryView', + uris.DCIM_MemoryView, + find_all=True) + + return [self._parse_memory(memory) for memory in installed_memory] + + def _parse_memory(self, memory): + return Memory(id=self._get_memory_attr(memory, 'FQDD'), + size=int(self._get_memory_attr(memory, 'Size')), + speed=int(self._get_memory_attr(memory, 'Speed')), + manufacturer=self._get_memory_attr(memory, + 'Manufacturer'), + model=self._get_memory_attr(memory, 'Model'), + status=PrimaryStatus[self._get_memory_attr( + memory, + 'PrimaryStatus')]) + + def _get_memory_attr(self, memory, attr_name): + return utils.get_wsman_resource_attr(memory, uris.DCIM_MemoryView, + attr_name) diff --git a/dracclient/resources/uris.py b/dracclient/resources/uris.py index 0c8949a..7ef1194 100644 --- a/dracclient/resources/uris.py +++ b/dracclient/resources/uris.py @@ -46,6 +46,9 @@ DCIM_CPUView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' DCIM_LifecycleJob = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_LifecycleJob') +DCIM_MemoryView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_MemoryView') + DCIM_PhysicalDiskView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_PhysicalDiskView') diff --git a/dracclient/tests/test_client.py b/dracclient/tests/test_client.py index 5d86c0d..347be2f 100644 --- a/dracclient/tests/test_client.py +++ b/dracclient/tests/test_client.py @@ -982,3 +982,30 @@ class ClientCPUTestCase(base.BaseTest): self.assertEqual( expected_cpu, self.drac_client.list_cpus()) + + +@requests_mock.Mocker() +class ClientMemoryestCase(base.BaseTest): + + def setUp(self): + super(ClientMemoryestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + def test_list_memory(self, mock_requests): + expected_memory = [inventory.Memory( + id='DIMM.Socket.A1', + size=16384, + speed=2133, + manufacturer='Samsung', + model='DDR4 DIMM', + status='OK', + )] + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.MemoryEnumerations[uris.DCIM_MemoryView]['ok']) + + self.assertEqual( + expected_memory, + self.drac_client.list_memory()) diff --git a/dracclient/tests/utils.py b/dracclient/tests/utils.py index f05322d..6b14081 100644 --- a/dracclient/tests/utils.py +++ b/dracclient/tests/utils.py @@ -133,6 +133,12 @@ LifecycleControllerEnumerations = { }, } +MemoryEnumerations = { + uris.DCIM_MemoryView: { + 'ok': load_wsman_xml('memory-enumeration-enum-ok') + }, +} + RAIDEnumerations = { uris.DCIM_ControllerView: { 'ok': load_wsman_xml('controller_view-enum-ok') diff --git a/dracclient/tests/wsman_mocks/memory-enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/memory-enumeration-enum-ok.xml new file mode 100644 index 0000000..e2319c1 --- /dev/null +++ b/dracclient/tests/wsman_mocks/memory-enumeration-enum-ok.xml @@ -0,0 +1,40 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:6a7e85cd-00a9-49a2-a781-d047063b9975 + uuid:09c85e7c-2fda-1fda-bf81-f148d4fe83b0 + + + + + + A + 1866 + DIMM A1 + DIMM.Socket.A1 + DIMM.Socket.A1 + 20160215025015.000000+000 + 20151112191452.000000+000 + Mon Sep 22 07:00:00 2014 UTC + Samsung + 26 + DDR4 DIMM + M393A2G40DB0-CPB + 1 + 2 + 39406867 + 16384 + 2133 + + + + + + +