3 from planetstack.config import Config
4 from observer.openstacksyncstep import OpenStackSyncStep
6 class GarbageCollector(OpenStackSyncStep):
7 requested_interval = 86400
12 logger.info('gc start')
16 self.gc_user_tenant_roles()
19 self.gc_external_routes()
25 all role that don't already exist in keystone. Remove keystone roles that
26 don't exist in planetstack
28 # sync all roles that don't already in keystone
29 keystone_roles = self.driver.shell.keystone.roles.findall()
30 keystone_role_names = [kr.name for kr in keystone_roles]
31 pending_roles = Role.objects.all()
32 pending_role_names = [r.role_type for r in pending_roles]
33 # don't delete roles for now
35 # delete keystone roles that don't exist in planetstack
36 for keystone_role in keystone_roles:
37 if keystone_role.name == 'admin':
39 if keystone_role.name not in pending_role_names:
41 self.manager.driver.delete_role({id: keystone_role.id})
48 Remove sites and slices that no don't exist in openstack db if they
49 have an enacted time (enacted != None).
51 # get all sites that where enacted != null. We can assume these sites
52 # have previously been synced and need to be checed for deletion.
53 sites = Site.objects.filter(enacted__isnull=False)
56 site_dict[site.login_base] = site
58 # get all slices that where enacted != null. We can assume these slices
59 # have previously been synced and need to be checed for deletion.
60 slices = Slice.objects.filter(enacted__isnull=False)
63 slice_dict[slice.name] = slice
65 # delete keystone tenants that don't have a site record
66 tenants = self.driver.shell.keystone.tenants.findall()
67 system_tenants = ['admin','service']
68 for tenant in tenants:
69 if tenant.name in system_tenants:
71 if tenant.name not in site_dict and tenant.name not in slice_dict:
73 self.driver.delete_tenant(tenant.id)
74 logger.info("deleted tenant: %s" % (tenant))
76 logger.log_exc("delete tenant failed: %s" % tenant)
81 Remove users that no don't exist in openstack db if they have an
82 enacted time (enacted != None).
84 # get all users that where enacted != null. We can assume these users
85 # have previously been synced and need to be checed for deletion.
86 users = User.objects.filter(enacted__isnull=False)
89 user_dict[user.kuser_id] = user
91 # delete keystone users that don't have a user record
92 system_users = ['admin', 'nova', 'quantum', 'glance', 'cinder', 'swift', 'service']
93 users = self.driver.shell.keystone.users.findall()
95 if user.name in system_users:
97 if user.id not in user_dict:
99 #self.manager.driver.delete_user(user.id)
100 logger.info("deleted user: %s" % user)
102 logger.log_exc("delete user failed: %s" % user)
105 def gc_user_tenant_roles(self):
107 Remove roles that don't exist in openstack db if they have
108 an enacted time (enacted != None).
110 # get all site privileges and slice memberships that have been enacted
111 user_tenant_roles = defaultdict(list)
112 for site_priv in SitePrivilege.objects.filter(enacted__isnull=False):
113 user_tenant_roles[(site_priv.user.kuser_id, site_priv.site.tenant_id)].append(site_priv.role.role)
114 for slice_memb in SliceMembership.objects.filter(enacted__isnull=False):
115 user_tenant_roles[(slice_memb.user.kuser_id, slice_memb.slice.tenant_id)].append(slice_memb.role.role)
117 # Some user tenant role aren't stored in planetstack but they must be preserved.
118 # Role that fall in this category are
119 # 1. Never remove a user's role that their home site
120 # 2. Never remove a user's role at a slice they've created.
121 # Keep track of all roles that must be preserved.
122 users = User.objects.all()
125 tenant_ids = [s['tenant_id'] for s in user.slices.values()]
126 tenant_ids.append(user.site.tenant_id)
127 preserved_roles[user.kuser_id] = tenant_ids
130 # begin removing user tenant roles from keystone. This is stored in the
132 for metadata in self.driver.shell.keystone_db.get_metadata():
134 if metadata.user_id == self.manager.driver.admin_user.id:
136 # skip preserved tenant ids
137 if metadata.user_id in preserved_roles and \
138 metadata.tenant_id in preserved_roles[metadata.user_id]:
140 # get roles for user at this tenant
141 user_tenant_role_ids = user_tenant_roles.get((metadata.user_id, metadata.tenant_id), [])
143 if user_tenant_role_ids:
144 # The user has roles at the tenant. Check if roles need to
146 user_keystone_role_ids = metadata.data.get('roles', [])
147 for role_id in user_keystone_role_ids:
148 if role_id not in user_tenant_role_ids:
149 user_keystone_role_ids.pop(user_keystone_role_ids.index(role_id))
151 # The user has no roles at this tenant.
152 metadata.data['roles'] = []
153 #session.add(metadata)
154 logger.info("pruning metadata for %s at %s" % (metadata.user_id, metadata.tenant_id))
156 def gc_slivers(self):
158 Remove slivers that no don't exist in openstack db if they have
159 an enacted time (enacted != None).
161 # get all slivers where enacted != null. We can assume these users
162 # have previously been synced and need to be checed for deletion.
163 slivers = Sliver.objects.filter(enacted__isnull=False)
165 for sliver in slivers:
166 sliver_dict[sliver.instance_id] = sliver
168 # delete sliver that don't have a sliver record
169 ctx = self.driver.shell.nova_db.ctx
170 instances = self.driver.shell.nova_db.instance_get_all(ctx)
171 for instance in instances:
172 if instance.uuid not in sliver_dict:
174 # lookup tenant and update context
175 tenant = self.driver.shell.keystone.tenants.find(id=instance.project_id)
176 driver = self.driver.client_driver(tenant=tenant.name)
177 driver.destroy_instance(instance.uuid)
178 logger.info("destroyed sliver: %s" % (instance))
180 logger.log_exc("destroy sliver failed: %s" % instance)
183 def gc_sliver_ips(self):
185 Update ips that have changed.
187 # fill in null ip addresses
188 slivers = Sliver.objects.filter(ip=None)
189 for sliver in slivers:
191 self.manager.init_admin(tenant=sliver.slice.name)
192 servers = self.manager.driver.shell.nova.servers.findall(id=sliver.instance_id)
196 ips = server.addresses.get(sliver.slice.name, [])
197 if ips and sliver.ip != ips[0]['addr']:
198 sliver.ip = ips[0]['addr']
200 logger.info("updated sliver ip: %s %s" % (sliver, ips[0]))
202 def gc_external_routes(self):