From: Thanh Ha Date: Thu, 20 Sep 2018 01:57:41 +0000 (-0400) Subject: Add cmd to clean up stale openstack heat stacks X-Git-Tag: v0.18.0~2 X-Git-Url: https://gerrit.linuxfoundation.org/infra/gitweb?a=commitdiff_plain;h=a440a11bfa4d8f603589b1cf66caa26ccc57ce1d;p=releng%2Flftools.git Add cmd to clean up stale openstack heat stacks Issue: RELENG-237 Change-Id: I8e2fcef93798395cc61f686a143ca3add5d081f2 Signed-off-by: Thanh Ha --- diff --git a/lftools/openstack/cmd.py b/lftools/openstack/cmd.py index 495e9e7e..522eca04 100644 --- a/lftools/openstack/cmd.py +++ b/lftools/openstack/cmd.py @@ -195,15 +195,31 @@ def create(ctx, name, template_file, parameter_file, timeout, tries): help='Stack delete timeout in seconds.') @click.pass_context def delete(ctx, name_or_id, timeout): - """Create stack.""" + """Delete stack.""" os_stack.delete( ctx.obj['os_cloud'], name_or_id, timeout) +@click.command(name='delete-stale') +@click.argument('jenkins_urls', nargs=-1) +@click.pass_context +def delete_stale(ctx, jenkins_urls): + """Delete stale stacks. + + This command checks Jenkins and OpenStack for stacks that do not appear in + both places. If a stack is no longer available in Jenkins but is in + OpenStack then it is considered stale. Stale stacks are then deleted. + """ + os_stack.delete_stale( + ctx.obj['os_cloud'], + jenkins_urls) + + stack.add_command(create) stack.add_command(delete) +stack.add_command(delete_stale) @openstack.group() diff --git a/lftools/openstack/stack.py b/lftools/openstack/stack.py index 5a764988..f4133d21 100644 --- a/lftools/openstack/stack.py +++ b/lftools/openstack/stack.py @@ -12,11 +12,16 @@ __author__ = 'Thanh Ha' +import logging import sys import time import shade +from lftools.jenkins import Jenkins + +log = logging.getLogger(__name__) + 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.""" @@ -101,3 +106,55 @@ def delete(os_cloud, name_or_id, timeout=900): print('Failed to delete stack.') return False + + +def delete_stale(os_cloud, jenkins_servers): + """Search Jenkins and OpenStack for orphaned stacks and remove them. + + An orphaned stack is a stack that is not known in any of the Jenkins + servers passed into this function. + """ + cloud = shade.openstack_cloud(cloud=os_cloud) + stacks = cloud.search_stacks() + if not stacks: + log.debug('No stacks to delete.') + sys.exit(0) + + builds = [] + for server in jenkins_servers: + jenkins = Jenkins(server) + jenkins_url = jenkins.url.rstrip('/') + silo = jenkins_url.split('/') + + if len(silo) == 4: # https://jenkins.opendaylight.org/releng + silo = silo[3] + elif len(silo) == 3: # https://jenkins.onap.org + silo = 'production' + else: + log.error('Unexpected URL pattern, could not detect silo.') + sys.exit(1) + + log.debug('Fetching running builds from {}'.format(jenkins_url)) + running_builds = jenkins.server.get_running_builds() + for build in running_builds: + build_name = '{}-{}-{}'.format( + silo, build.get('name'), build.get('number')) + log.debug(' {}'.format(build_name)) + builds.append(build_name) + + log.debug('Active stacks') + for stack in stacks: + if (stack.stack_status == 'CREATE_COMPLETE' or + stack.stack_status == 'CREATE_FAILED' or + stack.stack_status == 'DELETE_FAILED'): + log.debug(' {}'.format(stack.stack_name)) + + if stack.stack_status == 'DELETE_FAILED': + cloud.pprint(stack) + + if stack.stack_name not in builds: + log.debug(' >>>> Marked for deletion <<<<') + delete(os_cloud, stack.stack_name) + + else: + continue diff --git a/releasenotes/notes/openstack-delete-stale-stacks-bec3f2c27cd7cbe5.yaml b/releasenotes/notes/openstack-delete-stale-stacks-bec3f2c27cd7cbe5.yaml new file mode 100644 index 00000000..e4be14a9 --- /dev/null +++ b/releasenotes/notes/openstack-delete-stale-stacks-bec3f2c27cd7cbe5.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Add a new ``delete-stale`` option to the **stack** command. + + This function compares running builds in Jenkins to active stacks in + OpenStack and determines if there are orphaned stacks and removes them.