Skip to content

Commit

Permalink
Add support for series upgrade (#60)
Browse files Browse the repository at this point in the history
* Add support for series upgrade

We can't actually pause the service because the series upgrade hooks run
on the subordinates before the principal so doing so could interfere
with the pod drain process. So instead, we just set a status to let the
Juju admin know that it's ok to proceed.

Part of https://bugs.launchpad.net/charm-flannel/+bug/186994

* Refactor to use layer:status to prevent statuses from being overwritten
  • Loading branch information
johnsca committed Apr 24, 2020
1 parent f79f180 commit 2161958
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 39 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.tox/
__pycache__/
*.pyc
1 change: 1 addition & 0 deletions layer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ includes:
- 'layer:basic'
- 'layer:debug'
- 'layer:nagios'
- 'layer:status'
repo: https://github.com/juju-solutions/charm-flannel.git
options:
basic:
Expand Down
31 changes: 19 additions & 12 deletions reactive/flannel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
from charms.templating.jinja2 import render
from charmhelpers.core.host import service_start, service_stop, service_restart
from charmhelpers.core.host import service_running, service
from charmhelpers.core.hookenv import log, status_set, resource_get
from charmhelpers.core.hookenv import log, resource_get
from charmhelpers.core.hookenv import config, application_version_set
from charmhelpers.core.hookenv import network_get
from charmhelpers.contrib.charmsupport import nrpe
from charms.reactive.helpers import data_changed

from charms.layer import status


ETCD_PATH = '/etc/ssl/flannel'
ETCD_KEY_PATH = os.path.join(ETCD_PATH, 'client-key.pem')
Expand All @@ -32,20 +34,20 @@ def install_flannel_binaries():
except Exception:
message = 'Error fetching the flannel resource.'
log(message)
status_set('blocked', message)
status.blocked(message)
return
if not archive:
message = 'Missing flannel resource.'
log(message)
status_set('blocked', message)
status.blocked(message)
return
filesize = os.stat(archive).st_size
if filesize < 1000000:
message = 'Incomplete flannel resource'
log(message)
status_set('blocked', message)
status.blocked(message)
return
status_set('maintenance', 'Unpacking flannel resource.')
status.maintenance('Unpacking flannel resource.')
charm_dir = os.getenv('CHARM_DIR')
unpack_path = os.path.join(charm_dir, 'files', 'flannel')
os.makedirs(unpack_path, exist_ok=True)
Expand Down Expand Up @@ -121,7 +123,7 @@ def get_bind_address_interface():
@when_not('flannel.service.installed')
def install_flannel_service(etcd):
''' Install the flannel service. '''
status_set('maintenance', 'Installing flannel service.')
status.maintenance('Installing flannel service.')
# keep track of our etcd conn string and cert info so we can detect when it
# changes later
data_changed('flannel_etcd_connections', etcd.get_connection_string())
Expand Down Expand Up @@ -158,12 +160,12 @@ def etcd_changed(etcd):
@when_not('flannel.network.configured')
def invoke_configure_network(etcd):
''' invoke network configuration and adjust states '''
status_set('maintenance', 'Negotiating flannel network subnet.')
status.maintenance('Negotiating flannel network subnet.')
if configure_network(etcd):
set_state('flannel.network.configured')
remove_state('flannel.service.started')
else:
status_set('waiting', 'Waiting on etcd.')
status.waiting('Waiting on etcd.')


@retry(times=3, delay_secs=20)
Expand Down Expand Up @@ -206,7 +208,7 @@ def reconfigure_network():
@when_not('flannel.service.started')
def start_flannel_service():
''' Start the flannel service. '''
status_set('maintenance', 'Starting flannel service.')
status.maintenance('Starting flannel service.')
if service_running('flannel'):
service_restart('flannel')
else:
Expand Down Expand Up @@ -263,15 +265,15 @@ def update_nrpe_config(unused=None):
def ready():
''' Indicate that flannel is active. '''
try:
status_set('active', 'Flannel subnet ' + get_flannel_subnet())
status.active('Flannel subnet ' + get_flannel_subnet())
except FlannelSubnetNotFound:
status_set('waiting', 'Waiting for Flannel')
status.waiting('Waiting for Flannel')


@when_not('etcd.connected')
def halt_execution():
''' send a clear message to the user that we are waiting on etcd '''
status_set('blocked', 'Waiting for etcd relation.')
status.blocked('Waiting for etcd relation.')


@hook('upgrade-charm')
Expand All @@ -291,6 +293,11 @@ def reset_states_and_redeploy():
log(str(e))


@hook('pre-series-upgrade')
def pre_series_upgrade():
status.blocked('Series upgrade in progress')


@hook('stop')
def cleanup_deployment():
''' Terminate services, and remove the deployed bins '''
Expand Down
28 changes: 2 additions & 26 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,4 @@
import sys
from unittest.mock import MagicMock
import charms.unit_test


def identity(x):
return x


charmhelpers = MagicMock()
sys.modules['charmhelpers'] = charmhelpers
sys.modules['charmhelpers.core'] = charmhelpers.core
sys.modules['charmhelpers.core.hookenv'] = charmhelpers.core.hookenv
sys.modules['charmhelpers.core.host'] = charmhelpers.core.host
sys.modules['charmhelpers.contrib'] = charmhelpers.contrib
sys.modules['charmhelpers.contrib.charmsupport'] = \
charmhelpers.contrib.charmsupport

reactive = MagicMock()
sys.modules['charms.reactive'] = reactive
sys.modules['charms.reactive.helpers'] = reactive.helpers
reactive.when.return_value = identity
reactive.when_any.return_value = identity
reactive.when_not.return_value = identity
reactive.hook.return_value = identity

templating = MagicMock()
sys.modules['charms.templating'] = templating
sys.modules['charms.templating.jinja2'] = templating.jinja2
charms.unit_test.patch_reactive()
6 changes: 6 additions & 0 deletions tests/test_flannel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ def test_set_available():
cni_conf_file='10-flannel.conflist'
)
set_state.assert_called_once_with('flannel.cni.available')


def test_series_upgrade():
assert flannel.status.blocked.call_count == 0
flannel.pre_series_upgrade()
assert flannel.status.blocked.call_count == 1
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ deps =
pytest
flake8
ipdb
git+https://github.com/juju-solutions/charms.unit_test/#egg=charms.unit_test
commands = pytest --tb native -s {posargs}

[testenv:lint]
envdir = {toxworkdir}/py3
commands = flake8 {toxinidir}
commands = flake8 {toxinidir}/lib {toxinidir}/reactive {toxinidir}/tests

0 comments on commit 2161958

Please sign in to comment.