Additional condition is comparison when doing config check out of date

This will fix below scenario:
Controller-0 is installed and some configs were applied. Config
f5d83753-c485-4221-b4aa-e986f5421d6d is the target config and requests
boot.
After controller-0 is unlocked and reboot.another request with uuid
29c89b7e-51fe-40cb-8700-e22c83ed5fa9 is coming,then the config_target is
set to a9c89b7e-51fe-40cb-8700-e22c83ed5fa9;
Once 29c89b7e-51fe-40cb-8700-e22c83ed5fa9 was applied,the config should
be cleared, but because 29c89b7e-51fe-40cb-8700-e22c83ed5fa9 is not same
as a9c89b7e-51fe-40cb-8700-e22c83ed5fa9,the alarm can not be cleared.

In this fix, tracking list for reboot config and clear it once config is
applied. the out of date config will be clear if reboot config tracking
is empty and config_applied w/ reboot config flag is equal config_target

Closes-Bug: 1851874
Change-Id: Iabeab338bc3fb4615cefcff9e4ae9402e4216321
Signed-off-by: Sun Austin <austin.sun@intel.com>
This commit is contained in:
Sun Austin 2019-11-21 21:23:00 +08:00
parent 89e2975eb8
commit 238b196d3a
2 changed files with 108 additions and 6 deletions

View File

@ -192,6 +192,9 @@ class ConductorManager(service.PeriodicService):
# Timeouts for adding & removing operations
self._pv_op_timeouts = {}
self._stor_bck_op_timeouts = {}
# struct {'host_uuid':[config_uuid_0,config_uuid_1]}
# this will track the config w/ reboot request to apply
self._host_reboot_config_uuid = {}
def start(self):
self._start()
@ -7892,9 +7895,38 @@ class ConductorManager(service.PeriodicService):
# We avoid re-raising this as it may brake critical operations after this one
return constants.CINDER_RESIZE_FAILURE
def _remove_config_from_reboot_config_list(self, ihost_uuid, config_uuid):
LOG.info("_remove_config_from_reboot_config_list host: %s,config_uuid: %s" %
(ihost_uuid, config_uuid))
if ihost_uuid in self._host_reboot_config_uuid:
try:
self._host_reboot_config_uuid[ihost_uuid].remove(config_uuid)
except ValueError:
LOG.info("_remove_config_from_reboot_config_list fail"
" host:%s", ihost_uuid)
pass
def _clear_config_from_reboot_config_list(self, ihost_uuid):
LOG.info("_clear_config_from_reboot_config_list host:%s", ihost_uuid)
if ihost_uuid in self._host_reboot_config_uuid:
try:
del self._host_reboot_config_uuid[ihost_uuid][:]
except ValueError:
LOG.info("_clear_config_from_reboot_config_list fail"
" host: %s", ihost_uuid)
pass
def _config_out_of_date(self, ihost_obj):
target = ihost_obj.config_target
applied = ihost_obj.config_applied
applied_reboot = None
if applied is not None:
try:
applied_reboot = self._config_set_reboot_required(applied)
except ValueError:
# for worker node, the applied might be 'install'
applied_reboot = applied
pass
hostname = ihost_obj.hostname
if not hostname:
@ -7905,6 +7937,7 @@ class ConductorManager(service.PeriodicService):
(hostname, applied))
return False
elif target == applied:
self._clear_config_from_reboot_config_list(ihost_obj.uuid)
if ihost_obj.personality == constants.CONTROLLER:
controller_fs_list = self.dbapi.controller_fs_get_list()
@ -7921,6 +7954,13 @@ class ConductorManager(service.PeriodicService):
LOG.info("%s: iconfig up to date: target %s, applied %s " %
(hostname, target, applied))
return False
elif target == applied_reboot:
if ihost_obj.uuid in self._host_reboot_config_uuid:
if len(self._host_reboot_config_uuid[ihost_obj.uuid]) == 0:
return False
return True
else:
return False
else:
LOG.warn("%s: iconfig out of date: target %s, applied %s " %
(hostname, target, applied))
@ -8112,6 +8152,8 @@ class ConductorManager(service.PeriodicService):
@cutils.synchronized(lock_name, external=False)
def _sync_update_host_config_applied(self,
context, ihost_obj, config_uuid):
self._remove_config_from_reboot_config_list(ihost_obj.uuid,
config_uuid)
if ihost_obj.config_applied != config_uuid:
ihost_obj.config_applied = config_uuid
ihost_obj.save(context)
@ -8159,6 +8201,12 @@ class ConductorManager(service.PeriodicService):
for host in hosts:
if host.personality and host.personality in personalities:
if reboot:
if host.uuid in self._host_reboot_config_uuid:
self._host_reboot_config_uuid[host.uuid].append(config_uuid)
else:
self._host_reboot_config_uuid[host.uuid] = []
self._host_reboot_config_uuid[host.uuid].append(config_uuid)
self._update_host_config_target(context, host, config_uuid)
LOG.info("_config_update_hosts config_uuid=%s" % config_uuid)

View File

@ -23,11 +23,13 @@
"""Test class for Sysinv ManagerService."""
import mock
import os.path
import uuid
from sysinv.common import constants
from sysinv.common import exception
from sysinv.common import kubernetes
from sysinv.common import utils as cutils
from sysinv.conductor import manager
from sysinv.db import api as dbapi
from sysinv.openstack.common import context
@ -97,16 +99,14 @@ class ManagerTestCase(base.DbTestCase):
self.upgrade_downgrade_kube_components_patcher.start()
self.addCleanup(self.mock_upgrade_downgrade_kube_components.stop)
self.do_update_alarm_status_patcher = mock.patch.object(
manager.ConductorManager, '_do_update_alarm_status')
self.mock_do_update_alarm_status = \
self.do_update_alarm_status_patcher.start()
self.addCleanup(self.mock_do_update_alarm_status.stop)
self.service.fm_api = mock.Mock()
self.service.fm_api.set_fault.side_effect = self._raise_alarm
self.service.fm_api.clear_fault.side_effect = self._clear_alarm
self.fail_config_apply_runtime_manifest = False
def mock_config_apply_runtime_manifest(obj, context, config_uuid,
config_dict):
config_dict, force=False):
if not self.fail_config_apply_runtime_manifest:
# Pretend the config was applied
if 'host_uuids' in config_dict:
@ -184,6 +184,16 @@ class ManagerTestCase(base.DbTestCase):
self.mocked_get_kube_versions.start()
self.addCleanup(self.mocked_get_kube_versions.stop)
self.service._puppet = mock.Mock()
self.service._allocate_addresses_for_host = mock.Mock()
self.service._update_pxe_config = mock.Mock()
self.service._ceph_mon_create = mock.Mock()
self.alarm_raised = False
def tearDown(self):
super(ManagerTestCase, self).tearDown()
self.upgrade_downgrade_kube_components_patcher.stop()
def _create_test_ihost(self, **kwargs):
# ensure the system ID for proper association
kwargs['forisystemid'] = self.system['id']
@ -1012,3 +1022,47 @@ class ManagerTestCase(base.DbTestCase):
# Verify that the host upgrade status was cleared
updated_host_upgrade = self.dbapi.kube_host_upgrade_get(1)
self.assertIsNotNone(updated_host_upgrade.status)
def test_configure_out_of_date(self):
config_applied = self.service._config_set_reboot_required(uuid.uuid4())
config_target = self.service._config_set_reboot_required(uuid.uuid4())
ihost = self._create_test_ihost(config_applied=config_applied,
config_target=config_target)
os.path.isfile = mock.Mock(return_value=True)
cutils.is_aio_system = mock.Mock(return_value=True)
ihost['mgmt_mac'] = '00:11:22:33:44:55'
ihost['mgmt_ip'] = '1.2.3.42'
ihost['hostname'] = 'controller-0'
ihost['invprovision'] = 'provisioned'
ihost['personality'] = 'controller'
ihost['administrative'] = 'unlocked'
ihost['operational'] = 'available'
ihost['availability'] = 'online'
ihost['serialid'] = '1234567890abc'
ihost['boot_device'] = 'sda'
ihost['rootfs_device'] = 'sda'
ihost['install_output'] = 'text'
ihost['console'] = 'ttyS0,115200'
self.service.configure_ihost(self.context, ihost)
res = self.dbapi.ihost_get(ihost['uuid'])
imsg_dict = {'config_applied': res['config_target']}
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
self.assertEqual(self.alarm_raised, False)
personalities = [constants.CONTROLLER]
self.service._config_update_hosts(self.context, personalities, reboot=True)
res = self.dbapi.ihost_get(ihost['uuid'])
personalities = [constants.CONTROLLER]
self.service._config_update_hosts(self.context, personalities, reboot=False)
res = self.dbapi.ihost_get(ihost['uuid'])
config_uuid = self.service._config_clear_reboot_required(res['config_target'])
imsg_dict = {'config_applied': config_uuid}
self.service.iconfig_update_by_ihost(self.context, ihost['uuid'], imsg_dict)
self.assertEqual(self.alarm_raised, True)
def _raise_alarm(self, fault):
self.alarm_raised = True
def _clear_alarm(self, fm_id, fm_instance):
self.alarm_raised = False