277 lines
10 KiB
Python
277 lines
10 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2011 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
#
|
|
# Copyright 2011 Nebula, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import logging
|
|
|
|
from django.conf import settings
|
|
|
|
from keystoneclient import exceptions as keystone_exceptions
|
|
from keystoneclient import service_catalog
|
|
from keystoneclient.v2_0 import client as keystone_client
|
|
from keystoneclient.v2_0 import tokens
|
|
|
|
from horizon.api.base import *
|
|
from horizon.api.deprecated import admin_api
|
|
from horizon.api.deprecated import check_openstackx
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class Tenant(APIResourceWrapper):
|
|
"""Simple wrapper around keystoneclient.tenants.Tenant"""
|
|
_attrs = ['id', 'description', 'enabled', 'name']
|
|
|
|
|
|
class Token(APIResourceWrapper):
|
|
"""Simple wrapper around keystoneclient.tokens.Tenant"""
|
|
_attrs = ['id', 'user', 'serviceCatalog', 'tenant']
|
|
|
|
|
|
class User(APIResourceWrapper):
|
|
"""Simple wrapper around keystoneclient.users.User"""
|
|
_attrs = ['email', 'enabled', 'id', 'tenantId', 'name']
|
|
|
|
|
|
class Role(APIResourceWrapper):
|
|
"""Wrapper around keystoneclient.roles.role"""
|
|
_attrs = ['id', 'name', 'description', 'service_id']
|
|
|
|
|
|
class Services(APIResourceWrapper):
|
|
_attrs = ['disabled', 'host', 'id', 'last_update', 'stats', 'type', 'up',
|
|
'zone']
|
|
|
|
|
|
def keystoneclient(request, username=None, password=None, tenant_id=None,
|
|
token_id=None, endpoint=None, endpoint_type=None):
|
|
"""Returns a client connected to the Keystone backend.
|
|
|
|
Several forms of authentication are supported:
|
|
|
|
* Username + password -> Unscoped authentication
|
|
* Username + password + tenant id -> Scoped authentication
|
|
* Unscoped token -> Unscoped authentication
|
|
* Unscoped token + tenant id -> Scoped authentication
|
|
* Scoped token -> Scoped authentication
|
|
|
|
Available services and data from the backend will vary depending on
|
|
whether the authentication was scoped or unscoped.
|
|
|
|
Lazy authentication if an ``endpoint`` parameter is provided.
|
|
|
|
The client is cached so that subsequent API calls during the same
|
|
request/response cycle don't have to be re-authenticated.
|
|
"""
|
|
# Take care of client connection caching/fetching a new client
|
|
user = request.user
|
|
if hasattr(request, '_keystone') and \
|
|
request._keystone.auth_token == user.token:
|
|
LOG.debug("Using cached client for token: %s" % user.token)
|
|
conn = request._keystone
|
|
else:
|
|
LOG.debug("Creating a new client connection with endpoint: %s."
|
|
% endpoint)
|
|
conn = keystone_client.Client(username=username or user.username,
|
|
password=password,
|
|
project_id=tenant_id or user.tenant_id,
|
|
token=token_id or user.token,
|
|
auth_url=settings.OPENSTACK_KEYSTONE_URL,
|
|
endpoint=endpoint)
|
|
request._keystone = conn
|
|
|
|
# Fetch the correct endpoint for the user type
|
|
catalog = getattr(conn, 'service_catalog', None)
|
|
if catalog and "serviceCatalog" in catalog.catalog.keys():
|
|
if endpoint_type:
|
|
endpoint = catalog.url_for(service_type='identity',
|
|
endpoint_type=endpoint_type)
|
|
elif user.is_admin():
|
|
endpoint = catalog.url_for(service_type='identity',
|
|
endpoint_type='adminURL')
|
|
else:
|
|
endpoint = catalog.url_for(service_type='identity',
|
|
endpoint_type='publicURL')
|
|
else:
|
|
endpoint = settings.OPENSTACK_KEYSTONE_URL
|
|
conn.management_url = endpoint
|
|
|
|
return conn
|
|
|
|
|
|
def tenant_create(request, tenant_name, description, enabled):
|
|
return Tenant(keystoneclient(request).tenants.create(tenant_name,
|
|
description,
|
|
enabled))
|
|
|
|
|
|
def tenant_get(request, tenant_id):
|
|
return Tenant(keystoneclient(request).tenants.get(tenant_id))
|
|
|
|
|
|
def tenant_delete(request, tenant_id):
|
|
keystoneclient(request).tenants.delete(tenant_id)
|
|
|
|
|
|
def tenant_list(request):
|
|
return [Tenant(t) for t in keystoneclient(request).tenants.list()]
|
|
|
|
|
|
def tenant_update(request, tenant_id, tenant_name, description, enabled):
|
|
return Tenant(keystoneclient(request).tenants.update(tenant_id,
|
|
tenant_name,
|
|
description,
|
|
enabled))
|
|
|
|
|
|
def tenant_delete(request, tenant_id):
|
|
keystoneclient(request).tenants.delete(tenant_id)
|
|
|
|
|
|
def tenant_list_for_token(request, token, endpoint_type=None):
|
|
c = keystoneclient(request,
|
|
token_id=token,
|
|
endpoint=settings.OPENSTACK_KEYSTONE_URL,
|
|
endpoint_type=endpoint_type)
|
|
return [Tenant(t) for t in c.tenants.list()]
|
|
|
|
|
|
def token_create(request, tenant, username, password):
|
|
'''
|
|
Creates a token using the username and password provided. If tenant
|
|
is provided it will retrieve a scoped token and the service catalog for
|
|
the given tenant. Otherwise it will return an unscoped token and without
|
|
a service catalog.
|
|
'''
|
|
c = keystoneclient(request,
|
|
username=username,
|
|
password=password,
|
|
tenant_id=tenant,
|
|
endpoint=settings.OPENSTACK_KEYSTONE_URL)
|
|
token = c.tokens.authenticate(username=username,
|
|
password=password,
|
|
tenant=tenant)
|
|
return Token(token)
|
|
|
|
|
|
def token_create_scoped(request, tenant, token):
|
|
'''
|
|
Creates a scoped token using the tenant id and unscoped token; retrieves
|
|
the service catalog for the given tenant.
|
|
'''
|
|
if hasattr(request, '_keystone'):
|
|
del request._keystone
|
|
c = keystoneclient(request, tenant_id=tenant, token_id=token,
|
|
endpoint=settings.OPENSTACK_KEYSTONE_URL)
|
|
raw_token = c.tokens.authenticate(tenant=tenant,
|
|
token=token,
|
|
return_raw=True)
|
|
c.service_catalog = service_catalog.ServiceCatalog(raw_token)
|
|
if request.user.is_admin():
|
|
c.management_url = c.service_catalog.url_for(service_type='identity',
|
|
endpoint_type='adminURL')
|
|
else:
|
|
c.management_url = c.service_catalog.url_for(service_type='identity',
|
|
endpoint_type='publicURL')
|
|
scoped_token = tokens.Token(tokens.TokenManager, raw_token)
|
|
return Token(scoped_token)
|
|
|
|
|
|
def user_list(request, tenant_id=None):
|
|
return [User(u) for u in
|
|
keystoneclient(request).users.list(tenant_id=tenant_id)]
|
|
|
|
|
|
def user_create(request, user_id, email, password, tenant_id, enabled):
|
|
return User(keystoneclient(request).users.create(
|
|
user_id, password, email, tenant_id, enabled))
|
|
|
|
|
|
def user_delete(request, user_id):
|
|
keystoneclient(request).users.delete(user_id)
|
|
|
|
|
|
def user_get(request, user_id):
|
|
return User(keystoneclient(request).users.get(user_id))
|
|
|
|
|
|
def user_update_email(request, user_id, email):
|
|
return User(keystoneclient(request).users.update_email(user_id, email))
|
|
|
|
|
|
def user_update_enabled(request, user_id, enabled):
|
|
return User(keystoneclient(request).users.update_enabled(user_id, enabled))
|
|
|
|
|
|
def user_update_password(request, user_id, password):
|
|
return User(keystoneclient(request).users \
|
|
.update_password(user_id, password))
|
|
|
|
|
|
def user_update_tenant(request, user_id, tenant_id):
|
|
return User(keystoneclient(request).users \
|
|
.update_tenant(user_id, tenant_id))
|
|
|
|
|
|
def _get_role(request, name):
|
|
roles = keystoneclient(request).roles.list()
|
|
for role in roles:
|
|
if role.name.lower() == name.lower():
|
|
return role
|
|
|
|
raise Exception(_('Role does not exist: %s') % name)
|
|
|
|
|
|
def _get_roleref(request, user_id, tenant_id, role):
|
|
rolerefs = keystoneclient(request).roles.get_user_role_refs(user_id)
|
|
for roleref in rolerefs:
|
|
if roleref.roleId == role.id and roleref.tenantId == tenant_id:
|
|
return roleref
|
|
raise Exception(_('Role "%s" does not exist for that user on this tenant.')
|
|
% role.name)
|
|
|
|
|
|
def role_add_for_tenant_user(request, tenant_id, user_id, role):
|
|
role = _get_role(request, role)
|
|
return keystoneclient(request).roles.add_user_to_tenant(tenant_id,
|
|
user_id,
|
|
role.id)
|
|
|
|
|
|
def role_delete_for_tenant_user(request, tenant_id, user_id, role):
|
|
role = _get_role(request, role)
|
|
roleref = _get_roleref(request, user_id, tenant_id, role)
|
|
return keystoneclient(request).roles.remove_user_from_tenant(tenant_id,
|
|
user_id,
|
|
roleref.id)
|
|
|
|
|
|
def service_get(request, name):
|
|
return Services(admin_api(request).services.get(name))
|
|
|
|
|
|
@check_openstackx
|
|
def service_list(request):
|
|
return [Services(s) for s in admin_api(request).services.list()]
|
|
|
|
|
|
def service_update(request, name, enabled):
|
|
return Services(admin_api(request).services.update(name, enabled))
|