在nova/image 这个目录下是nova调用glance的接口。
首先看class API 这个类
这里的glance来自from nova.image import glance
class API(object):
def _get_session_and_image_id(self, context, id_or_uri):
return glance.get_remote_image_service(context, id_or_uri)
def _get_session(self, _context):
return glance.get_default_image_service()
def get(self, context, id_or_uri, include_locations=False,
show_deleted=True):
session, image_id = self._get_session_and_image_id(context, id_or_uri)
return session.show(context, image_id,
include_locations=include_locations,
show_deleted=show_deleted)
可以看到这里的get 通过_get_session得到glance的image service,再通过image service的show函数,那继续看看nova.image的show函数是怎么实现的。
源码在nova/image/glance.py 中。
在glance.py 中有提供了两个类,一个是class GlanceImageService(object)另外一个是class GlanceImageServiceV2(object)。很明显是对应两个不同的版本
其中class GlanceImageServiceV2包含了GlanceImageService 中的所有成员函数的实现.
以show函数为例
def show(self, context, image_id, include_locations=False,
show_deleted=True):
try:
//可见show函数的核心是调用glance的get函数,其参数是image_id
image = self._client.call(context, 2, 'get', image_id)
except Exception:
_reraise_translated_image_exception(image_id)
image = _translate_from_glance(image,
include_locations=include_locations)
if include_locations:
locations = image.get('locations', None) or []
du = image.get('direct_url', None)
if du:
locations.append({'url': du, 'metadata': {}})
image['locations'] = locations
return image
这里首先调用image = self._client.call(context, 2, 'get', image_id)根据得到image
这里的_client是在GlanceImageServiceV2的__init__函数中赋值
self._client = client or GlanceClientWrapper()
在nova中是通过get_default_image_service来调用GlanceImageServiceV2
def get_default_image_service():
# TODO(sbiswas7): Remove this check once we move to glance V2
# completely.
if CONF.glance.use_glance_v1:
return GlanceImageService()
else:
return GlanceImageServiceV2()
因此在self._client = client or GlanceClientWrapper(),其实等于self._client = GlanceClientWrapper()
继续看GlanceClientWrapper类,这里假定是version 2.
class GlanceClientWrapper(object):
"""Glance client wrapper class that implements retries."""
def __init__(self, context=None, endpoint=None):
if CONF.glance.use_glance_v1:
version = 1
else:
version = 2
if endpoint is not None:
//通过_create_static_client得到glance的endpoint
self.client = self._create_static_client(context,
endpoint,
version)
else:
self.client = None
self.api_servers = None
def _create_static_client(self, context, endpoint, version):
"""Create a client that we'll use for every call."""
self.api_server = str(endpoint)
//最终_glanceclient_from_endpoint->glanceclient.Client得到glance的endpoint,这样nova就可以调用glance的API了
return _glanceclient_from_endpoint(context, endpoint, version)
def call(self, context, version, method, *args, **kwargs):
"""Call a glance client method. If we get a connection error,
retry the request according to CONF.glance.num_retries.
"""
retry_excs = (glanceclient.exc.ServiceUnavailable,
glanceclient.exc.InvalidEndpoint,
glanceclient.exc.CommunicationError)
retries = CONF.glance.num_retries
if retries < 0:
LOG.warning(_LW("Treating negative config value (%(retries)s) for "
"'glance.num_retries' as 0."),
{'retries': retries})
retries = 0
num_attempts = retries + 1
for attempt in range(1, num_attempts + 1):
client = self.client or self._create_onetime_client(context,
version)
try:
controller = getattr(client,
kwargs.pop('controller', 'images'))
//通过getattr查看glance是否有是否有对应的实现,例如show函数其实是调用glance的get函数
//image = self._client.call(context, 2, 'get', image_id)
//因此这里先通过getattr查看glance是否有get这个函数,如果有的话,直接通过下面这一句来调用
result = getattr(controller, method)(*args, **kwargs)
if inspect.isgenerator(result):
# Convert generator results to a list, so that we can
# catch any potential exceptions now and retry the call.
return list(result)
return result
nova中的glance接口
最新推荐文章于 2021-05-17 16:19:45 发布