Fixes caching of ilo instances to use admin credentials

Currently the IloClient object cached uses iLO host as the key.
This can be issue if the iLO credentials are changed. The cached
node will not use new credentials leading to failure in
communication with iLO.

Change-Id: Ie1ea10aae78c4dab307d8a31996322597046ecb1
Closes-Bug: 1852688
This commit is contained in:
Shivanand Tendulker 2019-11-15 00:49:29 -05:00 committed by Shivanand Tendulker
parent 36f90a22d5
commit 086b3485c2
2 changed files with 32 additions and 25 deletions

View File

@ -136,12 +136,15 @@ def cache_node(cache=True):
self.cls = cls
self._instances = collections.OrderedDict()
def _if_not_exists(self, address):
return (address not in self._instances)
def _if_not_exists(self, ilo_info):
return (ilo_info not in self._instances)
def _create_instance(self, *args, **kwargs):
address = args[0]
self._instances[address] = self.cls(*args, **kwargs)
admin = args[1]
admin_pass = args[2]
self._instances[(address, admin, admin_pass)] = (
self.cls(*args, **kwargs))
# Check for max_cache_size
if len(self._instances) > self.MAX_CACHE_SIZE:
LOG.debug("Node cache hit the maximum size of %d." % (
@ -152,20 +155,23 @@ def cache_node(cache=True):
if not args:
LOG.error("Error creating iLO object.")
address = args[0]
admin = args[1]
admin_pass = args[2]
if self._if_not_exists(address):
if self._if_not_exists((address, admin, admin_pass)):
LOG.debug("Creating iLO object for node %(address)s.",
{'address': address})
self._create_instance(*args, **kwargs)
else:
LOG.debug("Using existing object for node "
"%(address)s.", {'address': address})
return self._instances[address]
return self._instances[(address, admin, admin_pass)]
def _pop_oldest_node(self):
node_keys = list(self._instances)
node_key = next(iter(node_keys))
LOG.debug("Removed oldest node %s from cache" % (node_key))
LOG.debug("Removed oldest node {} from "
"cache".format(node_key))
rnode = self._instances.pop(node_key, None)
if rnode:
del rnode

View File

@ -55,9 +55,10 @@ class IloCacheNodeTestCase(testtools.TestCase):
class IloClientWrapperTestCase(testtools.TestCase):
class DummyClass(object):
def __init__(self, ip, name):
def __init__(self, ip, name, password):
self._ip = ip
self._name = name
self._password = password
original_cls, decorated_cls = get_cls_wrapper(DummyClass)
@ -65,28 +66,28 @@ class IloClientWrapperTestCase(testtools.TestCase):
@mock.patch.object(wrapper_cls, '_create_instance')
@mock.patch.object(wrapper_cls, '_if_not_exists')
def test___call___new(self, exists_mock, create_mock):
def test___call___already_created(self, exists_mock, create_mock):
exists_mock.return_value = True
try:
wrapper_obj = IloClientWrapperTestCase.wrapper_cls(
IloClientWrapperTestCase.original_cls)
wrapper_obj('a.b.c.d', 'abcd')
wrapper_obj('a.b.c.d', 'abcd', 'deaf')
except KeyError:
pass
exists_mock.assert_called_once_with('a.b.c.d')
create_mock.assert_called_once_with('a.b.c.d', 'abcd')
exists_mock.assert_called_once_with(('a.b.c.d', 'abcd', 'deaf'))
create_mock.assert_called_once_with('a.b.c.d', 'abcd', 'deaf')
@mock.patch.object(wrapper_cls, '_create_instance')
@mock.patch.object(wrapper_cls, '_if_not_exists')
def test___call___already_created(self, exists_mock, create_mock):
def test___call___new(self, exists_mock, create_mock):
exists_mock.return_value = False
try:
wrapper_obj = IloClientWrapperTestCase.wrapper_cls(
IloClientWrapperTestCase.original_cls)
wrapper_obj('a.b.c.d', 'abcd')
wrapper_obj('a.b.c.d', 'abcd', 'deaf')
except KeyError:
pass
exists_mock.assert_called_once_with('a.b.c.d')
exists_mock.assert_called_once_with(('a.b.c.d', 'abcd', 'deaf'))
create_mock.assert_not_called()
@mock.patch.object(original_cls, '__init__')
@ -96,8 +97,8 @@ class IloClientWrapperTestCase(testtools.TestCase):
wrapper_obj = IloClientWrapperTestCase.wrapper_cls(
IloClientWrapperTestCase.original_cls)
wrapper_obj.MAX_CACHE_SIZE = 2
wrapper_obj._create_instance('a.b.c.d', 'abcd')
init_mock.assert_called_once_with('a.b.c.d', 'abcd')
wrapper_obj._create_instance('a.b.c.d', 'abcd', 'defe')
init_mock.assert_called_once_with('a.b.c.d', 'abcd', 'defe')
pop_mock.assert_not_called()
@mock.patch.object(original_cls, '__init__')
@ -107,21 +108,21 @@ class IloClientWrapperTestCase(testtools.TestCase):
wrapper_obj = IloClientWrapperTestCase.wrapper_cls(
IloClientWrapperTestCase.original_cls)
wrapper_obj.MAX_CACHE_SIZE = 2
wrapper_obj._create_instance('a.b.c.d', 'abcd')
wrapper_obj._create_instance('e.f.g.h', 'efgh')
wrapper_obj._create_instance('i.j.k.l', 'ijkl')
wrapper_obj._create_instance('a.b.c.d', 'abcd', 'deaf')
wrapper_obj._create_instance('e.f.g.h', 'efgh', 'deaf')
wrapper_obj._create_instance('i.j.k.l', 'ijkl', 'deaf')
pop_mock.assert_called_once_with()
def test__pop_oldest_node(self):
wrapper_obj = IloClientWrapperTestCase.wrapper_cls(
IloClientWrapperTestCase.original_cls)
wrapper_obj.MAX_CACHE_SIZE = 2
wrapper_obj('a.b.c.d', 'abcd')
wrapper_obj('e.f.g.h', 'efgh')
wrapper_obj('i.j.k.l', 'ijkl')
self.assertIn('i.j.k.l', wrapper_obj._instances)
self.assertIn('e.f.g.h', wrapper_obj._instances)
self.assertNotIn('a.b.c.d', wrapper_obj._instances)
wrapper_obj('a.b.c.d', 'abcd', 'deaf')
wrapper_obj('e.f.g.h', 'efgh', 'deaf')
wrapper_obj('i.j.k.l', 'ijkl', 'deaf')
self.assertIn(('i.j.k.l', 'ijkl', 'deaf'), wrapper_obj._instances)
self.assertIn(('e.f.g.h', 'efgh', 'deaf'), wrapper_obj._instances)
self.assertNotIn(('a.b.c.d', 'ijkl', 'deaf'), wrapper_obj._instances)
class IloClientInitTestCase(testtools.TestCase):