121 lines
4.1 KiB
Python
121 lines
4.1 KiB
Python
# Copyright 2014 IBM Corp.
|
|
# 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.
|
|
|
|
"""Storage preference based location strategy module"""
|
|
|
|
from oslo_config import cfg
|
|
import six
|
|
import six.moves.urllib.parse as urlparse
|
|
|
|
from glance import i18n
|
|
|
|
_ = i18n._
|
|
|
|
store_type_opts = [
|
|
cfg.ListOpt("store_type_preference",
|
|
default=[],
|
|
help=_("The store names to use to get store preference order. "
|
|
"The name must be registered by one of the stores "
|
|
"defined by the 'known_stores' config option. "
|
|
"This option will be applied when you using "
|
|
"'store_type' option as image location strategy "
|
|
"defined by the 'location_strategy' config option."))
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(store_type_opts, group='store_type_location_strategy')
|
|
|
|
_STORE_TO_SCHEME_MAP = {}
|
|
|
|
|
|
def get_strategy_name():
|
|
"""Return strategy module name."""
|
|
return 'store_type'
|
|
|
|
|
|
def init():
|
|
"""Initialize strategy module."""
|
|
# NOTE(zhiyan): We have a plan to do a reusable glance client library for
|
|
# all clients like Nova and Cinder in near period, it would be able to
|
|
# contains common code to provide uniform image service interface for them,
|
|
# just like Brick in Cinder, this code can be moved to there and shared
|
|
# between Glance and client both side. So this implementation as far as
|
|
# possible to prevent make relationships with Glance(server)-specific code,
|
|
# for example: using functions within store module to validate
|
|
# 'store_type_preference' option.
|
|
mapping = {'filesystem': ['file', 'filesystem'],
|
|
'http': ['http', 'https'],
|
|
'rbd': ['rbd'],
|
|
's3': ['s3', 's3+http', 's3+https'],
|
|
'swift': ['swift', 'swift+https', 'swift+http'],
|
|
'gridfs': ['gridfs'],
|
|
'sheepdog': ['sheepdog'],
|
|
'cinder': ['cinder'],
|
|
'vmware_datastore': ['vsphere']}
|
|
_STORE_TO_SCHEME_MAP.clear()
|
|
_STORE_TO_SCHEME_MAP.update(mapping)
|
|
|
|
|
|
def get_ordered_locations(locations, uri_key='url', **kwargs):
|
|
"""
|
|
Order image location list.
|
|
|
|
:param locations: The original image location list.
|
|
:param uri_key: The key name for location URI in image location dictionary.
|
|
:return: The image location list with preferred store type order.
|
|
"""
|
|
def _foreach_store_type_preference():
|
|
store_types = CONF.store_type_location_strategy.store_type_preference
|
|
for preferred_store in store_types:
|
|
preferred_store = str(preferred_store).strip()
|
|
if not preferred_store:
|
|
continue
|
|
yield preferred_store
|
|
|
|
if not locations:
|
|
return locations
|
|
|
|
preferences = {}
|
|
others = []
|
|
for preferred_store in _foreach_store_type_preference():
|
|
preferences[preferred_store] = []
|
|
|
|
for location in locations:
|
|
uri = location.get(uri_key)
|
|
if not uri:
|
|
continue
|
|
pieces = urlparse.urlparse(uri.strip())
|
|
|
|
store_name = None
|
|
for store, schemes in six.iteritems(_STORE_TO_SCHEME_MAP):
|
|
if pieces.scheme.strip() in schemes:
|
|
store_name = store
|
|
break
|
|
|
|
if store_name in preferences:
|
|
preferences[store_name].append(location)
|
|
else:
|
|
others.append(location)
|
|
|
|
ret = []
|
|
# NOTE(zhiyan): While configuration again since py26 does not support
|
|
# ordereddict container.
|
|
for preferred_store in _foreach_store_type_preference():
|
|
ret.extend(preferences[preferred_store])
|
|
|
|
ret.extend(others)
|
|
|
|
return ret
|