135 lines
4.7 KiB
Python
135 lines
4.7 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.
|
|
|
|
import copy
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
import stevedore
|
|
|
|
from glance.i18n import _, _LE
|
|
|
|
location_strategy_opts = [
|
|
cfg.StrOpt('location_strategy',
|
|
default='location_order',
|
|
choices=('location_order', 'store_type'),
|
|
help=_("""
|
|
Strategy to determine the preference order of image locations.
|
|
|
|
This configuration option indicates the strategy to determine
|
|
the order in which an image's locations must be accessed to
|
|
serve the image's data. Glance then retrieves the image data
|
|
from the first responsive active location it finds in this list.
|
|
|
|
This option takes one of two possible values ``location_order``
|
|
and ``store_type``. The default value is ``location_order``,
|
|
which suggests that image data be served by using locations in
|
|
the order they are stored in Glance. The ``store_type`` value
|
|
sets the image location preference based on the order in which
|
|
the storage backends are listed as a comma separated list for
|
|
the configuration option ``store_type_preference``.
|
|
|
|
Possible values:
|
|
* location_order
|
|
* store_type
|
|
|
|
Related options:
|
|
* store_type_preference
|
|
|
|
""")),
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(location_strategy_opts)
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def _load_strategies():
|
|
"""Load all strategy modules."""
|
|
modules = {}
|
|
namespace = "glance.common.image_location_strategy.modules"
|
|
ex = stevedore.extension.ExtensionManager(namespace)
|
|
for module_name in ex.names():
|
|
try:
|
|
mgr = stevedore.driver.DriverManager(
|
|
namespace=namespace,
|
|
name=module_name,
|
|
invoke_on_load=False)
|
|
|
|
# Obtain module name
|
|
strategy_name = str(mgr.driver.get_strategy_name())
|
|
if strategy_name in modules:
|
|
msg = (_('%(strategy)s is registered as a module twice. '
|
|
'%(module)s is not being used.') %
|
|
{'strategy': strategy_name, 'module': module_name})
|
|
LOG.warn(msg)
|
|
else:
|
|
# Initialize strategy module
|
|
mgr.driver.init()
|
|
modules[strategy_name] = mgr.driver
|
|
except Exception as e:
|
|
LOG.error(_LE("Failed to load location strategy module "
|
|
"%(module)s: %(e)s"), {'module': module_name,
|
|
'e': e})
|
|
return modules
|
|
|
|
|
|
_available_strategies = _load_strategies()
|
|
|
|
|
|
# TODO(kadachi): Not used but don't remove this until glance_store
|
|
# development/migration stage.
|
|
def verify_location_strategy(conf=None, strategies=_available_strategies):
|
|
"""Validate user configured 'location_strategy' option value."""
|
|
if not conf:
|
|
conf = CONF.location_strategy
|
|
if conf not in strategies:
|
|
msg = (_('Invalid location_strategy option: %(name)s. '
|
|
'The valid strategy option(s) is(are): %(strategies)s') %
|
|
{'name': conf, 'strategies': ", ".join(strategies.keys())})
|
|
LOG.error(msg)
|
|
raise RuntimeError(msg)
|
|
|
|
|
|
def get_ordered_locations(locations, **kwargs):
|
|
"""
|
|
Order image location list by configured strategy.
|
|
|
|
:param locations: The original image location list.
|
|
:param kwargs: Strategy-specific arguments for under layer strategy module.
|
|
:returns: The image location list with strategy-specific order.
|
|
"""
|
|
if not locations:
|
|
return []
|
|
strategy_module = _available_strategies[CONF.location_strategy]
|
|
return strategy_module.get_ordered_locations(copy.deepcopy(locations),
|
|
**kwargs)
|
|
|
|
|
|
def choose_best_location(locations, **kwargs):
|
|
"""
|
|
Choose best location from image location list by configured strategy.
|
|
|
|
:param locations: The original image location list.
|
|
:param kwargs: Strategy-specific arguments for under layer strategy module.
|
|
:returns: The best location from image location list.
|
|
"""
|
|
locations = get_ordered_locations(locations, **kwargs)
|
|
if locations:
|
|
return locations[0]
|
|
else:
|
|
return None
|