keystone  18.0.0
About: OpenStack Keystone (Core Service: Identity) provides an authentication and authorization service for other OpenStack services. Provides a catalog of endpoints for all OpenStack services.
The "Victoria" series (maintained release).
  Fossies Dox: keystone-18.0.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

core.py
Go to the documentation of this file.
1 # Copyright 2012 OpenStack Foundation
2 # Copyright 2012 Canonical Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15 
16 """Main entry point into the Catalog service."""
17 
18 from keystone.common import cache
19 from keystone.common import driver_hints
20 from keystone.common import manager
21 from keystone.common import provider_api
22 import keystone.conf
23 from keystone import exception
24 from keystone.i18n import _
25 from keystone import notifications
26 
27 
28 CONF = keystone.conf.CONF
29 PROVIDERS = provider_api.ProviderAPIs
30 
31 
32 # This is a general cache region for catalog administration (CRUD operations).
33 MEMOIZE = cache.get_memoization_decorator(group='catalog')
34 
35 # This builds a discrete cache region dedicated to complete service catalogs
36 # computed for a given user + project pair. Any write operation to create,
37 # modify or delete elements of the service catalog should invalidate this
38 # entire cache region.
39 COMPUTED_CATALOG_REGION = cache.create_region(name='computed catalog region')
40 MEMOIZE_COMPUTED_CATALOG = cache.get_memoization_decorator(
41  group='catalog',
42  region=COMPUTED_CATALOG_REGION)
43 
44 
45 class Manager(manager.Manager):
46  """Default pivot point for the Catalog backend.
47 
48  See :mod:`keystone.common.manager.Manager` for more details on how this
49  dynamically calls the backend.
50 
51  """
52 
53  driver_namespace = 'keystone.catalog'
54  _provides_api = 'catalog_api'
55 
56  _ENDPOINT = 'endpoint'
57  _SERVICE = 'service'
58  _REGION = 'region'
59 
60  def __init__(self):
61  super(Manager, self).__init__(CONF.catalog.driver)
62  notifications.register_event_callback(
63  notifications.ACTIONS.deleted, 'project',
65  notifications.register_event_callback(
66  notifications.ACTIONS.deleted, 'endpoint',
68 
69  def _on_project_or_endpoint_delete(self, service, resource_type, operation,
70  payload):
71  project_or_endpoint_id = payload['resource_info']
72  if resource_type == 'project':
73  PROVIDERS.catalog_api.delete_association_by_project(
74  project_or_endpoint_id)
75  PROVIDERS.catalog_api.delete_endpoint_group_association_by_project(
76  project_or_endpoint_id)
77  else:
78  PROVIDERS.catalog_api.delete_association_by_endpoint(
79  project_or_endpoint_id)
80 
81  def create_region(self, region_ref, initiator=None):
82  # Check duplicate ID
83  try:
84  self.get_region(region_ref['id'])
85  except exception.RegionNotFound: # nosec
86  # A region with the same id doesn't exist already, good.
87  pass
88  else:
89  msg = _('Duplicate ID, %s.') % region_ref['id']
90  raise exception.Conflict(type='region', details=msg)
91 
92  # NOTE(lbragstad,dstanek): The description column of the region
93  # database cannot be null. So if the user doesn't pass in a
94  # description or passes in a null description then set it to an
95  # empty string.
96  if region_ref.get('description') is None:
97  region_ref['description'] = ''
98  try:
99  ret = self.driver.create_region(region_ref)
100  except exception.NotFound:
101  parent_region_id = region_ref.get('parent_region_id')
102  raise exception.RegionNotFound(region_id=parent_region_id)
103 
104  notifications.Audit.created(self._REGION, ret['id'], initiator)
105  COMPUTED_CATALOG_REGION.invalidate()
106  return ret
107 
108  @MEMOIZE
109  def get_region(self, region_id):
110  try:
111  return self.driver.get_region(region_id)
112  except exception.NotFound:
113  raise exception.RegionNotFound(region_id=region_id)
114 
115  def update_region(self, region_id, region_ref, initiator=None):
116  # NOTE(lbragstad,dstanek): The description column of the region
117  # database cannot be null. So if the user passes in a null
118  # description set it to an empty string.
119  if 'description' in region_ref and region_ref['description'] is None:
120  region_ref['description'] = ''
121  ref = self.driver.update_region(region_id, region_ref)
122  notifications.Audit.updated(self._REGION, region_id, initiator)
123  self.get_region.invalidate(self, region_id)
124  COMPUTED_CATALOG_REGION.invalidate()
125  return ref
126 
127  def delete_region(self, region_id, initiator=None):
128  try:
129  ret = self.driver.delete_region(region_id)
130  notifications.Audit.deleted(self._REGION, region_id, initiator)
131  self.get_region.invalidate(self, region_id)
132  COMPUTED_CATALOG_REGION.invalidate()
133  return ret
134  except exception.NotFound:
135  raise exception.RegionNotFound(region_id=region_id)
136 
137  @manager.response_truncated
138  def list_regions(self, hints=None):
139  return self.driver.list_regions(hints or driver_hints.Hints())
140 
141  def create_service(self, service_id, service_ref, initiator=None):
142  service_ref.setdefault('enabled', True)
143  service_ref.setdefault('name', '')
144  ref = self.driver.create_service(service_id, service_ref)
145  notifications.Audit.created(self._SERVICE, service_id, initiator)
146  COMPUTED_CATALOG_REGION.invalidate()
147  return ref
148 
149  @MEMOIZE
150  def get_service(self, service_id):
151  try:
152  return self.driver.get_service(service_id)
153  except exception.NotFound:
154  raise exception.ServiceNotFound(service_id=service_id)
155 
156  def update_service(self, service_id, service_ref, initiator=None):
157  ref = self.driver.update_service(service_id, service_ref)
158  notifications.Audit.updated(self._SERVICE, service_id, initiator)
159  self.get_service.invalidate(self, service_id)
160  COMPUTED_CATALOG_REGION.invalidate()
161  return ref
162 
163  def delete_service(self, service_id, initiator=None):
164  try:
165  endpoints = self.list_endpoints()
166  ret = self.driver.delete_service(service_id)
167  notifications.Audit.deleted(self._SERVICE, service_id, initiator)
168  self.get_service.invalidate(self, service_id)
169  for endpoint in endpoints:
170  if endpoint['service_id'] == service_id:
171  self.get_endpoint.invalidate(self, endpoint['id'])
172  COMPUTED_CATALOG_REGION.invalidate()
173  return ret
174  except exception.NotFound:
175  raise exception.ServiceNotFound(service_id=service_id)
176 
177  @manager.response_truncated
178  def list_services(self, hints=None):
179  return self.driver.list_services(hints or driver_hints.Hints())
180 
181  def _assert_region_exists(self, region_id):
182  try:
183  if region_id is not None:
184  self.get_region(region_id)
186  raise exception.ValidationError(attribute='endpoint region_id',
187  target='region table')
188 
189  def _assert_service_exists(self, service_id):
190  try:
191  if service_id is not None:
192  self.get_service(service_id)
194  raise exception.ValidationError(attribute='endpoint service_id',
195  target='service table')
196 
197  def create_endpoint(self, endpoint_id, endpoint_ref, initiator=None):
198  self._assert_region_exists(endpoint_ref.get('region_id'))
199  self._assert_service_exists(endpoint_ref['service_id'])
200  ref = self.driver.create_endpoint(endpoint_id, endpoint_ref)
201 
202  notifications.Audit.created(self._ENDPOINT, endpoint_id, initiator)
203  COMPUTED_CATALOG_REGION.invalidate()
204  return ref
205 
206  def update_endpoint(self, endpoint_id, endpoint_ref, initiator=None):
207  self._assert_region_exists(endpoint_ref.get('region_id'))
208  self._assert_service_exists(endpoint_ref.get('service_id'))
209  ref = self.driver.update_endpoint(endpoint_id, endpoint_ref)
210  notifications.Audit.updated(self._ENDPOINT, endpoint_id, initiator)
211  self.get_endpoint.invalidate(self, endpoint_id)
212  COMPUTED_CATALOG_REGION.invalidate()
213  return ref
214 
215  def delete_endpoint(self, endpoint_id, initiator=None):
216  try:
217  ret = self.driver.delete_endpoint(endpoint_id)
218  notifications.Audit.deleted(self._ENDPOINT, endpoint_id, initiator)
219  self.get_endpoint.invalidate(self, endpoint_id)
220  COMPUTED_CATALOG_REGION.invalidate()
221  return ret
222  except exception.NotFound:
223  raise exception.EndpointNotFound(endpoint_id=endpoint_id)
224 
225  @MEMOIZE
226  def get_endpoint(self, endpoint_id):
227  try:
228  return self.driver.get_endpoint(endpoint_id)
229  except exception.NotFound:
230  raise exception.EndpointNotFound(endpoint_id=endpoint_id)
231 
232  @manager.response_truncated
233  def list_endpoints(self, hints=None):
234  return self.driver.list_endpoints(hints or driver_hints.Hints())
235 
236  @MEMOIZE_COMPUTED_CATALOG
237  def get_v3_catalog(self, user_id, project_id):
238  return self.driver.get_v3_catalog(user_id, project_id)
239 
240  def add_endpoint_to_project(self, endpoint_id, project_id):
241  self.driver.add_endpoint_to_project(endpoint_id, project_id)
242  COMPUTED_CATALOG_REGION.invalidate()
243 
244  def remove_endpoint_from_project(self, endpoint_id, project_id):
245  self.driver.remove_endpoint_from_project(endpoint_id, project_id)
246  COMPUTED_CATALOG_REGION.invalidate()
247 
248  def add_endpoint_group_to_project(self, endpoint_group_id, project_id):
249  self.driver.add_endpoint_group_to_project(
250  endpoint_group_id, project_id)
251  COMPUTED_CATALOG_REGION.invalidate()
252 
253  def remove_endpoint_group_from_project(self, endpoint_group_id,
254  project_id):
256  endpoint_group_id, project_id)
257  COMPUTED_CATALOG_REGION.invalidate()
258 
260  try:
262  project_id)
264  # Some catalog drivers don't support this
265  pass
266 
267  def get_endpoint_groups_for_project(self, project_id):
268  # recover the project endpoint group memberships and for each
269  # membership recover the endpoint group
270  PROVIDERS.resource_api.get_project(project_id)
271  try:
272  refs = self.list_endpoint_groups_for_project(project_id)
273  endpoint_groups = [self.get_endpoint_group(
274  ref['endpoint_group_id']) for ref in refs]
275  return endpoint_groups
277  return []
278 
279  def get_endpoints_filtered_by_endpoint_group(self, endpoint_group_id):
280  endpoints = self.list_endpoints()
281  filters = self.get_endpoint_group(endpoint_group_id)['filters']
282  filtered_endpoints = []
283 
284  for endpoint in endpoints:
285  is_candidate = True
286  for key, value in filters.items():
287  if endpoint[key] != value:
288  is_candidate = False
289  break
290  if is_candidate:
291  filtered_endpoints.append(endpoint)
292  return filtered_endpoints
293 
294  def list_endpoints_for_project(self, project_id):
295  """List all endpoints associated with a project.
296 
297  :param project_id: project identifier to check
298  :type project_id: string
299  :returns: a list of endpoint ids or an empty list.
300 
301  """
302  refs = self.driver.list_endpoints_for_project(project_id)
303  filtered_endpoints = {}
304  for ref in refs:
305  try:
306  endpoint = self.get_endpoint(ref['endpoint_id'])
307  filtered_endpoints.update({ref['endpoint_id']: endpoint})
309  # remove bad reference from association
310  self.remove_endpoint_from_project(ref['endpoint_id'],
311  project_id)
312 
313  # need to recover endpoint_groups associated with project
314  # then for each endpoint group return the endpoints.
315  endpoint_groups = self.get_endpoint_groups_for_project(project_id)
316  for endpoint_group in endpoint_groups:
317  endpoint_refs = self.get_endpoints_filtered_by_endpoint_group(
318  endpoint_group['id'])
319  # now check if any endpoints for current endpoint group are not
320  # contained in the list of filtered endpoints
321  for endpoint_ref in endpoint_refs:
322  if endpoint_ref['id'] not in filtered_endpoints:
323  filtered_endpoints[endpoint_ref['id']] = endpoint_ref
324 
325  return filtered_endpoints
326 
327  def delete_association_by_endpoint(self, endpoint_id):
328  try:
329  self.driver.delete_association_by_endpoint(endpoint_id)
331  # Some catalog drivers don't support this
332  pass
333 
334  def delete_association_by_project(self, project_id):
335  try:
336  self.driver.delete_association_by_project(project_id)
338  # Some catalog drivers don't support this
339  pass
keystone.catalog.core.Manager.list_endpoints
def list_endpoints(self, hints=None)
Definition: core.py:233
keystone.exception.RegionNotFound
Definition: exception.py:445
keystone.catalog.core.Manager.update_endpoint
def update_endpoint(self, endpoint_id, endpoint_ref, initiator=None)
Definition: core.py:206
keystone.catalog.core.Manager.get_region
def get_region(self, region_id)
Definition: core.py:109
keystone.catalog.core.Manager.create_endpoint
def create_endpoint(self, endpoint_id, endpoint_ref, initiator=None)
Definition: core.py:197
keystone.catalog.core.Manager.delete_association_by_endpoint
def delete_association_by_endpoint(self, endpoint_id)
Definition: core.py:327
keystone.catalog.core.Manager.delete_region
def delete_region(self, region_id, initiator=None)
Definition: core.py:127
keystone.catalog.core.Manager._SERVICE
string _SERVICE
Definition: core.py:57
keystone.catalog.core.Manager.get_v3_catalog
def get_v3_catalog(self, user_id, project_id)
Definition: core.py:237
keystone.exception.NotFound
Definition: exception.py:395
keystone.catalog.core.Manager._REGION
string _REGION
Definition: core.py:58
keystone.catalog.core.Manager
Definition: core.py:45
keystone.catalog.core.Manager.create_service
def create_service(self, service_id, service_ref, initiator=None)
Definition: core.py:141
keystone.exception.ValidationError
Definition: exception.py:98
keystone.catalog.core.Manager._ENDPOINT
string _ENDPOINT
Definition: core.py:56
keystone.catalog.core.Manager.update_region
def update_region(self, region_id, region_ref, initiator=None)
Definition: core.py:115
keystone.exception.ServiceNotFound
Definition: exception.py:449
keystone.catalog.core.Manager._assert_region_exists
def _assert_region_exists(self, region_id)
Definition: core.py:181
keystone.catalog.core.Manager.remove_endpoint_from_project
def remove_endpoint_from_project(self, endpoint_id, project_id)
Definition: core.py:244
keystone.catalog.core.Manager.add_endpoint_to_project
def add_endpoint_to_project(self, endpoint_id, project_id)
Definition: core.py:240
keystone.catalog.core.Manager.list_endpoints_for_project
def list_endpoints_for_project(self, project_id)
Definition: core.py:294
keystone.catalog.core.Manager.delete_endpoint
def delete_endpoint(self, endpoint_id, initiator=None)
Definition: core.py:215
keystone.exception.Conflict
Definition: exception.py:559
keystone.catalog.core.Manager.delete_association_by_project
def delete_association_by_project(self, project_id)
Definition: core.py:334
keystone.exception.EndpointNotFound
Definition: exception.py:401
keystone.catalog.core.Manager._on_project_or_endpoint_delete
def _on_project_or_endpoint_delete(self, service, resource_type, operation, payload)
Definition: core.py:70
keystone.catalog.core.Manager.get_endpoint
def get_endpoint(self, endpoint_id)
Definition: core.py:226
keystone.catalog.core.Manager.delete_service
def delete_service(self, service_id, initiator=None)
Definition: core.py:163
keystone.conf
Definition: __init__.py:1
keystone.exception.NotImplemented
Definition: exception.py:621
keystone.i18n._
_
Definition: i18n.py:29
keystone.catalog.core.Manager.list_regions
def list_regions(self, hints=None)
Definition: core.py:138
keystone.exception.EndpointGroupNotFound
Definition: exception.py:497
keystone.catalog.core.Manager.update_service
def update_service(self, service_id, service_ref, initiator=None)
Definition: core.py:156
keystone.catalog.core.Manager.delete_endpoint_group_association_by_project
def delete_endpoint_group_association_by_project(self, project_id)
Definition: core.py:259
keystone.catalog.core.Manager.get_endpoints_filtered_by_endpoint_group
def get_endpoints_filtered_by_endpoint_group(self, endpoint_group_id)
Definition: core.py:279
keystone.catalog.core.Manager.get_service
def get_service(self, service_id)
Definition: core.py:150
keystone.common
Definition: __init__.py:1
keystone.i18n
Definition: i18n.py:1
keystone.catalog.core.Manager.add_endpoint_group_to_project
def add_endpoint_group_to_project(self, endpoint_group_id, project_id)
Definition: core.py:248
keystone.catalog.core.Manager.__init__
def __init__(self)
Definition: core.py:60
keystone.catalog.core.Manager.get_endpoint_groups_for_project
def get_endpoint_groups_for_project(self, project_id)
Definition: core.py:267
keystone.catalog.core.Manager.list_services
def list_services(self, hints=None)
Definition: core.py:178
keystone.catalog.core.Manager.create_region
def create_region(self, region_ref, initiator=None)
Definition: core.py:81
keystone.catalog.core.Manager._assert_service_exists
def _assert_service_exists(self, service_id)
Definition: core.py:189
keystone.catalog.core.Manager.remove_endpoint_group_from_project
def remove_endpoint_group_from_project(self, endpoint_group_id, project_id)
Definition: core.py:254