e82c7b4336
Signed-off-by: Scott Little <scott.little@windriver.com>
179 lines
6.8 KiB
Python
179 lines
6.8 KiB
Python
# Copyright 2015 Huawei Technologies Co., Ltd.
|
|
# All Rights Reserved
|
|
#
|
|
# 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 collections
|
|
|
|
from keystoneauth1 import loading
|
|
from keystoneauth1 import session
|
|
|
|
from keystoneclient.v3 import client as keystone_client
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
from dcorch.common import consts
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class EndpointCache(object):
|
|
def __init__(self, region_name=None, auth_url=None):
|
|
self.endpoint_map = collections.defaultdict(dict)
|
|
self.admin_session = None
|
|
self.keystone_client = None
|
|
|
|
# if auth_url is provided use that otherwise use the one
|
|
# defined in the config
|
|
if auth_url:
|
|
self.external_auth_url = auth_url
|
|
else:
|
|
self.external_auth_url = cfg.CONF.cache.auth_uri
|
|
|
|
self._initialize_keystone_client(region_name, auth_url)
|
|
|
|
self._update_endpoints()
|
|
|
|
def _initialize_keystone_client(self, region_name=None, auth_url=None):
|
|
loader = loading.get_plugin_loader(
|
|
cfg.CONF.keystone_authtoken.auth_type)
|
|
|
|
auth = loader.load_from_options(
|
|
auth_url=self.external_auth_url,
|
|
username=cfg.CONF.cache.admin_username,
|
|
user_domain_name=cfg.CONF.cache.admin_user_domain_name,
|
|
password=cfg.CONF.cache.admin_password,
|
|
project_name=cfg.CONF.cache.admin_tenant,
|
|
project_domain_name=cfg.CONF.cache.admin_project_domain_name,
|
|
)
|
|
self.admin_session = session.Session(
|
|
auth=auth, additional_headers=consts.USER_HEADER)
|
|
self.keystone_client = keystone_client.Client(
|
|
session=self.admin_session,
|
|
region_name=consts.VIRTUAL_MASTER_CLOUD)
|
|
|
|
# if Endpoint cache is intended for a subcloud then
|
|
# we need to retrieve the subcloud token and session.
|
|
# Skip this if auth_url was provided as its assumed that the
|
|
# auth_url would correspond to a subcloud so session was
|
|
# set up above
|
|
if (not auth_url and region_name and
|
|
region_name not in
|
|
[consts.CLOUD_0, consts.VIRTUAL_MASTER_CLOUD]):
|
|
identity_service = self.keystone_client.services.list(
|
|
name='keystone', type='identity')
|
|
sc_auth_url = self.keystone_client.endpoints.list(
|
|
service=identity_service[0].id,
|
|
interface=consts.KS_ENDPOINT_INTERNAL,
|
|
region=region_name)
|
|
try:
|
|
sc_auth_url = sc_auth_url[0].url
|
|
except IndexError:
|
|
LOG.error("Cannot find identity auth_url for %s", region_name)
|
|
raise
|
|
sc_loader = loading.get_plugin_loader(
|
|
cfg.CONF.keystone_authtoken.auth_type)
|
|
# We assume that the Admin user names and passwords are the same
|
|
# on this subcloud since this is an audited resource
|
|
sc_auth = sc_loader.load_from_options(
|
|
auth_url=sc_auth_url,
|
|
username=cfg.CONF.cache.admin_username,
|
|
user_domain_name=cfg.CONF.cache.admin_user_domain_name,
|
|
password=cfg.CONF.cache.admin_password,
|
|
project_name=cfg.CONF.cache.admin_tenant,
|
|
project_domain_name=cfg.CONF.cache.admin_project_domain_name,
|
|
)
|
|
self.admin_session = session.Session(
|
|
auth=sc_auth, additional_headers=consts.USER_HEADER)
|
|
self.keystone_client = keystone_client.Client(
|
|
session=self.admin_session,
|
|
region_name=region_name)
|
|
self.external_auth_url = sc_auth_url
|
|
|
|
@staticmethod
|
|
def _get_endpoint_from_keystone(self):
|
|
service_id_name_map = {}
|
|
for service in self.keystone_client.services.list():
|
|
service_dict = service.to_dict()
|
|
service_id_name_map[service_dict['id']] = service_dict['name']
|
|
|
|
region_service_endpoint_map = {}
|
|
for endpoint in self.keystone_client.endpoints.list():
|
|
endpoint_dict = endpoint.to_dict()
|
|
if endpoint_dict['interface'] != consts.KS_ENDPOINT_INTERNAL:
|
|
continue
|
|
region_id = endpoint_dict['region']
|
|
service_id = endpoint_dict['service_id']
|
|
url = endpoint_dict['url']
|
|
service_name = service_id_name_map[service_id]
|
|
if region_id not in region_service_endpoint_map:
|
|
region_service_endpoint_map[region_id] = {}
|
|
region_service_endpoint_map[region_id][service_name] = url
|
|
return region_service_endpoint_map
|
|
|
|
def _get_endpoint(self, region, service, retry):
|
|
if service not in self.endpoint_map[region]:
|
|
if retry:
|
|
self.update_endpoints()
|
|
return self._get_endpoint(region, service, False)
|
|
else:
|
|
return ''
|
|
else:
|
|
return self.endpoint_map[region][service]
|
|
|
|
def _update_endpoints(self):
|
|
endpoint_map = EndpointCache._get_endpoint_from_keystone(self)
|
|
|
|
for region in endpoint_map:
|
|
for service in endpoint_map[region]:
|
|
self.endpoint_map[region][
|
|
service] = endpoint_map[region][service]
|
|
|
|
def get_endpoint(self, region, service):
|
|
"""Get service endpoint url.
|
|
|
|
:param region: region the service belongs to
|
|
:param service: service type
|
|
:return: url of the service
|
|
"""
|
|
return self._get_endpoint(region, service, True)
|
|
|
|
def update_endpoints(self):
|
|
"""Update endpoint cache from Keystone.
|
|
|
|
:return: None
|
|
"""
|
|
self._update_endpoints()
|
|
|
|
def get_all_regions(self):
|
|
"""Get region list.
|
|
|
|
return: List of regions
|
|
"""
|
|
return self.endpoint_map.keys()
|
|
|
|
def get_session_from_token(self, token, project_id):
|
|
"""Get session based on token to communicate with openstack services.
|
|
|
|
:param token: token with which the request is triggered.
|
|
:param project_id: UUID of the project.
|
|
|
|
:return: session object.
|
|
"""
|
|
loader = loading.get_plugin_loader('token')
|
|
auth = loader.load_from_options(auth_url=self.external_auth_url,
|
|
token=token, project_id=project_id)
|
|
sess = session.Session(auth=auth)
|
|
return sess
|