Fix issue with crontab enablement

The token flush and token rotate crontabs are re-written when the
leader unit changes inline with Juju leadership management.

Align contexts used to generate crontabs with Juju leadership
status, rather than corosync/pacemaker.

Correct use of OpenStackCompareReleases to ensure that releases
between ocata and queens don't automatically enable fernet
token behaviour.

Change-Id: I6db8d006ceac7b61e69f547682c5a49d876cfec6
Closes-Bug: 1816807
This commit is contained in:
James Page 2019-02-21 14:58:58 +00:00
parent 2dca259156
commit 1a07a7e657
3 changed files with 23 additions and 21 deletions

View File

@ -1,9 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project> <?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property> <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/keystone/hooks</path> <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<path>/keystone/unit_tests</path>
</pydev_pathproperty> <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/keystone/hooks</path>
<path>/keystone/unit_tests</path>
<path>/${PROJECT_DIR_NAME}</path>
</pydev_pathproperty>
</pydev_project> </pydev_project>

View File

@ -18,10 +18,8 @@ import json
from charmhelpers.contrib.openstack import context from charmhelpers.contrib.openstack import context
from charmhelpers.contrib.hahelpers.cluster import ( from charmhelpers.contrib.hahelpers.cluster import (
DC_RESOURCE_NAME,
determine_apache_port, determine_apache_port,
determine_api_port, determine_api_port,
is_elected_leader,
https, https,
) )
@ -30,6 +28,7 @@ from charmhelpers.core.hookenv import (
config, config,
log, log,
leader_get, leader_get,
is_leader,
local_unit, local_unit,
related_units, related_units,
relation_ids, relation_ids,
@ -270,8 +269,7 @@ class TokenFlushContext(context.OSContextGenerator):
def __call__(self): def __call__(self):
ctxt = { ctxt = {
'token_flush': (not fernet_enabled() and 'token_flush': (not fernet_enabled() and is_leader())
is_elected_leader(DC_RESOURCE_NAME))
} }
return ctxt return ctxt
@ -281,8 +279,7 @@ class FernetCronContext(context.OSContextGenerator):
def __call__(self): def __call__(self):
token_expiration = int(config('token-expiration')) token_expiration = int(config('token-expiration'))
ctxt = { ctxt = {
'enabled': (fernet_enabled() and 'enabled': (fernet_enabled() and is_leader()),
is_elected_leader(DC_RESOURCE_NAME)),
'unit_name': local_unit(), 'unit_name': local_unit(),
'charm_dir': charm_dir(), 'charm_dir': charm_dir(),
'minute': ('*/5' if token_expiration > 300 else '*') 'minute': ('*/5' if token_expiration > 300 else '*')
@ -299,7 +296,7 @@ def fernet_enabled():
cmp_release = CompareOpenStackReleases(os_release('keystone')) cmp_release = CompareOpenStackReleases(os_release('keystone'))
if cmp_release < 'ocata': if cmp_release < 'ocata':
return False return False
elif 'ocata' >= cmp_release < 'rocky': elif cmp_release >= 'ocata' and cmp_release < 'rocky':
return config('token-provider') == 'fernet' return config('token-provider') == 'fernet'
else: else:
return True return True

View File

@ -164,17 +164,17 @@ class TestKeystoneContexts(CharmTestCase):
'log_file': '/var/log/keystone/keystone.log'}, 'log_file': '/var/log/keystone/keystone.log'},
ctxt()) ctxt())
@patch.object(context, 'is_elected_leader') @patch.object(context, 'is_leader')
@patch.object(context, 'fernet_enabled') @patch.object(context, 'fernet_enabled')
def test_token_flush_context( def test_token_flush_context(
self, mock_fernet_enabled, mock_is_elected_leader): self, mock_fernet_enabled, mock_is_leader):
ctxt = context.TokenFlushContext() ctxt = context.TokenFlushContext()
mock_fernet_enabled.return_value = False mock_fernet_enabled.return_value = False
mock_is_elected_leader.return_value = False mock_is_leader.return_value = False
self.assertEqual({'token_flush': False}, ctxt()) self.assertEqual({'token_flush': False}, ctxt())
mock_is_elected_leader.return_value = True mock_is_leader.return_value = True
self.assertEqual({'token_flush': True}, ctxt()) self.assertEqual({'token_flush': True}, ctxt())
mock_fernet_enabled.return_value = True mock_fernet_enabled.return_value = True
@ -182,10 +182,10 @@ class TestKeystoneContexts(CharmTestCase):
@patch.object(context, 'charm_dir') @patch.object(context, 'charm_dir')
@patch.object(context, 'local_unit') @patch.object(context, 'local_unit')
@patch.object(context, 'is_elected_leader') @patch.object(context, 'is_leader')
@patch.object(context, 'fernet_enabled') @patch.object(context, 'fernet_enabled')
def test_fernet_cron_context( def test_fernet_cron_context(
self, mock_fernet_enabled, mock_is_elected_leader, mock_local_unit, self, mock_fernet_enabled, mock_is_leader, mock_local_unit,
mock_charm_dir): mock_charm_dir):
ctxt = context.FernetCronContext() ctxt = context.FernetCronContext()
@ -200,10 +200,10 @@ class TestKeystoneContexts(CharmTestCase):
} }
mock_fernet_enabled.return_value = False mock_fernet_enabled.return_value = False
mock_is_elected_leader.return_value = False mock_is_leader.return_value = False
self.assertEqual(expected, ctxt()) self.assertEqual(expected, ctxt())
mock_is_elected_leader.return_value = True mock_is_leader.return_value = True
self.assertEqual(expected, ctxt()) self.assertEqual(expected, ctxt())
mock_fernet_enabled.return_value = True mock_fernet_enabled.return_value = True