OpenStack Image Management (Glance)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

store_utils.py 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # Copyright 2014 IBM Corp.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. # not use this file except in compliance with the License. You may obtain
  5. # a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. # License for the specific language governing permissions and limitations
  13. # under the License.
  14. import sys
  15. import glance_store as store_api
  16. from oslo_config import cfg
  17. from oslo_log import log as logging
  18. from oslo_utils import encodeutils
  19. import six.moves.urllib.parse as urlparse
  20. import glance.db as db_api
  21. from glance.i18n import _LE, _LW
  22. from glance import scrubber
  23. LOG = logging.getLogger(__name__)
  24. CONF = cfg.CONF
  25. CONF.import_opt('use_user_token', 'glance.registry.client')
  26. RESTRICTED_URI_SCHEMAS = frozenset(['file', 'filesystem', 'swift+config'])
  27. def safe_delete_from_backend(context, image_id, location):
  28. """
  29. Given a location, delete an image from the store and
  30. update location status to db.
  31. This function try to handle all known exceptions which might be raised
  32. by those calls on store and DB modules in its implementation.
  33. :param context: The request context
  34. :param image_id: The image identifier
  35. :param location: The image location entry
  36. """
  37. try:
  38. ret = store_api.delete_from_backend(location['url'], context=context)
  39. location['status'] = 'deleted'
  40. if 'id' in location:
  41. db_api.get_api().image_location_delete(context, image_id,
  42. location['id'], 'deleted')
  43. return ret
  44. except store_api.NotFound:
  45. msg = _LW('Failed to delete image %s in store from URI') % image_id
  46. LOG.warn(msg)
  47. except store_api.StoreDeleteNotSupported as e:
  48. LOG.warn(encodeutils.exception_to_unicode(e))
  49. except store_api.UnsupportedBackend:
  50. exc_type = sys.exc_info()[0].__name__
  51. msg = (_LE('Failed to delete image %(image_id)s from store: %(exc)s') %
  52. dict(image_id=image_id, exc=exc_type))
  53. LOG.error(msg)
  54. def schedule_delayed_delete_from_backend(context, image_id, location):
  55. """
  56. Given a location, schedule the deletion of an image location and
  57. update location status to db.
  58. :param context: The request context
  59. :param image_id: The image identifier
  60. :param location: The image location entry
  61. """
  62. db_queue = scrubber.get_scrub_queue()
  63. if not CONF.use_user_token:
  64. context = None
  65. ret = db_queue.add_location(image_id, location)
  66. if ret:
  67. location['status'] = 'pending_delete'
  68. if 'id' in location:
  69. # NOTE(zhiyan): New added image location entry will has no 'id'
  70. # field since it has not been saved to DB.
  71. db_api.get_api().image_location_delete(context, image_id,
  72. location['id'],
  73. 'pending_delete')
  74. else:
  75. db_api.get_api().image_location_add(context, image_id, location)
  76. return ret
  77. def delete_image_location_from_backend(context, image_id, location):
  78. """
  79. Given a location, immediately or schedule the deletion of an image
  80. location and update location status to db.
  81. :param context: The request context
  82. :param image_id: The image identifier
  83. :param location: The image location entry
  84. """
  85. deleted = False
  86. if CONF.delayed_delete:
  87. deleted = schedule_delayed_delete_from_backend(context,
  88. image_id, location)
  89. if not deleted:
  90. # NOTE(zhiyan) If image metadata has not been saved to DB
  91. # such as uploading process failure then we can't use
  92. # location status mechanism to support image pending delete.
  93. safe_delete_from_backend(context, image_id, location)
  94. def validate_external_location(uri):
  95. """
  96. Validate if URI of external location are supported.
  97. Only over non-local store types are OK, i.e. Swift,
  98. HTTP. Note the absence of 'file://' for security reasons,
  99. see LP bug #942118, 1400966, 'swift+config://' is also
  100. absent for security reasons, see LP bug #1334196.
  101. :param uri: The URI of external image location.
  102. :returns: Whether given URI of external image location are OK.
  103. """
  104. if not uri:
  105. return False
  106. # TODO(zhiyan): This function could be moved to glance_store.
  107. # TODO(gm): Use a whitelist of allowed schemes
  108. scheme = urlparse.urlparse(uri).scheme
  109. return (scheme in store_api.get_known_schemes() and
  110. scheme not in RESTRICTED_URI_SCHEMAS)