OpenStack Orphans
14 April, 2015It’s surprisingly easy to find yourself with a large number of orphaned Neutron objects in your OpenStack installation, i.e resources left behind after a project or tenant has been deleted. This can be particularly problematic when it comes to routers and floating IP addresses as these can quickly eat into what precious few addresses you might have available, especially if they’re publically accessible.
Here’s a bit of python I’ve knocked together to check for orphaned resources of this type within your OpenStack install. The credentials are taken from your current working environment and you’ll need to be an administrator in order for this to work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 <object> 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'] | |
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): | |
tenantids = get_tenantids() | |
objects = getattr(neutron, 'list_' + object)() | |
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) |