eDeploy plugin to not overwrite node's capabilities
If a node already has some capabilities specified make sure the eDeploy pluging don't overwrite it when adding the node profile match. Change-Id: I0651d82d5bebd1f232ad46f9f8cd261908f21cfd
This commit is contained in:
parent
9d4006e186
commit
cea076b457
|
@ -101,11 +101,15 @@ class eDeployHook(base.ProcessingHook):
|
|||
"""Store the hardware data from what has been discovered."""
|
||||
|
||||
if 'hardware' in node_info:
|
||||
capabilities_dict = utils.capabilities_to_dict(
|
||||
node.properties.get('capabilities'))
|
||||
capabilities_dict['profile'] = node_info['hardware']['profile']
|
||||
|
||||
return [
|
||||
{'op': 'add',
|
||||
'path': '/extra/configdrive_metadata',
|
||||
'value': {'hardware': node_info['hardware']}},
|
||||
{'op': 'add',
|
||||
'path': '/properties/capabilities',
|
||||
'value': 'profile:%s' % node_info['hardware']['profile']}
|
||||
'value': utils.dict_to_capabilities(capabilities_dict)}
|
||||
], {}
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from hardware import state
|
||||
import mock
|
||||
|
||||
from ironic_discoverd import conf
|
||||
from ironic_discoverd.plugins import edeploy
|
||||
from ironic_discoverd.test import base as test_base
|
||||
from ironic_discoverd import utils
|
||||
|
||||
|
||||
|
@ -31,8 +31,10 @@ def fake_load(obj, cfg_dir):
|
|||
@mock.patch.object(state.State, '_load_specs',
|
||||
lambda o, n: [('network', '$iface', 'serial', '$mac'),
|
||||
('network', '$iface', 'ipv4', '$ipv4')])
|
||||
class TestEdeploy(unittest.TestCase):
|
||||
class TestEdeploy(test_base.NodeTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEdeploy, self).setUp()
|
||||
conf.init_conf()
|
||||
conf.CONF.add_section('edeploy')
|
||||
basedir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
@ -51,7 +53,7 @@ class TestEdeploy(unittest.TestCase):
|
|||
self.assertEqual('192.168.100.12', node_info['hardware']['ipv4'])
|
||||
self.assertEqual('99:99:99:99:99:99',
|
||||
node_info['interfaces']['eth0']['mac'])
|
||||
node_patches, _ = hook.before_update(None, None, node_info)
|
||||
node_patches, _ = hook.before_update(self.node, None, node_info)
|
||||
self.assertEqual('/extra/configdrive_metadata',
|
||||
node_patches[0]['path'])
|
||||
self.assertEqual('hw1',
|
||||
|
@ -61,6 +63,16 @@ class TestEdeploy(unittest.TestCase):
|
|||
self.assertEqual('profile:hw1',
|
||||
node_patches[1]['value'])
|
||||
|
||||
def test_hook_multiple_capabilities(self):
|
||||
hook = edeploy.eDeployHook()
|
||||
self.node.properties['capabilities'] = 'cat:meow,profile:robin'
|
||||
node_info = {'hardware': {'profile': 'batman'}}
|
||||
node_patches, _ = hook.before_update(self.node, None, node_info)
|
||||
self.assertIn('cat:meow', node_patches[1]['value'])
|
||||
self.assertIn('profile:batman', node_patches[1]['value'])
|
||||
# Assert the old profile is gone
|
||||
self.assertNotIn('profile:robin', node_patches[1]['value'])
|
||||
|
||||
def test_hook_no_data(self):
|
||||
hook = edeploy.eDeployHook()
|
||||
node_info = {}
|
||||
|
|
|
@ -63,3 +63,18 @@ class TestRetryOnConflict(unittest.TestCase):
|
|||
call, 1, 2, x=3)
|
||||
call.assert_called_with(1, 2, x=3)
|
||||
self.assertEqual(utils.RETRY_COUNT, call.call_count)
|
||||
|
||||
|
||||
class TestCapabilities(unittest.TestCase):
|
||||
|
||||
def test_capabilities_to_dict(self):
|
||||
capabilities = 'cat:meow,dog:wuff'
|
||||
expected_output = {'cat': 'meow', 'dog': 'wuff'}
|
||||
output = utils.capabilities_to_dict(capabilities)
|
||||
self.assertEqual(expected_output, output)
|
||||
|
||||
def test_dict_to_capabilities(self):
|
||||
capabilities_dict = {'cat': 'meow', 'dog': 'wuff'}
|
||||
output = utils.dict_to_capabilities(capabilities_dict)
|
||||
self.assertIn('cat:meow', output)
|
||||
self.assertIn('dog:wuff', output)
|
||||
|
|
|
@ -95,3 +95,16 @@ def retry_on_conflict(call, *args, **kwargs):
|
|||
eventlet.greenthread.sleep(RETRY_DELAY)
|
||||
|
||||
raise RuntimeError('unreachable code') # pragma: no cover
|
||||
|
||||
|
||||
def capabilities_to_dict(caps):
|
||||
"""Convert the Node's capabilities into a dictionary."""
|
||||
if not caps:
|
||||
return {}
|
||||
return dict([key.split(':', 1) for key in caps.split(',')])
|
||||
|
||||
|
||||
def dict_to_capabilities(caps_dict):
|
||||
"""Convert a dictionary into a string with the capabilities syntax."""
|
||||
return ','.join(["%s:%s" % (key, value)
|
||||
for key, value in caps_dict.items()])
|
||||
|
|
Loading…
Reference in New Issue