.. toctree::
:maxdepth: 2
+ nexus
+ openstack
version
--- /dev/null
+*********
+OpenStack
+*********
+
+.. program-output:: lftools openstack --help
+
+Commands
+========
+
+.. contents:: OpenStack Commands
+ :local:
+
+image
+-----
+
+.. program-output:: lftools openstack --os-cloud docs image --help
+
+cleanup
+^^^^^^^
+
+The intent of this command is to automatically cleanup old images in the cloud.
+The OpenDaylight project has 2 clouds, a Private Cloud and a Public cloud which
+needs the `--clouds` option to automatically remove the same images from
+multiple clouds simultaniously.
+
+.. program-output:: lftools openstack --os-cloud docs image cleanup --help
+
+list
+^^^^
+
+.. program-output:: lftools openstack --os-cloud docs image list --help
import click
from lftools.cli.nexus import nexus
from lftools.cli.version import version
+from lftools.openstack.cmd import openstack
@click.group()
pass
+cli.add_command(openstack)
cli.add_command(nexus)
cli.add_command(version)
-if __name__ == '__main__':
+def main():
+ """Entry point for lftools CLI."""
cli(obj={})
+
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+# @License EPL-1.0 <http://spdx.org/licenses/EPL-1.0>
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+"""lftools openstack package."""
+
+__author__ = 'Thanh Ha'
--- /dev/null
+# -*- code: utf-8 -*-
+# @License EPL-1.0 <http://spdx.org/licenses/EPL-1.0>
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+"""CLI configuration for openstack command."""
+
+__author__ = 'Thanh Ha'
+
+
+import click
+from lftools.openstack import image as os_image
+
+
+@click.group()
+@click.option('--os-cloud', envvar='OS_CLOUD', type=str, required=True)
+@click.pass_context
+def openstack(ctx, os_cloud):
+ """Provide an interface to OpenStack."""
+ ctx.obj['os_cloud'] = os_cloud
+
+
+@openstack.group()
+@click.pass_context
+def image(ctx):
+ """Command for manipulating images."""
+ pass
+
+
+@click.command()
+@click.option(
+ '--days', type=int, default=0,
+ help='Find images older than or equal to days.')
+@click.option(
+ '--hide-public', type=bool, default=False,
+ help='Ignore public images.')
+@click.option(
+ '--clouds', type=str, default=None,
+ help=('Clouds (as defined in clouds.yaml) to remove images from. If not'
+ 'passed will assume from os-cloud parameter. (optional)'))
+@click.pass_context
+def cleanup(ctx, days, hide_public, clouds):
+ """Cleanup old images."""
+ os_image.cleanup(
+ ctx.obj['os_cloud'],
+ days=days,
+ hide_public=hide_public,
+ clouds=clouds)
+
+
+@click.command()
+@click.option(
+ '--days', type=int, default=0,
+ help='Find images older than or equal to days.')
+@click.option(
+ '--hide-public', type=bool, default=False,
+ help='Ignore public images.')
+@click.pass_context
+def list(ctx, days, hide_public):
+ """List cloud images."""
+ os_image.list(
+ ctx.obj['os_cloud'],
+ days=days,
+ hide_public=hide_public)
+
+
+image.add_command(cleanup)
+image.add_command(list)
--- /dev/null
+# -*- code: utf-8 -*-
+# @License EPL-1.0 <http://spdx.org/licenses/EPL-1.0>
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+"""Image related sub-commands for openstack command."""
+
+__author__ = 'Thanh Ha'
+
+from datetime import datetime
+from datetime import timedelta
+
+import shade
+
+
+def _filter_images(images, days=0, hide_public=False):
+ """Filter image data and return list.
+
+ :arg bool hide_public: Whether or not to include public images.
+ """
+ filtered = []
+ for image in images:
+ if hide_public and image.is_public:
+ continue
+ if days and (
+ datetime.strptime(image.created_at, '%Y-%m-%dT%H:%M:%SZ')
+ >= datetime.now() - timedelta(days=days)):
+ continue
+
+ filtered.append(image)
+ return filtered
+
+
+def list(os_cloud, days=0, hide_public=False):
+ """List images found according to parameters."""
+ cloud = shade.openstack_cloud(cloud=os_cloud)
+ images = cloud.list_images()
+
+ filtered_images = _filter_images(images, days, hide_public)
+ for image in filtered_images:
+ print(image.name)
+
+
+def cleanup(os_cloud, days=0, hide_public=False, clouds=None):
+ """Remove image from cloud.
+
+ :arg str os_cloud: Cloud name as defined in OpenStack clouds.yaml.
+ :arg int days: Filter images that are older than number of days.
+ :arg bool hide_public: If true, will ignore public images. (Default: false)
+ :arg str clouds: If passed, comma-separated list of clouds to remove image
+ from. Otherwise os_cloud will be used.
+ """
+ def _remove_images_from_cloud(images, cloud):
+ print('Removing {} images from {}.'.format(len(images), cloud.cloud_config.name))
+ for image in images:
+ try:
+ result = cloud.delete_image(image.name)
+ except shade.exc.OpenStackCloudException as e:
+ if str(e).startswith('Multiple matches found for'):
+ print('WARNING: {}. Skipping image...'.format(str(e)))
+ continue
+ else:
+ print('ERROR: Unexpected exception: {}'.format(str(e)))
+ raise
+
+ if not result:
+ print('WARNING: Failed to remove \"{}\" from {}. Possibly already deleted.'
+ .format(image.name, cloud.cloud_config.name))
+ else:
+ print('Removed "{}" from {}.'.format(image.name, cloud.cloud_config.name))
+
+ cloud = shade.openstack_cloud(cloud=os_cloud)
+ if clouds:
+ cloud_list = []
+ for c in clouds.split(","):
+ cloud_list.append(shade.openstack_cloud(cloud=c))
+
+ images = cloud.list_images()
+ filtered_images = _filter_images(images, days, hide_public)
+
+ if clouds:
+ for c in cloud_list:
+ _remove_images_from_cloud(filtered_images, c)
+ else:
+ _remove_images_from_cloud(filtered_images, cloud)
click
pyyaml
requests
+shade
sphinx>=1.4.9
sphinxcontrib-programoutput
sphinx_bootstrap_theme>=0.4.14
tests_require=['pytest'],
entry_points='''
[console_scripts]
- lftools=lftools.cli:cli
+ lftools=lftools.cli:main
''',
scripts=[
'shell/version',