Action managed upgrade

This commit is contained in:
David Ames 2015-09-23 09:28:19 -07:00
parent d61fba73d1
commit 58ecdfb9ea
7 changed files with 173 additions and 1 deletions

View File

@ -9,3 +9,7 @@ resume:
Resume swift-proxy services.
If the swift-proxy deployment is clustered using the hacluster charm, the
corresponding hacluster unit on the node must be resumed as well.
openstack-upgrade:
description: |
Perform openstack upgrades. Config option action-managed-upgrade must be
set to True.

1
actions/openstack-upgrade Symbolic link
View File

@ -0,0 +1 @@
openstack_upgrade.py

34
actions/openstack_upgrade.py Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/python
import sys
sys.path.append('hooks/')
from charmhelpers.contrib.openstack.utils import (
do_action_openstack_upgrade,
)
from swift_hooks import (
config_changed,
CONFIGS,
)
from lib.swift_utils import (
do_openstack_upgrade,
)
def openstack_upgrade():
"""Upgrade packages to config-set Openstack version.
If the charm was installed from source we cannot upgrade it.
For backwards compatibility a config flag must be set for this
code to run, otherwise a full service level upgrade will fire
on config-changed."""
if (do_action_openstack_upgrade('python-swift',
do_openstack_upgrade,
CONFIGS)):
config_changed()
if __name__ == '__main__':
openstack_upgrade()

View File

@ -25,6 +25,7 @@ import sys
import re
import six
import traceback
import yaml
from charmhelpers.contrib.network import ip
@ -34,6 +35,8 @@ from charmhelpers.core import (
)
from charmhelpers.core.hookenv import (
action_fail,
action_set,
config,
log as juju_log,
charm_dir,
@ -749,3 +752,47 @@ def git_yaml_value(projects_yaml, key):
return projects[key]
return None
def do_action_openstack_upgrade(package, upgrade_callback, configs):
"""Perform action-managed OpenStack upgrade.
Upgrades packages to the configured openstack-origin version and sets
the corresponding action status as a result.
If the charm was installed from source we cannot upgrade it.
For backwards compatibility a config flag (action-managed-upgrade) must
be set for this code to run, otherwise a full service level upgrade will
fire on config-changed.
@param package: package name for determining if upgrade available
@param upgrade_callback: function callback to charm's upgrade function
@param configs: templating object derived from OSConfigRenderer class
@return: True if upgrade successful; False if upgrade failed or skipped
"""
ret = False
if git_install_requested():
action_set({'outcome': 'installed from source, skipped upgrade.'})
else:
if openstack_upgrade_available(package):
if config('action-managed-upgrade'):
juju_log('Upgrading OpenStack release')
try:
upgrade_callback(configs=configs)
action_set({'outcome': 'success, upgrade completed.'})
ret = True
except:
action_set({'outcome': 'upgrade failed, see traceback.'})
action_set({'traceback': traceback.format_exc()})
action_fail('do_openstack_upgrade resulted in an '
'unexpected error')
else:
action_set({'outcome': 'action-managed-upgrade config is '
'False, skipped upgrade.'})
else:
action_set({'outcome': 'no upgrade available.'})
return ret

View File

@ -255,3 +255,13 @@ options:
description: |
A comma-separated list of nagios servicegroups.
If left empty, the nagios_context will be used as the servicegroup
action-managed-upgrade:
type: boolean
default: False
description: |
If True enables openstack upgrades for this charm via juju actions.
You will still need to set openstack-origin to the new repository but
instead of an upgrade running automatically across all units, it will
wait for you to execute the openstack-upgrade action for this charm on
each unit. If False it will revert to existing behavior of upgrading
all units on config change.

View File

@ -132,7 +132,8 @@ def config_changed():
update_nrpe_config()
# Determine whether or not we should do an upgrade.
if openstack.openstack_upgrade_available('python-swift'):
if not config('action-managed-upgrade') and \
openstack.openstack_upgrade_available('python-swift'):
do_openstack_upgrade(CONFIGS)
update_rings(min_part_hours=config('min-hours'))

View File

@ -0,0 +1,75 @@
from mock import patch
import os
import unittest
os.environ['JUJU_UNIT_NAME'] = 'swift-proxy'
with patch('actions.charmhelpers.core.hookenv.config') as config:
config.return_value = 'swift'
import actions.openstack_upgrade as openstack_upgrade
TO_PATCH = [
'config_changed',
'do_openstack_upgrade',
]
class CharmTestCase(unittest.TestCase):
def setUp(self, obj, patches):
super(CharmTestCase, self).setUp()
self.patches = patches
self.obj = obj
self.patch_all()
def patch(self, method):
_m = patch.object(self.obj, method)
mocked = _m.start()
self.addCleanup(_m.stop)
return mocked
def patch_all(self):
for method in self.patches:
setattr(self, method, self.patch(method))
class TestSwiftUpgradeActions(CharmTestCase):
def setUp(self):
super(TestSwiftUpgradeActions, self).setUp(openstack_upgrade,
TO_PATCH)
@patch('actions.charmhelpers.contrib.openstack.utils.config')
@patch('actions.charmhelpers.contrib.openstack.utils.action_set')
@patch('actions.charmhelpers.contrib.openstack.utils.'
'git_install_requested')
@patch('actions.charmhelpers.contrib.openstack.utils.'
'openstack_upgrade_available')
def test_openstack_upgrade_true(self, upgrade_avail, git_requested,
action_set, config):
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = True
openstack_upgrade.openstack_upgrade()
self.assertTrue(self.do_openstack_upgrade.called)
self.assertTrue(self.config_changed.called)
@patch('actions.charmhelpers.contrib.openstack.utils.config')
@patch('actions.charmhelpers.contrib.openstack.utils.action_set')
@patch('actions.charmhelpers.contrib.openstack.utils.'
'git_install_requested')
@patch('actions.charmhelpers.contrib.openstack.utils.'
'openstack_upgrade_available')
def test_openstack_upgrade_false(self, upgrade_avail, git_requested,
action_set, config):
git_requested.return_value = False
upgrade_avail.return_value = True
config.return_value = False
openstack_upgrade.openstack_upgrade()
self.assertFalse(self.do_openstack_upgrade.called)
self.assertFalse(self.config_changed.called)