def get_network(net_id): try: net = admin_client_set().compute.networks.get(net_id) except osc_exc.NotFound: flask.abort(404) return make_json_response(_net_to_dict(net))
def _project_has_servers(project_id): s = admin_client_set().compute.servers.list(detailed=False, search_opts=dict( all_tenants=1, tenant_id=project_id, limit=1)) return len(s) > 0
def list_users(): parse_collection_request(_SCHEMA.list_args) user_mgr = auth.admin_client_set().identity_admin.users return make_collection_response(u'users', [ user_to_view(user) for user in user_mgr.list() if _user_is_visible(user, not g.my_projects) ])
def delete_project(project_id): set_audit_resource_id(project_id) tenant = get_tenant(project_id) # NOTE(imelnikov): server deletion in OpenStack is asynchronous and # takes a lot of time, so to avoid races we don't delete them here if _project_has_servers(project_id): raise exc.InvalidRequest("Can't delete project " "while there are instances in it") # NOTE(imelnikov): image deletion would work OK here, but for consistency # and safety we opt for check instead if _project_has_images(project_id): raise exc.InvalidRequest("Can't delete project " "while there are images in it") # detach all networks net_client = admin_client_set().compute.networks for net in net_client.list(): if net.project_id == tenant.id: net_client.disassociate(net) try: tenant.delete() except osc_exc.NotFound: pass # already deleted by someone else return make_json_response(None, 204)
def remind_about_instances(): """Run periodically to send reminding emails""" cs = admin_client_set() server_mgr = cs.compute.servers user_mgr = cs.identity_admin.users for instance_data in InstanceDataDAO.remind_list(datetime.utcnow()): try: try: server = server_mgr.get(instance_data.instance_id) except osc_exc.NotFound: InstanceDataDAO.delete(instance_data.instance_id) continue try: user = user_mgr.get(server.user_id) except osc_exc.NotFound: pass else: send_instance_reminder(user.email, server.name, server.id, instance_data.expires_at, greeting=getattr(user, 'fullname', '')) InstanceDataDAO.update(instance_data.instance_id, remind_at=None) except Exception: current_app.logger.exception( 'Failed to send reminder email about instance %r' % instance_data.instance_id)
def fetch_instance(instance_id): try: instance = admin_client_set().compute.servers.get(instance_id) except osc_exc.NotFound: abort(404) assert_admin_or_project_user(instance.tenant_id, eperm_status=404) return instance
def list_users(): parse_collection_request(_SCHEMA.list_args) user_mgr = auth.admin_client_set().identity_admin.users return make_collection_response( u'users', [user_to_view(user) for user in user_mgr.list() if _user_is_visible(user, not g.my_projects)])
def _project_has_servers(project_id): s = admin_client_set().compute.servers.list( detailed=False, search_opts=dict(all_tenants=1, tenant_id=project_id, limit=1)) return len(s) > 0
def _project_users_list(project_id): assert_admin_or_project_user(project_id, eperm_status=404) if project_id == default_tenant_id(): abort(404) try: return admin_client_set().identity_admin.tenants.list_users(project_id) except osc_exc.NotFound: abort(404)
def _get_security_group(sg_id): try: sg = auth.admin_client_set().compute.security_groups.get(sg_id) except osc_exc.NotFound: abort(404) auth.assert_admin_or_project_user(sg.tenant_id, eperm_status=404) # TODO(imelnikov): do we need to check if group belongs to systenant? return sg
def list_projects(): parse_collection_request(_SCHEMA) if g.my_projects: client = g.client_set.identity_public else: client = admin_client_set().identity_admin tenants = client.tenants.list() networks = dict(((net.project_id, net) for net in admin_client_set().compute.networks.list() if net.project_id)) systenant = app.config['SYSTENANT'] # systenant is special entity, not a 'project' in Altai sense result = [_project_to_view(t, networks.get(t.id), _quotaset_for_project(t.id)) for t in tenants if t.name != systenant] return make_collection_response(u'projects', result)
def fetch_user(user_id, admin_mode): """Get user from keystone or abort with 404 if user is not found""" try: user = auth.admin_client_set().identity_admin.users.get(user_id) except osc_exc.NotFound: abort(404) if not _user_is_visible(user, admin_mode): abort(404) return user
def get_users_ssh_key(user_id, key_name): if not g.is_admin: fetch_user(user_id, False) # check that user is visible try: mgr = auth.admin_client_set().compute_ext.user_keypairs keypair = mgr.get(user_id, key_name) except osc_exc.NotFound: abort(404) return make_json_response(keypair_to_view(keypair))
def list_projects(): parse_collection_request(_SCHEMA) if g.my_projects: client = g.client_set.identity_public else: client = admin_client_set().identity_admin tenants = client.tenants.list() networks = dict(((net.project_id, net) for net in admin_client_set().compute.networks.list() if net.project_id)) systenant = app.config['SYSTENANT'] # systenant is special entity, not a 'project' in Altai sense result = [ _project_to_view(t, networks.get(t.id), _quotaset_for_project(t.id)) for t in tenants if t.name != systenant ] return make_collection_response(u'projects', result)
def _invite_and_user(code): user_mgr = auth.admin_client_set().identity_admin.users invite = InvitesDAO.get(code) try: assert not invite.complete user = user_mgr.get(invite.user_id) assert not user.enabled except (osc_exc.NotFound, AssertionError): abort(404) return invite, user
def test_admin_client_set_works(self): auth._client_set('test_admin', 'test_p@ssw0rd', tenant_name='test_default_tenant')\ .AndReturn('FAKE_CLIENT_SET') auth.admin_role_id('FAKE_CLIENT_SET').AndReturn('AR_ID') self.mox.ReplayAll() with self.app.test_request_context(): cs = auth.admin_client_set() self.assertEquals(cs, 'FAKE_CLIENT_SET') self.assertEquals(g.admin_client_set, 'FAKE_CLIENT_SET')
def list_users_ssh_keys(user_id): parse_collection_request(_SCHEMA) fetch_user(user_id, g.is_admin) # check that user exists and is visible mgr = auth.admin_client_set().compute_ext.user_keypairs result = [keypair_to_view(keypair) for keypair in mgr.list(user_id)] parent_href = url_for('users.get_user', user_id=user_id) return make_collection_response('ssh-keys', result, parent_href=parent_href)
def delete_fw_rule_set(fw_rule_set_id): try: sg = admin_client_set().compute.security_groups.get(fw_rule_set_id) assert_admin_or_project_user(sg.tenant_id, eperm_status=404) sg.delete() except osc_exc.NotFound: abort(404) set_audit_resource_id(sg) return make_json_response(None, status_code=204)
def delete_users_ssh_key(user_id, key_name): if user_id != auth.current_user_id(): auth.assert_admin() mgr = auth.admin_client_set().compute_ext.user_keypairs try: mgr.delete(user_id, key_name) except osc_exc.NotFound: abort(404) return make_json_response(None, 204)
def _images_for_tenant(tenant_id, is_public): try: tenant = auth.admin_client_set().identity_admin \ .tenants.get(tenant_id) except osc_exc.NotFound: return [] # consistent with project:eq client = auth.client_set_for_tenant(tenant_id, fallback_to_api=g.is_admin) image_list = client.image.images.list(filters={'is_public': is_public}) return [_image_to_view(image, tenant) for image in image_list]
def _security_groups_for_server(instance_id): try: result = admin_client_set().compute.security_groups._list( '/servers/%s/os-security-groups' % instance_id, 'security_groups') except osc_exc.HttpException: fetch_instance(instance_id) # check that server exists and is visible raise # if server exists, re-raise: it was other error if not result: fetch_instance(instance_id) # check that server exists and is visible else: assert_admin_or_project_user(result[0].tenant_id, eperm_status=404) return result
def create_users_ssh_key(user_id): data = parse_request_data(required=_SCHEMA.required) if user_id != auth.current_user_id(): auth.assert_admin() fetch_user(user_id, g.is_admin) # check that user exists and is visible mgr = auth.admin_client_set().compute_ext.user_keypairs try: kp = mgr.create(user_id, data['name'], data['public-key']) except osc_exc.BadRequest, e: raise exc.InvalidRequest(str(e))
def instance_data_gc(): """Remove instance data for already deleted servers""" server_mgr = admin_client_set().compute.servers for instance_data in InstanceDataDAO.list_all(): try: server_mgr.get(instance_data.instance_id) except osc_exc.NotFound: InstanceDataDAO.delete(instance_data.instance_id) except Exception: current_app.logger.exception('Failed to delete data ' 'for non-existing instance %r' % instance_data.instance_id)
def _images_for_all_tenants(): if g.my_projects: tenants = g.client_set.identity_public.tenants.list() else: tenants = g.client_set.identity_admin.tenants.list() tenant_dict = dict(((tenant.id, tenant) for tenant in tenants)) tenant_dict[auth.default_tenant_id()] = None return [_image_to_view(image, tenant_dict.get(image.owner)) for image in list_all_images(auth.admin_client_set().image.images) if not g.my_projects or image.owner in tenant_dict]
def _images_for_tenant(tenant_id, is_public): try: tenant = auth.admin_client_set().identity_admin \ .tenants.get(tenant_id) except osc_exc.NotFound: return [] # consistent with project:eq client = auth.client_set_for_tenant(tenant_id, fallback_to_api=g.is_admin) image_list = client.image.images.list( filters={'is_public': is_public}) return [_image_to_view(image, tenant) for image in image_list]
def accept_invite(code): data = parse_request_data(_ACCEPT_SCHEMA, _ACCEPT_REQUIRES) invite, user = _invite_and_user(code) data['enabled'] = True try: update_user_data(user, data) user = auth.admin_client_set().identity_admin.users.get(user.id) except osc_exc.NotFound: abort(404) InvitesDAO.complete_for_user(user.id) return make_json_response(user_to_view(user, invite), 200)
def get_tenant(project_id): try: if g.is_admin: tenant = admin_client_set().identity_admin.tenants.get(project_id) else: # NOTE(imelnikov): get does not work for public API tenant = g.client_set.identity_public.tenants.find(id=project_id) except osc_exc.NotFound: abort(404) # systenant is special entity, not a 'project' in Altai sense if tenant.name == app.config['SYSTENANT']: abort(404) return tenant
def _fetch_image(image_id, to_modify): try: image = auth.admin_client_set().image.images.get(image_id) except osc_exc.NotFound: abort(404) # NOTE(imelnikov): yes, glance may return False as string if image.deleted and image.deleted != 'False': abort(404) if image.owner == auth.default_tenant_id(): if to_modify: auth.assert_admin() else: auth.assert_admin_or_project_user(image.owner) return image
def list_fw_rule_sets(): parse_collection_request(_SCHEMA) if g.my_projects: tenants = g.client_set.identity_public.tenants.list() else: tenants = admin_client_set().identity_admin.tenants.list() result = [] for tenant in tenants: if tenant.name != app.config['SYSTENANT']: tcs = client_set_for_tenant(tenant.id, fallback_to_api=g.is_admin) for sg in tcs.compute.security_groups.list(): result.append(_sg_to_view(sg, tenant.name)) return make_collection_response(u'fw-rule-sets', result)
def update_user_data(user, data): fields_to_update = {} for key in ('name', 'email', 'fullname', 'enabled'): if key in data: fields_to_update[key] = data[key] user_mgr = auth.admin_client_set().identity_admin.users try: if fields_to_update: user_mgr.update(user, **fields_to_update) if 'password' in data: user_mgr.update_password(user, data['password']) except osc_exc.NotFound: abort(404)
def _images_for_all_tenants(): if g.my_projects: tenants = g.client_set.identity_public.tenants.list() else: tenants = g.client_set.identity_admin.tenants.list() tenant_dict = dict(((tenant.id, tenant) for tenant in tenants)) tenant_dict[auth.default_tenant_id()] = None return [ _image_to_view(image, tenant_dict.get(image.owner)) for image in list_all_images(auth.admin_client_set().image.images) if not g.my_projects or image.owner in tenant_dict ]
def add_instance_fw_rule_set(instance_id): server = fetch_instance(instance_id) set_id = parse_request_data(required=_SCHEMA.required)['id'] set_audit_resource_id(set_id) try: sg = admin_client_set().compute.security_groups.get(set_id) except osc_exc.NotFound: raise exc.InvalidElementValue('id', 'string', set_id, 'Security group does not exist') tcs = client_set_for_tenant(server.tenant_id, fallback_to_api=g.is_admin) try: tcs.compute.servers.add_security_group(server, sg.name) except osc_exc.BadRequest, e: raise exc.InvalidRequest(str(e))
def link_for_project(project_id, project_name=None): """Make a link object for a project If project_name is not provided, it is looked up in the identity_admin and passes any exception it raises in case of error. """ if project_name is None: try: tenant = admin_client_set().identity_admin.tenants.get(project_id) project_name = tenant.name except osc_exc.NotFound: project_name = None return { u'id': project_id, u'name': project_name, u'href': url_for('projects.get_project', project_id=project_id) }
def rip_expired_instances(): """Run periodically to remove expired instances""" server_mgr = admin_client_set().compute.servers for instance_data in InstanceDataDAO.expired_list(datetime.utcnow()): try: server_mgr.delete(instance_data.instance_id) AuditDAO.create_record(dict( resource=url_for('instances.delete_instance', instance_id=instance_data.instance_id), method='DELETE', response_status=200, message='Automatically deleted expired instance', )) except osc_exc.NotFound: InstanceDataDAO.delete(instance_data.instance_id) except Exception: current_app.logger.exception('Failed to delete expired instance %r' % instance_data.instance_id)
def altai_stats(): cs = auth.admin_client_set() tenants = cs.identity_admin.tenants.list() users = cs.identity_admin.users.list() # TODO(imelnikov): should we ignore servers in systenant? servers = cs.compute.servers.list(search_opts={'all_tenants': 1}) images = list_all_images(cs.image.images) global_images = [image for image in images if image.is_public] return make_json_response({ 'projects': len(tenants) - 1, # not counting systenant 'instances': len(servers), 'users': len(users), 'total-images': len(images), 'global-images': len(global_images), 'by-project-stats-href': url_for('stats.list_stats_by_project') })
def list_stats_by_project(): parse_collection_request(_SCHEMA) cs = auth.admin_client_set() if g.my_projects: tenants = g.client_set.identity_public.tenants.list() else: tenants = cs.identity_admin.tenants.list() result = {} for tenant in tenants: if tenant.id != auth.default_tenant_id(): users = cs.identity_admin.tenants.list_users(tenant.id) result[tenant.id] = { 'project': link_for_tenant(tenant), 'members': len(users), 'instances': 0, 'local-images': 0, 'total-images': 0, 'href': url_for('stats.get_project_stats', project_id=tenant.id) } for server in cs.compute.servers.list(search_opts={'all_tenants': 1}): try: result[server.tenant_id]['instances'] += 1 except KeyError: pass global_images = 0 for image in list_all_images(cs.image.images): if image.is_public: global_images += 1 if image.owner in result: result[image.owner]['local-images'] += 1 if not image.is_public: result[image.owner]['total-images'] += 1 for value in result.itervalues(): value['total-images'] += global_images data = sorted(result.itervalues(), key=lambda s: s['href']) return make_collection_response(u'stats', data, parent_href=url_for('stats.altai_stats'))
def remove_project_user(project_id, user_id): tenant = get_tenant(project_id) if user_id != current_user_id(): assert_admin() try: user_mgr = admin_client_set().identity_admin.users roles = user_mgr.list_roles(user_id, project_id) except osc_exc.NotFound: abort(404) if not roles: abort(404) # user was not member of the project for role in roles: try: tenant.remove_user(user_id, role.id) except osc_exc.NotFound: pass # already deleted by someone else return make_json_response(None, status_code=204)
def rip_expired_instances(): """Run periodically to remove expired instances""" server_mgr = admin_client_set().compute.servers for instance_data in InstanceDataDAO.expired_list(datetime.utcnow()): try: server_mgr.delete(instance_data.instance_id) AuditDAO.create_record( dict( resource=url_for('instances.delete_instance', instance_id=instance_data.instance_id), method='DELETE', response_status=200, message='Automatically deleted expired instance', )) except osc_exc.NotFound: InstanceDataDAO.delete(instance_data.instance_id) except Exception: current_app.logger.exception( 'Failed to delete expired instance %r' % instance_data.instance_id)