^^^^
.. 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
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
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):
--- /dev/null
+# -*- 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