Remove profile matching from eDeploy plugin
The matching functionality will be moved to a seperate utility located at github/rdo-management/ahc-tools. Change-Id: I3b82fb89056c33f3671983a0ca7efe8682b7cc1a Closes-Bug: 1449568
This commit is contained in:
parent
48471bce6d
commit
eaad7e09b9
|
@ -19,143 +19,25 @@ details on how to use it. Note that this plugin requires a special ramdisk.
|
|||
|
||||
import logging
|
||||
|
||||
from hardware import matcher
|
||||
from hardware import state
|
||||
from oslo_config import cfg
|
||||
|
||||
from ironic_discoverd.common.i18n import _, _LW
|
||||
from ironic_discoverd.common.i18n import _LW
|
||||
from ironic_discoverd.plugins import base
|
||||
from ironic_discoverd import utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
LOG = logging.getLogger('ironic_discoverd.plugins.edeploy')
|
||||
|
||||
|
||||
EDEPLOY_OPTS = [
|
||||
cfg.StrOpt('lockname',
|
||||
default='/var/lock/discoverd.lock'),
|
||||
cfg.StrOpt('configdir',
|
||||
default='/etc/edeploy'),
|
||||
]
|
||||
CONF.register_opts(EDEPLOY_OPTS, group='edeploy')
|
||||
|
||||
|
||||
def list_opts():
|
||||
return [
|
||||
('edeploy', EDEPLOY_OPTS)
|
||||
]
|
||||
|
||||
|
||||
class eDeployHook(base.ProcessingHook):
|
||||
"""Interact with eDeploy ramdisk for discovery data processing hooks."""
|
||||
|
||||
def before_processing(self, node_info):
|
||||
"""Hook to run before data processing.
|
||||
|
||||
Finds matching profile in the database.
|
||||
|
||||
:param node_info: raw information sent by the ramdisk, may be modified
|
||||
by the hook.
|
||||
:raises: Error if node_info does not contain extended information
|
||||
:returns: nothing.
|
||||
"""
|
||||
|
||||
if 'data' not in node_info:
|
||||
raise utils.Error(
|
||||
_('edeploy plugin: no "data" key in the received JSON'))
|
||||
|
||||
LOG.debug('before_processing: %s', node_info['data'])
|
||||
|
||||
hw_items = []
|
||||
for info in node_info['data']:
|
||||
hw_items.append(tuple(info))
|
||||
|
||||
hw_copy = list(hw_items)
|
||||
self._process_data_for_discoverd(hw_copy, node_info)
|
||||
sobj = None
|
||||
|
||||
try:
|
||||
sobj = state.State(CONF.edeploy.lockname)
|
||||
sobj.load(CONF.edeploy.configdir)
|
||||
prof, var = sobj.find_match(hw_items)
|
||||
var['profile'] = prof
|
||||
|
||||
if 'logical_disks' in var:
|
||||
node_info['target_raid_configuration'] = {
|
||||
'logical_disks': var.pop('logical_disks')}
|
||||
|
||||
if 'bios_settings' in var:
|
||||
node_info['bios_settings'] = var.pop('bios_settings')
|
||||
|
||||
node_info['hardware'] = var
|
||||
node_info['edeploy_facts'] = hw_items
|
||||
|
||||
except Exception as excpt:
|
||||
LOG.warning(_LW(
|
||||
'Unable to find a matching hardware profile: %s'), excpt)
|
||||
finally:
|
||||
if sobj:
|
||||
sobj.save()
|
||||
sobj.unlock()
|
||||
del node_info['data']
|
||||
|
||||
def _process_data_for_discoverd(self, hw_items, node_info):
|
||||
matcher.match_spec(('memory', 'total', 'size', '$memory_mb'),
|
||||
hw_items, node_info)
|
||||
matcher.match_spec(('cpu', 'logical', 'number', '$cpus'),
|
||||
hw_items, node_info)
|
||||
matcher.match_spec(('system', 'kernel', 'arch', '$cpu_arch'),
|
||||
hw_items, node_info)
|
||||
matcher.match_spec(('disk', '$disk', 'size', '$local_gb'),
|
||||
hw_items, node_info)
|
||||
matcher.match_spec(('ipmi', 'lan', 'ip-address', '$ipmi_address'),
|
||||
hw_items, node_info)
|
||||
node_info['interfaces'] = {}
|
||||
while True:
|
||||
info = {'ipv4': 'none'}
|
||||
if not matcher.match_spec(('network', '$iface', 'serial', '$mac'),
|
||||
hw_items, info):
|
||||
break
|
||||
matcher.match_spec(('network', info['iface'], 'ipv4', '$ipv4'),
|
||||
hw_items, info)
|
||||
node_info['interfaces'][info['iface']] = {'mac': info['mac'],
|
||||
'ip': info['ipv4']}
|
||||
|
||||
def before_update(self, node, ports, node_info):
|
||||
"""Store the hardware data from what has been discovered."""
|
||||
|
||||
patches = []
|
||||
|
||||
if 'hardware' in node_info:
|
||||
capabilities_dict = utils.capabilities_to_dict(
|
||||
node.properties.get('capabilities'))
|
||||
capabilities_dict['profile'] = node_info['hardware']['profile']
|
||||
|
||||
patches.append({'op': 'add',
|
||||
'path': '/extra/configdrive_metadata',
|
||||
'value': {'hardware': node_info['hardware']}})
|
||||
patches.append(
|
||||
{'op': 'add',
|
||||
'path': '/properties/capabilities',
|
||||
'value': utils.dict_to_capabilities(capabilities_dict)})
|
||||
|
||||
patches.append(
|
||||
{'op': 'add',
|
||||
if 'data' not in node_info:
|
||||
LOG.warning(_LW('No eDeploy data was received from the ramdisk'))
|
||||
return [], {}
|
||||
# (trown) it is useful for the edeploy report tooling to have the node
|
||||
# uuid stored with the other edeploy_facts
|
||||
node_info['data'].append(['system', 'product',
|
||||
'ironic_uuid', node.uuid])
|
||||
return [{'op': 'add',
|
||||
'path': '/extra/edeploy_facts',
|
||||
'value': node_info['edeploy_facts']})
|
||||
|
||||
if 'target_raid_configuration' in node_info:
|
||||
patches.append(
|
||||
{'op': 'add',
|
||||
'path': '/extra/target_raid_configuration',
|
||||
'value': node_info['target_raid_configuration']})
|
||||
|
||||
if 'bios_settings' in node_info:
|
||||
patches.append(
|
||||
{'op': 'add',
|
||||
'path': '/extra/bios_settings',
|
||||
'value': node_info['bios_settings']})
|
||||
|
||||
return patches, {}
|
||||
'value': node_info['data']}], {}
|
||||
|
|
|
@ -11,131 +11,36 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
|
||||
from hardware import cmdb
|
||||
from hardware import state
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from ironic_discoverd.plugins import edeploy
|
||||
from ironic_discoverd.test import base as test_base
|
||||
from ironic_discoverd import utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def fake_load(obj, cfg_dir):
|
||||
obj._cfg_dir = cfg_dir
|
||||
obj._data = [('hw1', '*'), ]
|
||||
|
||||
|
||||
@mock.patch.object(state.State, 'load', fake_load)
|
||||
@mock.patch.object(state.State, '_load_specs',
|
||||
lambda o, n: [('network', '$iface', 'serial', '$mac'),
|
||||
('network', '$iface', 'ipv4', '$ipv4')])
|
||||
class TestEdeploy(test_base.NodeTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestEdeploy, self).setUp()
|
||||
basedir = os.path.dirname(os.path.abspath(__file__))
|
||||
CONF.set_override('configdir',
|
||||
os.path.join(basedir, 'edeploy_conf'),
|
||||
'edeploy')
|
||||
self.hook = edeploy.eDeployHook()
|
||||
|
||||
def test_hook(self):
|
||||
hook = edeploy.eDeployHook()
|
||||
node_info = {'data': [
|
||||
['network', 'eth0', 'serial', '99:99:99:99:99:99'],
|
||||
['network', 'eth0', 'ipv4', '192.168.100.12'],
|
||||
]}
|
||||
hook.before_processing(node_info)
|
||||
self.assertEqual('hw1', node_info['hardware']['profile'])
|
||||
self.assertEqual('eth0', node_info['hardware']['iface'])
|
||||
self.assertEqual('192.168.100.12', node_info['hardware']['ipv4'])
|
||||
self.assertEqual('99:99:99:99:99:99',
|
||||
node_info['interfaces']['eth0']['mac'])
|
||||
self.assertEqual([('network', 'eth0', 'serial', '99:99:99:99:99:99'),
|
||||
('network', 'eth0', 'ipv4', '192.168.100.12')],
|
||||
node_info['edeploy_facts'])
|
||||
node_patches, _ = hook.before_update(self.node, None, node_info)
|
||||
self.assertEqual('/extra/configdrive_metadata',
|
||||
node_patches[0]['path'])
|
||||
self.assertEqual('hw1',
|
||||
node_patches[0]['value']['hardware']['profile'])
|
||||
self.assertEqual('/properties/capabilities',
|
||||
node_patches[1]['path'])
|
||||
self.assertEqual('profile:hw1',
|
||||
node_patches[1]['value'])
|
||||
def test_data_recieved(self):
|
||||
node_info = {'data': [['memory', 'total', 'size', '4294967296'],
|
||||
['cpu', 'physical', 'number', '1'],
|
||||
['cpu', 'logical', 'number', '1']]}
|
||||
self.hook.before_processing(node_info)
|
||||
node_patches, _ = self.hook.before_update(self.node, None, node_info)
|
||||
|
||||
expected_value = [['memory', 'total', 'size', '4294967296'],
|
||||
['cpu', 'physical', 'number', '1'],
|
||||
['cpu', 'logical', 'number', '1'],
|
||||
['system', 'product', 'ironic_uuid', self.node.uuid]]
|
||||
self.assertEqual('add',
|
||||
node_patches[0]['op'])
|
||||
self.assertEqual('/extra/edeploy_facts',
|
||||
node_patches[2]['path'])
|
||||
self.assertEqual(('network', 'eth0', 'serial', '99:99:99:99:99:99'),
|
||||
node_patches[2]['value'][0])
|
||||
node_patches[0]['path'])
|
||||
self.assertEqual(expected_value,
|
||||
node_patches[0]['value'])
|
||||
|
||||
def test_hook_multiple_capabilities(self):
|
||||
hook = edeploy.eDeployHook()
|
||||
self.node.properties['capabilities'] = 'cat:meow,profile:robin'
|
||||
node_info = {'hardware': {'profile': 'batman'}, 'edeploy_facts': []}
|
||||
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 = {}
|
||||
self.assertRaises(utils.Error, hook.before_processing, node_info)
|
||||
|
||||
@mock.patch.object(edeploy, 'LOG')
|
||||
def test_hook_no_profile(self, mock_log):
|
||||
hook = edeploy.eDeployHook()
|
||||
node_info = {'data': []}
|
||||
hook.before_processing(node_info)
|
||||
self.assertTrue(mock_log.warning.called)
|
||||
|
||||
@mock.patch.object(cmdb, 'load_cmdb')
|
||||
def test_raid_configuration_passed(self, mock_load_cmdb):
|
||||
hook = edeploy.eDeployHook()
|
||||
mock_load_cmdb.return_value = [
|
||||
{'logical_disks': (
|
||||
{'disk_type': 'hdd',
|
||||
'interface_type': 'sas',
|
||||
'is_root_volume': 'true',
|
||||
'raid_level': '1+0',
|
||||
'size_gb': 50,
|
||||
'volume_name': 'root_volume'},
|
||||
{'disk_type': 'hdd',
|
||||
'interface_type': 'sas',
|
||||
'number_of_physical_disks': 3,
|
||||
'raid_level': '5',
|
||||
'size_gb': 100,
|
||||
'volume_name': 'data_volume'})}]
|
||||
node_info = {'data': [
|
||||
['network', 'eth0', 'serial', '99:99:99:99:99:99'],
|
||||
['network', 'eth0', 'ipv4', '192.168.100.12'],
|
||||
]}
|
||||
|
||||
hook.before_processing(node_info)
|
||||
self.assertIn('target_raid_configuration', node_info)
|
||||
|
||||
node_patches, _ = hook.before_update(self.node, None, node_info)
|
||||
self.assertEqual('/extra/target_raid_configuration',
|
||||
node_patches[3]['path'])
|
||||
|
||||
@mock.patch.object(cmdb, 'load_cmdb')
|
||||
def test_bios_configuration_passed(self, mock_load_cmdb):
|
||||
hook = edeploy.eDeployHook()
|
||||
mock_load_cmdb.return_value = [
|
||||
{'bios_settings': {'ProcVirtualization': 'Disabled'}}]
|
||||
node_info = {'data': [
|
||||
['network', 'eth0', 'serial', '99:99:99:99:99:99'],
|
||||
['network', 'eth0', 'ipv4', '192.168.100.12'],
|
||||
]}
|
||||
|
||||
hook.before_processing(node_info)
|
||||
self.assertIn('bios_settings', node_info)
|
||||
|
||||
node_patches, _ = hook.before_update(self.node, None, node_info)
|
||||
self.assertEqual('/extra/bios_settings',
|
||||
node_patches[3]['path'])
|
||||
def test_no_data_recieved(self):
|
||||
node_info = {'cats': 'meow'}
|
||||
self.hook.before_processing(node_info)
|
||||
node_patches, _ = self.hook.before_update(self.node, None, node_info)
|
||||
self.assertEqual(0, len(node_patches))
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
hardware>=0.7,<0.99
|
Loading…
Reference in New Issue