diff --git a/neutron/listorphans.py b/neutron/listorphans.py deleted file mode 100755 index d6011d9..0000000 --- a/neutron/listorphans.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python - -import os -import sys -import keystoneclient.v2_0.client as ksclient -import neutronclient.v2_0.client as nclient - -def usage(): - print "listorphans.py where object is one or more of", - print "'networks', 'routers', 'subnets', 'floatingips' or 'all'" - -def get_credentials(): - d = {} - d['username'] = os.environ['OS_USERNAME'] - d['password'] = os.environ['OS_PASSWORD'] - d['auth_url'] = os.environ['OS_AUTH_URL'] - d['tenant_name'] = os.environ['OS_TENANT_NAME'] - if 'OS_REGION_NAME' in os.environ: - d['region_name'] = os.environ['OS_REGION_NAME'] - return d - -credentials = get_credentials() -neutron = nclient.Client(**credentials) -keystone = ksclient.Client(**credentials) - -def get_tenantids(): - return [tenant.id for tenant in keystone.tenants.list()] - -def get_orphaned_neutron_objects(object): - objects = getattr(neutron, 'list_' + object)() - tenantids = get_tenantids() - orphans = [] - for object in objects.get(object): - if object['tenant_id'] not in tenantids: - orphans.append(object['id']) - return orphans - -if __name__ == '__main__': - if len(sys.argv) > 1: - if sys.argv[1] == 'all': - objects = [ 'networks', 'routers', 'subnets', 'floatingips' ] - else: - objects = sys.argv[1:] - for object in objects: - orphans = get_orphaned_neutron_objects(object) - print len(orphans), 'orphan(s) found of type', object - print '\n'.join(map(str, orphans)) - else: - usage() - sys.exit(1) diff --git a/neutron/orphan_tool/README.md b/neutron/orphan_tool/README.md new file mode 100644 index 0000000..931f3f1 --- /dev/null +++ b/neutron/orphan_tool/README.md @@ -0,0 +1,52 @@ +# Neutron Orphan Cleanup Tools + +Provides a simple set of scripts to aid in the cleanup of orphaned resources in Neutron. Current +scripts include: + + * list_orhpans.py - List orphaned networks, subnets, routers and floating IPs. + * delete_orphan_floatingips.py - Cleanup floating IPs without any associated ports. + * delete_tenantless_floatingips.py - Cleanup floating IPs without an associated tenant / project. + + +### Installation + +Scripts work with Python 2.7 or newer including Python 3. It is suggested you install any Python +scripts in a seperate Python VirtualEnv to prevent spoiling your system's Python environment. + +Create a new VirtualEnv and assume the VirtualEnv + +``` +virtualenv orphan_tools +source orphan_tools/bin/activate +``` + +Install dependencies + +`pip install -r requirements.txt` + + +### Usage + +Export OpenStack credentials as environment variables + +``` +export OS_USERNAME=test +export OS_PASSWORD=mys3cr3t +export OS_AUTH-URL=https://controller:5000/v2.0 +export OS_TENANT_NAME=test +export OS_REGION_NAME=my_region +``` + +List orphaned Neutron resources + +`python list_orphans.py` + +It is recommended before you delete orphaned resources that you do a dry run and check the script +proposes to delete the resources you expect + +`python delete_orphan_floatingips.py --dry-run` + +Once you are happy you'd like to delete the items returned by the dry run remove the --dry-run flag +to perform the deletion + +`python delete_orphan_floatingips.py` diff --git a/neutron/delete_orphan_floatingips.py b/neutron/orphan_tool/delete_orphan_floatingips.py similarity index 97% rename from neutron/delete_orphan_floatingips.py rename to neutron/orphan_tool/delete_orphan_floatingips.py index 998cf6b..a609bc0 100644 --- a/neutron/delete_orphan_floatingips.py +++ b/neutron/orphan_tool/delete_orphan_floatingips.py @@ -1,13 +1,10 @@ #!/usr/bin/env python - """ This script deletes all the floatingips a user has that are not associated with a port_id. """ - import os import sys - from neutronclient.v2_0 import client @@ -41,4 +38,6 @@ def main(): if not dry_run: neutron.delete_floatingip(floatingip['id']) -main() + +if __name__ == "__main__": + main() diff --git a/neutron/delete_tenantless_floatingips.py b/neutron/orphan_tool/delete_tenantless_floatingips.py similarity index 85% rename from neutron/delete_tenantless_floatingips.py rename to neutron/orphan_tool/delete_tenantless_floatingips.py index cde808a..666efbf 100644 --- a/neutron/delete_tenantless_floatingips.py +++ b/neutron/orphan_tool/delete_tenantless_floatingips.py @@ -1,15 +1,13 @@ #!/usr/bin/env python - """ This script deletes all the floatingips a user has that are not associated with a tenant. """ - import os import sys - -from neutronclient.v2_0 import client import keystoneclient.v2_0.client as ksclient +from neutronclient.v2_0 import client + def main(): @@ -34,10 +32,10 @@ def main(): region_name=region_name) keystone = ksclient.Client(username=username, - tenant_name=tenant_name, - password=password, - auth_url=auth_url, - region_name=region_name) + tenant_name=tenant_name, + password=password, + auth_url=auth_url, + region_name=region_name) floatingips = neutron.list_floatingips() for floatingip in floatingips['floatingips']: @@ -50,4 +48,6 @@ def main(): if not dry_run: neutron.delete_floatingip(floatingip['id']) -main() + +if __name__ == "__main__": + main() diff --git a/neutron/orphan_tool/list_orphans.py b/neutron/orphan_tool/list_orphans.py new file mode 100755 index 0000000..8dbc10e --- /dev/null +++ b/neutron/orphan_tool/list_orphans.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +import os +import sys +import keystoneclient.v2_0.client as ksclient +import neutronclient.v2_0.client as nclient + + +def get_credentials(): + credentials = {} + credentials['username'] = os.environ['OS_USERNAME'] + credentials['password'] = os.environ['OS_PASSWORD'] + credentials['auth_url'] = os.environ['OS_AUTH_URL'] + credentials['tenant_name'] = os.environ['OS_TENANT_NAME'] + if 'OS_REGION_NAME' in os.environ: + credentials['region_name'] = os.environ['OS_REGION_NAME'] + return credentials + + +CREDENTIALS = get_credentials() +NEUTRON = nclient.Client(**CREDENTIALS) +KEYSTONE = ksclient.Client(**CREDENTIALS) + + +def usage(): + print("listorphans.py where object is one or more of ") + print("'networks', 'routers', 'subnets', 'floatingips' or 'all'") + + +def get_tenantids(): + return [tenant.id for tenant in KEYSTONE.tenants.list()] + + +def get_orphaned_neutron_objects(neutron_obj): + neutron_objs = getattr(NEUTRON, 'list_' + neutron_obj)() + tenantids = get_tenantids() + orphans = [] + for neutron_obj in neutron_objs.get(neutron_obj): + if neutron_obj['tenant_id'] not in tenantids: + orphans.append(object['id']) + return orphans + + +if __name__ == '__main__': + if len(sys.argv) > 1: + if sys.argv[1] == 'all': + neutron_objs = ['networks', 'routers', 'subnets', 'floatingips'] + else: + neutron_objs = sys.argv[1:] + for neutron_obj in neutron_objs: + orphans = get_orphaned_neutron_objects(neutron_obj) + print('%s orphan(s) found of type %s' % (len(orphans), + neutron_obj)) + print('\n'.join(map(str, orphans))) + + else: + usage() + sys.exit(1) diff --git a/neutron/orphan_tool/requirements.txt b/neutron/orphan_tool/requirements.txt new file mode 100644 index 0000000..def1693 --- /dev/null +++ b/neutron/orphan_tool/requirements.txt @@ -0,0 +1,2 @@ +python-keystoneclient +python-neutronclient \ No newline at end of file