Add cmd to clean up stale openstack heat stacks 74/12674/5
authorThanh Ha <thanh.ha@linuxfoundation.org>
Thu, 20 Sep 2018 01:57:41 +0000 (21:57 -0400)
committerThanh Ha <thanh.ha@linuxfoundation.org>
Tue, 16 Oct 2018 23:28:24 +0000 (19:28 -0400)
Issue: RELENG-237
Change-Id: I8e2fcef93798395cc61f686a143ca3add5d081f2
Signed-off-by: Thanh Ha <thanh.ha@linuxfoundation.org>
lftools/openstack/cmd.py
lftools/openstack/stack.py
releasenotes/notes/openstack-delete-stale-stacks-bec3f2c27cd7cbe5.yaml [new file with mode: 0644]

index 495e9e7..522eca0 100644 (file)
@@ -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()
index 5a76498..f4133d2 100644 (file)
 
 __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 (file)
index 0000000..e4be14a
--- /dev/null
@@ -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.