From: Thanh Ha Date: Tue, 21 Aug 2018 23:05:31 +0000 (-0400) Subject: Add stack create & delete commands X-Git-Tag: v0.17.0~1^2 X-Git-Url: https://gerrit.linuxfoundation.org/infra/gitweb?a=commitdiff_plain;h=0a5942299f83aaa74da3bf1fdf985d4003ce30f3;p=releng%2Flftools.git Add stack create & delete commands Add 2 new commands: - stack create - stack delete These commands allow lftools the ability to create and delete stacks. Issue: RELENG-235 Change-Id: Ied7ff51a292199675dc944e36f1d821a5a2d045d Signed-off-by: Thanh Ha --- diff --git a/docs/commands/openstack.rst b/docs/commands/openstack.rst index eb33937c..fefa86e1 100644 --- a/docs/commands/openstack.rst +++ b/docs/commands/openstack.rst @@ -31,3 +31,41 @@ list ^^^^ .. program-output:: lftools openstack --os-cloud docs image list --help + +stack +----- + +Command for managing stacks. + +.. program-output:: lftools openstack --os-cloud docs stack --help + +create +^^^^^^ + +Create a new stack. + +.. program-output:: lftools openstack --os-cloud docs stack create --help + +The create command requires a parameters file in the following format in order +to build out the stack: + +.. code-block: yaml + :caption: parameter_file + + parameters: + job_name: JOB_NAME + silo: SILO + vm_0_count: 1 + vm_0_flavor: odl-highcpu-4 + vm_0_image: ZZCI - CentOS 7 - builder - 20180802-220823.782 + vm_1_count: 1 + vm_1_flavor: odl-standard-4 + vm_1_image: ZZCI - CentOS 7 - devstack-pike - 20171208-1649 + + +delete +^^^^^^ + +Delete existing stack. + +.. program-output:: lftools openstack --os-cloud docs stack delete --help diff --git a/lftools/openstack/cmd.py b/lftools/openstack/cmd.py index 0a110dea..a0b6c5f2 100644 --- a/lftools/openstack/cmd.py +++ b/lftools/openstack/cmd.py @@ -17,6 +17,7 @@ import click from lftools.openstack import image as os_image from lftools.openstack import server as os_server +from lftools.openstack import stack as os_stack from lftools.openstack import volume as os_volume @@ -134,6 +135,53 @@ server.add_command(list) server.add_command(remove) +@openstack.group() +@click.pass_context +def stack(ctx): + """Command for manipulating stacks.""" + pass + + +@click.command() +@click.argument('name') +@click.argument('template_file') +@click.argument('parameter_file') +@click.option( + '--timeout', type=int, default=900, + help='Stack create timeout in seconds.') +@click.option( + '--tries', type=int, default=2, + help='Number of tries before giving up.') +@click.pass_context +def create(ctx, name, template_file, parameter_file, timeout, tries): + """Create stack.""" + os_stack.create( + ctx.obj['os_cloud'], + name, + template_file, + parameter_file, + timeout, + tries) + + +@click.command() +@click.argument('name_or_id') +@click.option( + '--timeout', type=int, default=900, + help='Stack delete timeout in seconds.') +@click.pass_context +def delete(ctx, name_or_id, timeout): + """Create stack.""" + os_stack.delete( + ctx.obj['os_cloud'], + name_or_id, + timeout) + + +stack.add_command(create) +stack.add_command(delete) + + @openstack.group() @click.pass_context def volume(ctx): diff --git a/lftools/openstack/stack.py b/lftools/openstack/stack.py new file mode 100644 index 00000000..5a764988 --- /dev/null +++ b/lftools/openstack/stack.py @@ -0,0 +1,103 @@ +# -*- code: utf-8 -*- +# SPDX-License-Identifier: EPL-1.0 +############################################################################## +# Copyright (c) 2018 The Linux Foundation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +############################################################################## +"""stack related sub-commands for openstack command.""" + +__author__ = 'Thanh Ha' + +import sys +import time + +import shade + + +def create(os_cloud, name, template_file, parameter_file, timeout=900, tries=2): + """Create a heat stack from a template_file and a parameter_file.""" + cloud = shade.openstack_cloud(cloud=os_cloud) + stack_success = False + + print('Creating stack {}'.format(name)) + for i in range(tries): + try: + stack = cloud.create_stack( + name, + template_file=template_file, + environment_files=[parameter_file], + timeout=timeout, + rollback=False) + except shade.exc.OpenStackCloudHTTPError as e: + if cloud.search_stacks(name): + print('Stack with name {} already exists.'.format(name)) + else: + print(e) + sys.exit(1) + + stack_id = stack.id + t_end = time.time() + timeout + while time.time() < t_end: + time.sleep(10) + stack = cloud.get_stack(stack_id) + + if stack.stack_status == 'CREATE_IN_PROGRESS': + print('Waiting to initialize infrastructure...') + elif stack.stack_status == 'CREATE_COMPLETE': + print('Stack initialization successful.') + stack_success = True + break + elif stack.stack_status == 'CREATE_FAILED': + print('WARN: Failed to initialize stack. Reason: {}'.format( + stack.stack_status_reason)) + if delete(os_cloud, stack_id): + break + else: + print('Unexpected status: {}'.format(stack.stack_status)) + + if stack_success: + break + + print('------------------------------------') + print('Stack Details') + print('------------------------------------') + cloud.pprint(stack) + print('------------------------------------') + + +def delete(os_cloud, name_or_id, timeout=900): + """Delete a stack. + + Return True if delete was successful. + """ + cloud = shade.openstack_cloud(cloud=os_cloud) + print('Deleting stack {}'.format(name_or_id)) + cloud.delete_stack(name_or_id) + + t_end = time.time() + timeout + while time.time() < t_end: + time.sleep(10) + stack = cloud.get_stack(name_or_id) + + if not stack or stack.stack_status == 'DELETE_COMPLETE': + print('Successfully deleted stack {}'.format(name_or_id)) + return True + elif stack.stack_status == 'DELETE_IN_PROGRESS': + print('Waiting for stack to delete...') + elif stack.stack_status == 'DELETE_FAILED': + print('WARN: Failed to delete $STACK_NAME. Reason: {}'.format( + stack.stack_status_reason)) + print('Retrying delete...') + cloud.delete_stack(name_or_id) + else: + print('WARN: Unexpected delete status: {}'.format( + stack.stack_status)) + print('Retrying delete...') + cloud.delete_stack(name_or_id) + + print('Failed to delete stack.') + return False diff --git a/releasenotes/notes/openstack-stack-08f643f16b75bfb8.yaml b/releasenotes/notes/openstack-stack-08f643f16b75bfb8.yaml new file mode 100644 index 00000000..590e6b92 --- /dev/null +++ b/releasenotes/notes/openstack-stack-08f643f16b75bfb8.yaml @@ -0,0 +1,20 @@ +--- +prelude: > + Add new stack command feature to allow creation and deletion of stacks + using lftools. + + Usage: lftools openstack stack create|delete +features: + - | + Add stack command. + https://jira.linuxfoundation.org/browse/RELENG-235 + - | + Add stack create sub-command. + https://jira.linuxfoundation.org/browse/RELENG-235 + + Usage: lftools openstack stack create NAME TEMPLATE_FILE PARAMETER_FILE + - | + Add stack delete sub-command. + https://jira.linuxfoundation.org/browse/RELENG-235 + + Usage: lftools openstack stack create NAME