Use workflow for overcloud node delete

This patch adds support for using a workflow in tripleo-common
for deleting nodes from a stack (scale down).

Change-Id: Ia65734273d70ea0ae30d96122728950e1f0217b8
Partial-Bug: #1626736
This commit is contained in:
Ryan Brady 2016-10-06 14:04:58 -04:00
parent 846e7f35d4
commit a85ad62d85
3 changed files with 103 additions and 16 deletions

View File

@ -33,11 +33,26 @@ class TestDeleteNode(fakes.TestDeleteNode):
# Get the command object to test # Get the command object to test
self.cmd = overcloud_node.DeleteNode(self.app, None) self.cmd = overcloud_node.DeleteNode(self.app, None)
self.app.client_manager.workflow_engine = mock.Mock()
self.tripleoclient = mock.Mock()
self.websocket = mock.Mock()
self.websocket.__enter__ = lambda s: self.websocket
self.websocket.__exit__ = lambda s, *exc: None
self.tripleoclient = mock.Mock()
self.tripleoclient.messaging_websocket.return_value = self.websocket
self.app.client_manager.tripleoclient = self.tripleoclient
self.workflow = self.app.client_manager.workflow_engine
# Mock UUID4 generation for every test
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4")
self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop)
# TODO(someone): This test does not pass with autospec=True, it should # TODO(someone): This test does not pass with autospec=True, it should
# probably be fixed so that it can pass with that. # probably be fixed so that it can pass with that.
@mock.patch('tripleo_common.scale.ScaleManager') def test_node_delete(self):
def test_node_delete(self, scale_manager):
argslist = ['instance1', 'instance2', '--templates', argslist = ['instance1', 'instance2', '--templates',
'--stack', 'overcloud'] '--stack', 'overcloud']
verifylist = [ verifylist = [
@ -45,10 +60,21 @@ class TestDeleteNode(fakes.TestDeleteNode):
('nodes', ['instance1', 'instance2']) ('nodes', ['instance1', 'instance2'])
] ]
parsed_args = self.check_parser(self.cmd, argslist, verifylist) parsed_args = self.check_parser(self.cmd, argslist, verifylist)
self.websocket.wait_for_message.return_value = {
"status": "SUCCESS"
}
self.cmd.take_action(parsed_args) self.cmd.take_action(parsed_args)
scale_manager.scaledown(parsed_args.nodes)
scale_manager.scaledown.assert_called_once_with(['instance1', # Verify
'instance2']) self.workflow.executions.create.assert_called_once_with(
'tripleo.scale.v1.delete_node',
workflow_input={
'container': 'overcloud',
'queue_name': 'UUID4',
'nodes': ['instance1', 'instance2']
})
class TestProvideNode(fakes.TestOvercloudNode): class TestProvideNode(fakes.TestOvercloudNode):

View File

@ -20,11 +20,11 @@ import uuid
from osc_lib.command import command from osc_lib.command import command
from osc_lib.i18n import _ from osc_lib.i18n import _
from osc_lib import utils from osc_lib import utils
from tripleo_common import scale
from tripleoclient import constants from tripleoclient import constants
from tripleoclient import utils as oooutils from tripleoclient import utils as oooutils
from tripleoclient.workflows import baremetal from tripleoclient.workflows import baremetal
from tripleoclient.workflows import scale
class DeleteNode(command.Command): class DeleteNode(command.Command):
@ -42,14 +42,21 @@ class DeleteNode(command.Command):
default=utils.env('OVERCLOUD_STACK_NAME')) default=utils.env('OVERCLOUD_STACK_NAME'))
parser.add_argument( parser.add_argument(
'--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES, '--templates', nargs='?', const=constants.TRIPLEO_HEAT_TEMPLATES,
help=_("The directory containing the Heat templates to deploy") help=_("The directory containing the Heat templates to deploy. "
"This argument is deprecated. The command now utilizes "
"a deployment plan, which should be updated prior to "
"running this command, should that be required. Otherwise "
"this argument will be silently ignored."),
) )
parser.add_argument( parser.add_argument(
'-e', '--environment-file', metavar='<HEAT ENVIRONMENT FILE>', '-e', '--environment-file', metavar='<HEAT ENVIRONMENT FILE>',
action='append', dest='environment_files', action='append', dest='environment_files',
help=_('Environment files to be passed to the heat stack-create ' help=_("Environment files to be passed to the heat stack-create "
'or heat stack-update command. (Can be specified more than ' "or heat stack-update command. (Can be specified more than "
'once.)') "once.) This argument is deprecated. The command now "
"utilizes a deployment plan, which should be updated prior "
"to running this command, should that be required. "
"Otherwise this argument will be silently ignored."),
) )
return parser return parser
@ -58,14 +65,10 @@ class DeleteNode(command.Command):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
clients = self.app.client_manager clients = self.app.client_manager
scale_manager = scale.ScaleManager(
heatclient=clients.orchestration,
stack_id=parsed_args.stack,
tht_dir=parsed_args.templates,
environment_files=parsed_args.environment_files)
print("deleting nodes {0} from stack {1}".format(parsed_args.nodes, print("deleting nodes {0} from stack {1}".format(parsed_args.nodes,
parsed_args.stack)) parsed_args.stack))
scale_manager.scaledown(parsed_args.nodes)
scale.scale_down(clients, parsed_args.stack, parsed_args.nodes)
class ProvideNode(command.Command): class ProvideNode(command.Command):

View File

@ -0,0 +1,58 @@
# Copyright 2016 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
import pprint
import uuid
from tripleoclient.workflows import base
def delete_node(clients, **workflow_input):
workflow_client = clients.workflow_engine
tripleoclients = clients.tripleoclient
queue_name = workflow_input['queue_name']
execution = base.start_workflow(
workflow_client,
'tripleo.scale.v1.delete_node',
workflow_input=workflow_input
)
with tripleoclients.messaging_websocket(queue_name) as ws:
message = ws.wait_for_message(execution.id)
assert message['status'] == "SUCCESS", pprint.pformat(message)
def scale_down(clients, plan_name, nodes, timeout=None):
"""Deletes overcloud nodes from a heat stack.
:param clients: openstack clients
:param plan_name: name of the container holding the plan data
:param nodes: list of node id's to remove from the stack
:param timeout: timeout for stack update operation
"""
workflow_input = {
"container": plan_name,
"nodes": nodes,
"queue_name": str(uuid.uuid4()),
}
if timeout is not None:
workflow_input['timeout'] = timeout
delete_node(clients, **workflow_input)