**** CubicPower OpenStack Study ****
def _image_handler_asso(handler, path, location, image_meta):
_IMAGE_HANDLERS_ASSO[path] = (handler, location, image_meta)
**** CubicPower OpenStack Study ****
def _image_handler_disasso(handler, path):
_IMAGE_HANDLERS_ASSO.pop(path, None)
**** CubicPower OpenStack Study ****
def _match_locations(locations, schemes):
matched = []
if locations and (schemes is not None):
for loc in locations:
# Note(zhiyan): location = {'url': 'string',
# 'metadata': {...}}
if len(schemes) == 0:
# Note(zhiyan): handler has not scheme limitation.
matched.append(loc)
elif urlparse.urlparse(loc['url']).scheme in schemes:
matched.append(loc)
return matched
**** CubicPower OpenStack Study ****
def load_image_handlers(driver):
"""Loading construct user configured image handlers.
Handler objects will be cached to keep handler instance as singleton
since this structure need support follow sub-class development,
developer could implement particular sub-class in relevant hypervisor
layer with more advanced functions.
The handler's __init__() need do some re-preparing work if it needed,
for example when nova-compute service restart or host reboot,
CinderImageHandler will need to re-prepare iscsi/fc link for volumes
those already be cached on compute host as template image previously.
"""
global _IMAGE_HANDLERS, _IMAGE_HANDLERS_ASSO
if _IMAGE_HANDLERS:
_IMAGE_HANDLERS = []
_IMAGE_HANDLERS_ASSO = {}
# for de-duplicate. using ordereddict lib to support both py26 and py27?
processed_handler_names = []
ex = stevedore.extension.ExtensionManager('nova.virt.image.handlers')
for name in CONF.image_handlers:
if not name:
continue
name = name.strip()
if name in processed_handler_names:
LOG.warn(_("Duplicated handler extension name in 'image_handlers' "
"option: %s, skip."), name)
continue
elif name not in ex.names():
LOG.warn(_("Invalid handler extension name in 'image_handlers' "
"option: %s, skip."), name)
continue
processed_handler_names.append(name)
try:
mgr = stevedore.driver.DriverManager(
namespace='nova.virt.image.handlers',
name=name,
invoke_on_load=True,
invoke_kwds={"driver": driver,
"associate_fn": _image_handler_asso,
"disassociate_fn": _image_handler_disasso})
_IMAGE_HANDLERS.append(mgr.driver)
except Exception as err:
LOG.warn(_("Failed to import image handler extension "
"%(name)s: %(err)s"), {'name': name, 'err': err})
**** CubicPower OpenStack Study ****
def handle_image(context=None, image_id=None,
user_id=None, project_id=None,
target_path=None):
"""Handle image using available handles.
This generator will return each available handler on each time.
:param context: Request context
:param image_id: The opaque image identifier
:param user_id: Request user id
:param project_id: Request project id
:param target_path: Where the image data to write
:raises NoImageHandlerAvailable: if no any image handler specified in
the configuration is available for this request.
"""
handled = False
if target_path is not None:
target_path = target_path.strip()
# Check if target image has been handled before,
# we can using previous handler process it again directly.
if target_path and _IMAGE_HANDLERS_ASSO:
ret = _IMAGE_HANDLERS_ASSO.get(target_path)
if ret:
(image_handler, location, image_meta) = ret
yield image_handler, location, image_meta
handled = image_handler.last_ops_handled()
image_meta = None
if not handled and _IMAGE_HANDLERS:
if context and image_id:
(image_service, _image_id) = glance.get_remote_image_service(
context, image_id)
image_meta = image_service.show(context, image_id)
# Note(zhiyan): Glance maybe can not receive image
# location property since Glance disabled it by default.
img_locs = image_service.get_locations(context, image_id)
for image_handler in _IMAGE_HANDLERS:
matched_locs = _match_locations(img_locs,
image_handler.get_schemes())
for loc in matched_locs:
yield image_handler, loc, image_meta
handled = image_handler.last_ops_handled()
if handled:
return
if not handled:
# Note(zhiyan): using location-independent handler do it.
for image_handler in _IMAGE_HANDLERS:
if len(image_handler.get_schemes()) == 0:
yield image_handler, None, image_meta
handled = image_handler.last_ops_handled()
if handled:
return
if not handled:
LOG.error(_("Can not handle image: %(image_id)s %(target_path)s"),
{'image_id': image_id, 'target_path': target_path})
raise exception.NoImageHandlerAvailable(image_id=image_id)