Rollback cluster/bay on update failure
Rollback mechanism was added in Magnum in patch https://review.openstack.org/343478 but currently there is no support on the client side. This patch add rollback support for Magnum cluster/bay, user can enable rollback on cluster update failure by specifying option '--rollback' when executing 'magnum cluster-update', for example: magnum cluster-update XXX replace node_count=5 --rollback The code is based on outdated patch https://review.openstack.org/347586 and improves it: * added rollback support for clusters * added API version check in CLI (should be >= 1.3) * added several unit tests Change-Id: Iaae51e084e8ffd69be38512eec8c4c54b158b55e Co-authored-by: Wenzhi Yu <wenzhi_yu@163.com> Implements: blueprint bay-rollback-on-update-failure
This commit is contained in:
parent
b3d5948c77
commit
1aed004a50
@ -81,6 +81,13 @@ fake_responses = {
|
||||
UPDATED_BAY,
|
||||
),
|
||||
},
|
||||
'/v1/bays/%s/?rollback=True' % BAY1['id']:
|
||||
{
|
||||
'PATCH': (
|
||||
{},
|
||||
UPDATED_BAY,
|
||||
),
|
||||
},
|
||||
'/v1/bays/%s' % BAY1['name']:
|
||||
{
|
||||
'GET': (
|
||||
@ -297,3 +304,14 @@ class BayManagerTest(testtools.TestCase):
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(NEW_NAME, bay.name)
|
||||
|
||||
def test_bay_update_with_rollback(self):
|
||||
patch = {'op': 'replace',
|
||||
'value': NEW_NAME,
|
||||
'path': '/name'}
|
||||
bay = self.mgr.update(id=BAY1['id'], patch=patch, rollback=True)
|
||||
expect = [
|
||||
('PATCH', '/v1/bays/%s/?rollback=True' % BAY1['id'], {}, patch),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(NEW_NAME, bay.name)
|
||||
|
@ -245,14 +245,29 @@ class ShellTest(shell_test_base.TestCommandLineArgument):
|
||||
def test_bay_update_success(self, mock_update):
|
||||
self._test_arg_success('bay-update test add test=test')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'}]
|
||||
mock_update.assert_called_once_with('test', patch)
|
||||
mock_update.assert_called_once_with('test', patch, False)
|
||||
|
||||
@mock.patch('magnumclient.v1.bays.BayManager.update')
|
||||
def test_bay_update_success_many_attribute(self, mock_update):
|
||||
self._test_arg_success('bay-update test add test=test test1=test1')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'},
|
||||
{'op': 'add', 'path': '/test1', 'value': 'test1'}]
|
||||
mock_update.assert_called_once_with('test', patch)
|
||||
mock_update.assert_called_once_with('test', patch, False)
|
||||
|
||||
@mock.patch('magnumclient.v1.bays.BayManager.update')
|
||||
def test_bay_update_success_rollback(self, mock_update):
|
||||
self._test_arg_success('bay-update test add test=test --rollback')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'}]
|
||||
mock_update.assert_called_once_with('test', patch, True)
|
||||
|
||||
@mock.patch('magnumclient.v1.bays.BayManager.update')
|
||||
def test_bay_update_rollback_old_api_version(self, mock_update):
|
||||
self.assertRaises(
|
||||
exceptions.CommandError,
|
||||
self.shell,
|
||||
'--magnum-api-version 1.2 bay-update '
|
||||
'test add test=test --rollback')
|
||||
mock_update.assert_not_called()
|
||||
|
||||
@mock.patch('magnumclient.v1.bays.BayManager.update')
|
||||
def test_bay_update_failure_wrong_op(self, mock_update):
|
||||
|
@ -81,6 +81,13 @@ fake_responses = {
|
||||
UPDATED_CLUSTER,
|
||||
),
|
||||
},
|
||||
'/v1/clusters/%s/?rollback=True' % CLUSTER1['id']:
|
||||
{
|
||||
'PATCH': (
|
||||
{},
|
||||
UPDATED_CLUSTER,
|
||||
),
|
||||
},
|
||||
'/v1/clusters/%s' % CLUSTER1['name']:
|
||||
{
|
||||
'GET': (
|
||||
@ -313,3 +320,16 @@ class ClusterManagerTest(testtools.TestCase):
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(NEW_NAME, cluster.name)
|
||||
|
||||
def test_cluster_update_with_rollback(self):
|
||||
patch = {'op': 'replace',
|
||||
'value': NEW_NAME,
|
||||
'path': '/name'}
|
||||
cluster = self.mgr.update(id=CLUSTER1['id'], patch=patch,
|
||||
rollback=True)
|
||||
expect = [
|
||||
('PATCH', '/v1/clusters/%s/?rollback=True' % CLUSTER1['id'],
|
||||
{}, patch),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(NEW_NAME, cluster.name)
|
||||
|
@ -295,14 +295,29 @@ class ShellTest(shell_test_base.TestCommandLineArgument):
|
||||
def test_cluster_update_success(self, mock_update):
|
||||
self._test_arg_success('cluster-update test add test=test')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'}]
|
||||
mock_update.assert_called_once_with('test', patch)
|
||||
mock_update.assert_called_once_with('test', patch, False)
|
||||
|
||||
@mock.patch('magnumclient.v1.clusters.ClusterManager.update')
|
||||
def test_cluster_update_success_many_attribute(self, mock_update):
|
||||
self._test_arg_success('cluster-update test add test=test test1=test1')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'},
|
||||
{'op': 'add', 'path': '/test1', 'value': 'test1'}]
|
||||
mock_update.assert_called_once_with('test', patch)
|
||||
mock_update.assert_called_once_with('test', patch, False)
|
||||
|
||||
@mock.patch('magnumclient.v1.clusters.ClusterManager.update')
|
||||
def test_cluster_update_success_rollback(self, mock_update):
|
||||
self._test_arg_success('cluster-update test add test=test --rollback')
|
||||
patch = [{'op': 'add', 'path': '/test', 'value': 'test'}]
|
||||
mock_update.assert_called_once_with('test', patch, True)
|
||||
|
||||
@mock.patch('magnumclient.v1.clusters.ClusterManager.update')
|
||||
def test_cluster_update_rollback_old_api_version(self, mock_update):
|
||||
self.assertRaises(
|
||||
exceptions.CommandError,
|
||||
self.shell,
|
||||
'--magnum-api-version 1.2 cluster-update '
|
||||
'test add test=test --rollback')
|
||||
mock_update.assert_not_called()
|
||||
|
||||
@mock.patch('magnumclient.v1.clusters.ClusterManager.update')
|
||||
def test_cluster_update_failure_wrong_op(self, mock_update):
|
||||
|
@ -104,5 +104,8 @@ class BaseTemplateManager(base.Manager):
|
||||
def delete(self, id):
|
||||
return self._delete(self._path(id))
|
||||
|
||||
def update(self, id, patch):
|
||||
return self._update(self._path(id), patch)
|
||||
def update(self, id, patch, rollback=False):
|
||||
url = self._path(id)
|
||||
if rollback:
|
||||
url += '/?rollback=True'
|
||||
return self._update(url, patch)
|
||||
|
@ -176,6 +176,9 @@ def do_bay_show(cs, args):
|
||||
|
||||
|
||||
@utils.arg('bay', metavar='<bay>', help="UUID or name of bay")
|
||||
@utils.arg('--rollback',
|
||||
action='store_true', default=False,
|
||||
help='Rollback bay on update failure.')
|
||||
@utils.arg(
|
||||
'op',
|
||||
metavar='<op>',
|
||||
@ -195,8 +198,13 @@ def do_bay_update(cs, args):
|
||||
|
||||
(Deprecated in favor of cluster-update.)
|
||||
"""
|
||||
if args.rollback and args.magnum_api_version and \
|
||||
args.magnum_api_version in ('1.0', '1.1', '1.2'):
|
||||
raise exceptions.CommandError(
|
||||
"Rollback is not supported in API v%s. "
|
||||
"Please use API v1.3+." % args.magnum_api_version)
|
||||
patch = magnum_utils.args_array_to_patch(args.op, args.attributes[0])
|
||||
bay = cs.bays.update(args.bay, patch)
|
||||
bay = cs.bays.update(args.bay, patch, args.rollback)
|
||||
if args.magnum_api_version and args.magnum_api_version == '1.1':
|
||||
_show_bay(bay)
|
||||
else:
|
||||
|
@ -184,6 +184,9 @@ def do_cluster_show(cs, args):
|
||||
|
||||
|
||||
@utils.arg('cluster', metavar='<cluster>', help="UUID or name of cluster")
|
||||
@utils.arg('--rollback',
|
||||
action='store_true', default=False,
|
||||
help='Rollback cluster on update failure.')
|
||||
@utils.arg(
|
||||
'op',
|
||||
metavar='<op>',
|
||||
@ -199,8 +202,13 @@ def do_cluster_show(cs, args):
|
||||
"(only PATH is necessary on remove)")
|
||||
def do_cluster_update(cs, args):
|
||||
"""Update information about the given cluster."""
|
||||
if args.rollback and args.magnum_api_version and \
|
||||
args.magnum_api_version in ('1.0', '1.1', '1.2'):
|
||||
raise exceptions.CommandError(
|
||||
"Rollback is not supported in API v%s. "
|
||||
"Please use API v1.3+." % args.magnum_api_version)
|
||||
patch = magnum_utils.args_array_to_patch(args.op, args.attributes[0])
|
||||
cluster = cs.clusters.update(args.cluster, patch)
|
||||
cluster = cs.clusters.update(args.cluster, patch, args.rollback)
|
||||
if args.magnum_api_version and args.magnum_api_version == '1.1':
|
||||
_show_cluster(cluster)
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user