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. Resume swift-proxy services.
If the swift-proxy deployment is clustered using the hacluster charm, the If the swift-proxy deployment is clustered using the hacluster charm, the
corresponding hacluster unit on the node must be resumed as well. 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 re
import six import six
import traceback
import yaml import yaml
from charmhelpers.contrib.network import ip from charmhelpers.contrib.network import ip
@ -34,6 +35,8 @@ from charmhelpers.core import (
) )
from charmhelpers.core.hookenv import ( from charmhelpers.core.hookenv import (
action_fail,
action_set,
config, config,
log as juju_log, log as juju_log,
charm_dir, charm_dir,
@ -749,3 +752,47 @@ def git_yaml_value(projects_yaml, key):
return projects[key] return projects[key]
return None 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: | description: |
A comma-separated list of nagios servicegroups. A comma-separated list of nagios servicegroups.
If left empty, the nagios_context will be used as the servicegroup 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() update_nrpe_config()
# Determine whether or not we should do an upgrade. # 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) do_openstack_upgrade(CONFIGS)
update_rings(min_part_hours=config('min-hours')) 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)