Allow storage drivers to add metadata to locations
This patches allows a storage system to add metadata to a location.
For example, if a location is a file:// URL the storage system may
wish to add information about it like the following:
{'FS': Gluster, 'mountpoint': '/usr/local/', 'namespace': 'abc-efg-xyz'}
Such information can be useful to a client with access to the direct
URL (often times the URL alone cannot encode enough information).
With this change when new data is added to the store a dictionary
is returned along with URL. That dictionary is then stored in the
DB with the URL. It is up to each store to determine what is in this
metadata dictionary. Possible way to do so are with a configuration
file. This patch does not included storage systems (other than tests)
that set this information.
If the API service is configured with the follow options:
show_multiple_locations = True
then the location and the location information is returned with the
image information in the field 'locations'. locations is
a list with the following format:
{'url': '<url>', 'metadata': <a storage specific dict>}
With this patch it will always be a list of one, but future patches
relating to the blueprint multiple-image-locations will allow for more.
blueprint: direct-url-meta-data
blueprint: multiple-image-locations
docimpact: show_multiple_locations
Change-Id: Ia832b8a8366bb06bfbaa53871af39a6a10b5721d
This commit is contained in:
@@ -52,6 +52,42 @@ SUPPORTED_SORT_DIRS = ('asc', 'desc')
|
||||
SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
|
||||
|
||||
|
||||
def _normalize_image_location_for_db(image_data):
|
||||
"""
|
||||
This function takes the legacy locations field and the newly added
|
||||
location_data field from the image_data values dictionary which flows
|
||||
over the wire between the registry and API servers and converts it
|
||||
into the location_data format only which is then consumable by the
|
||||
Image object.
|
||||
|
||||
:param image_data: a dict of values representing information in the image
|
||||
:return: a new image data dict
|
||||
"""
|
||||
if 'locations' not in image_data and 'location_data' not in image_data:
|
||||
image_data['locations'] = None
|
||||
return image_data
|
||||
|
||||
locations = image_data.pop('locations', [])
|
||||
location_data = image_data.pop('location_data', [])
|
||||
|
||||
location_data_dict = {}
|
||||
for l in locations:
|
||||
location_data_dict[l] = {}
|
||||
for l in location_data:
|
||||
location_data_dict[l['url']] = l['metadata']
|
||||
|
||||
# NOTE(jbresnah) preserve original order. tests assume original order,
|
||||
# should that be defined functionality
|
||||
ordered_keys = locations[:]
|
||||
for ld in location_data:
|
||||
if ld['url'] not in ordered_keys:
|
||||
ordered_keys.append(ld['url'])
|
||||
location_data = [{'url': l, 'metadata': location_data_dict[l]}
|
||||
for l in ordered_keys]
|
||||
image_data['locations'] = location_data
|
||||
return image_data
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
@@ -359,6 +395,7 @@ class Controller(object):
|
||||
image_data['locations'] = [image_data.pop('location')]
|
||||
|
||||
try:
|
||||
image_data = _normalize_image_location_for_db(image_data)
|
||||
image_data = self.db_api.image_create(req.context, image_data)
|
||||
msg = _("Successfully created image %(id)s")
|
||||
LOG.info(msg % {'id': image_id})
|
||||
@@ -397,6 +434,7 @@ class Controller(object):
|
||||
try:
|
||||
LOG.debug(_("Updating image %(id)s with metadata: "
|
||||
"%(image_data)r") % locals())
|
||||
image_data = _normalize_image_location_for_db(image_data)
|
||||
if purge_props == "true":
|
||||
updated_image = self.db_api.image_update(req.context, id,
|
||||
image_data, True)
|
||||
@@ -434,9 +472,10 @@ class Controller(object):
|
||||
def _limit_locations(image):
|
||||
locations = image.pop('locations', [])
|
||||
try:
|
||||
image['location'] = locations[0]
|
||||
image['location'] = locations[0]['url']
|
||||
except IndexError:
|
||||
image['location'] = None
|
||||
image['location_data'] = locations
|
||||
|
||||
|
||||
def make_image_dict(image):
|
||||
|
||||
Reference in New Issue
Block a user