OpenStack建立实例完整过程源码详细分析(2)
2013-06-20 13:37
766 查看
感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!
如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn
继续解析方法def show(self, context, image_id):
1.2.2 image = self.service.show(context, image_uuid)
这里可以知道self.service = service or glance.get_default_image_service();
跟踪到方法get_default_image_service()可知:
show(self, context, image_id):
1.2.2.1 image = self._client.call(context, 1, 'get', image_id)
这条语句实现的功能是调用一个glance客户端的对象,调用其中的get方法,获取image_id指定的镜像元数据;
参数解释:
context: 上下文信息;
1: 传到下一个方法中,作为最终调用glanceclient版本version参数;
'get': 作为方法参数,传到下一个函数;
image_id: 获取的image镜像ID;
具体看方法/nova/image/glance.py----def call(self, context, version, method, *args, **kwargs):
1)num_attempts = 1 + CONF.glance_num_retries
获取得到试图连接glance客户端的最大次数;
2)client = self.client or self._create_onetime_client(context, version)
_create_onetime_client:尝试建立并返回一个正确的glanceclient.Client客户端;
我们看看是如何建立glance客户端的;
port, 'https'),用于后续建立glance客户端;
方法_create_glance_client则实现了实例化一个正确的新的glanceclient.Client对象,先看它的代码:
return glanceclient.Client(str(version), endpoint, **params)
由代码导入的模块可以知道,这就访问了glance客户端组件,并且调用了glance客户端组件glanceclient中的/glanceclient/client.py----def Client(version, *args, **kwargs):
最终返回客户端类的实例对象,如方法call中的:client = self.client or self._create_onetime_client(context, version),client也就是客户端类的实例对象;
3)return getattr(client.images, method)(*args, **kwargs)
因为传入的menthod参数为‘get’,所以这条语句就相当于:return client.images.get(*args, **kwargs);
即调用了/glanceclient/glanceclient/v1/images.py----def get(self, image),来获取指定的镜像元数据;
到底是如何通过glance客户端获取指定镜像元数据的,而获取到的元数据又是什么,我将会写一篇博客加以解析。(查看链接)
至此,方法/nova/image/glance.py----def call(self, context, version, method, *args, **kwargs)解析完成,这个方法主要完成了:
根据配置参数确定最大链接访问glance客户端的次数,在不超过最大次数的情况下,尝试确定正确的客户端版本,建立glance客户端类的对象,通过glance客户端中images.py中的get方法,获取指定的镜像元数据;
最后回到方法show中,语句image = self._client.call(context, 1, 'get', image_id)解析完成;
1.2.2.2 base_image_meta = self._translate_from_glance(image)
这条语句实现了把通过glanceclient获取的镜像元数据转换为python可处理的数据格式(原为JSON格式);
至此,语句image = self.service.show(context, image_uuid)完成解析,它主要实现了:
调用/nova/image/glance.py----def show(self, context, image_id)方法,完成通过glance客户端获取image_uuid指定的镜像元数据,并转换为python可处理的数据格式返回;
如果转载,请保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
邮箱地址:dong.liu@siat.ac.cn
继续解析方法def show(self, context, image_id):
def show(self, context, image_id): """ # 调用之一传进来的参数: # context:上下文信息; # image_id=internal_id:实例镜像的ID值(从EC2 ID值变换了格式以后得到的); """ # id_to_glance_id:根据数据库内置ID值(实例或者说是镜像的ID)获取数据库中相应的UUID值,赋值给image_uuid; image_uuid = ec2utils.id_to_glance_id(context, image_id) # 这里的service:service = service or glance.get_default_image_service(); # 获取service或者是GlanceImageService的对象(glance.get_default_image_service()指向的); # 所以这里调用的还是/nova/image/glance.py中的show方法; image = self.service.show(context, image_uuid) # 转换镜像中的image_uuid到image_id; # 更新image当中的相关属性,返回更新后的image数据; return self._translate_uuid_to_id(context, image)
1.2.2 image = self.service.show(context, image_uuid)
这里可以知道self.service = service or glance.get_default_image_service();
跟踪到方法get_default_image_service()可知:
def get_default_image_service(): return GlanceImageService()可以看到,这里service获取的是类GlanceImageService的实例对象;进而调用了类GlanceImageService下的方法def
show(self, context, image_id):
def show(self, context, image_id): """ 以字典的形式返回给定image镜像ID的镜像数据; 调用glance客户端,获取image_id指定的镜像元数据(此时为JSON格式); 转换从glance下载的镜像数据为python可处理的字典格式; # 调用之一传进来的参数; # context:上下文信息; # image_id:获取的image镜像ID; """ # call:调用一个glance客户端的对象,调用其中的get方法,获取image镜像元数据; # 这个方法尝试一定次数连接glance,从glance客户端下载image,如果连接成功,这时会获取glance客户端对象; # 并返回client.images.get给image; # context:上下文信息; # 1:传到下一个方法中,作为version参数; # 'get':作为方法参数,传到下一个函数; # image_id:获取的image镜像ID; try: image = self._client.call(context, 1, 'get', image_id) except Exception: _reraise_translated_image_exception(image_id) # 如果image是不可用的,则引发异常;; # _is_image_available:检测镜像image的可用性 if not self._is_image_available(context, image): raise exception.ImageNotFound(image_id=image_id) # _translate_from_glance:把通过glanceclient获取的镜像元数据转换为python可处理的数据格式(原为JSON格式); base_image_meta = self._translate_from_glance(image) return base_image_meta
1.2.2.1 image = self._client.call(context, 1, 'get', image_id)
这条语句实现的功能是调用一个glance客户端的对象,调用其中的get方法,获取image_id指定的镜像元数据;
参数解释:
context: 上下文信息;
1: 传到下一个方法中,作为最终调用glanceclient版本version参数;
'get': 作为方法参数,传到下一个函数;
image_id: 获取的image镜像ID;
具体看方法/nova/image/glance.py----def call(self, context, version, method, *args, **kwargs):
def call(self, context, version, method, *args, **kwargs): """ 调用一个glance客户端的对象,调用其中的get方法,获取image镜像; 尝试一定次数连接glance,如果连接成功,这时会获取glance客户端对象,并返回client.images.get; 如果到达最大尝试连接次数都没有连接成功,则会引发异常; # 调用之一传进来的参数: # context:上下文信息; # 1:传到下一个方法中,作为version参数; # 'get':作为方法参数,传到下一个函数; # image_id:获取的image镜像ID; """ # 各种异常; retry_excs = (glanceclient.exc.ServiceUnavailable, glanceclient.exc.InvalidEndpoint, glanceclient.exc.CommunicationError) # glance_num_retries:这个参数定义了当从glance下载image镜像时,重试的次数; # 默认为0应该是表示会下载无数次; # 加1是为了排除无数次下载尝试的可能,而定义为只有1次重新下载的机会; # 计算从glance下载image镜像重试机会的次数; num_attempts = 1 + CONF.glance_num_retries # 从1循环到num_attempts; for attempt in xrange(1, num_attempts + 1): # 得到glance客户端对象,如果没有定义,则新建立一个客户端对象; # _create_onetime_client:建立并返回一个正确的glanceclient.Client客户端,它会被用于一次call; # context:上下文信息; # version:版本; client = self.client or self._create_onetime_client(context, version) # 这里传进来的一个method是get,所以返回的是client.images.get; # getattr(client.images, method)(*args, **kwargs)调用的就是客户端对象类中的get方法,获取image镜像; try: return getattr(client.images, method)(*args, **kwargs) except retry_excs as e: host = self.host port = self.port extra = "retrying" error_msg = _("Error contacting glance server " "'%(host)s:%(port)s' for '%(method)s', %(extra)s.") # 如果达到了最大的尝试下载次数,则会引发异常,提示glance连接失败; if attempt == num_attempts: extra = 'done trying' LOG.exception(error_msg, locals()) raise exception.GlanceConnectionFailed( host=host, port=port, reason=str(e)) LOG.exception(error_msg, locals()) time.sleep(1)具体看这个方法:
1)num_attempts = 1 + CONF.glance_num_retries
获取得到试图连接glance客户端的最大次数;
2)client = self.client or self._create_onetime_client(context, version)
_create_onetime_client:尝试建立并返回一个正确的glanceclient.Client客户端;
我们看看是如何建立glance客户端的;
def _create_onetime_client(self, context, version): """ 建立并返回一个正确的glanceclient.Client客户端,它会被用于一次call; """ # get_api_servers:以(host, port, 'https')的形式作为一个元素,获取glance api servers的列表api_servers; # 返回的是不断循环的api_servers列表中的元素(因为执行了这个方法:itertools.cycle); if self.api_servers is None: self.api_servers = get_api_servers() # 从api_servers中随机获取某一个元素,进而获取一组host、port、use_ssl的值; self.host, self.port, self.use_ssl = self.api_servers.next() # _create_glance_client:实例化一个正确的新的glanceclient.Client对象; # context:上下文信息; # self.host:glance api service的host值; # self.port:glance api service的port值; # self.use_ssl:glance api service的use_ssl值; # version:版本信息; return _create_glance_client(context, self.host, self.port, self.use_ssl, version)方法get_api_servers获取了glance api service的列表,列表中的每一个元素都是(host, port, 'https')的形式,如果进入方法可以看到,在方法的结尾返回的是:itertools.cycle(api_servers),这是一个无界迭代器,会重复不断对列表api_servers进行循环读取;因此再执行self.api_servers.next()语句,就相当于随机的获取一组可用的(host,
port, 'https'),用于后续建立glance客户端;
方法_create_glance_client则实现了实例化一个正确的新的glanceclient.Client对象,先看它的代码:
def _create_glance_client(context, host, port, use_ssl, version=1): """ 实例化一个正确的新的glanceclient.Client对象; 获取正确的glanceclient.version.client.Client类; 因为在python-glanceclient中一共定义了两个版本的客户端: glanceclient.v1和glanceclient.v2 # 调用之一传进来的参数; # context:上下文信息; # self.host:glance api service的host值; # self.port:glance api service的port值; # self.use_ssl:glance api service的use_ssl值; # version:版本信息; """ # http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的; # HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全; if use_ssl: scheme = 'https' else: scheme = 'http' params = {} # glance_api_insecure:这个参数定义了是否执行不安全的SSL协议(https); # 参数的默认值为False; params['insecure'] = CONF.glance_api_insecure # auth_strategy:这个参数定义了身份认证所使用的策略是noauth或者是keystone; # 参数的默认值是'noauth'; if CONF.auth_strategy == 'keystone': params['token'] = context.auth_token # 组成能够访问glance api service的URL形式; endpoint = '%s://%s:%s' % (scheme, host, port) # glanceclient.Client: # 获取正确的glanceclient.version.client.Client类; # 因为一共有两个版本的客户端:glanceclient.v1和glanceclient.v2 # str(version):版本信息; # endpoint:访问glance api服务的端点,为能够访问glance api service的URL形式:scheme://host:port; # params:一些参数集合; return glanceclient.Client(str(version), endpoint, **params)我们可以看到,除了开始的SSL协议确定和身份验证策略的确定,结尾返回的语句是:
return glanceclient.Client(str(version), endpoint, **params)
由代码导入的模块可以知道,这就访问了glance客户端组件,并且调用了glance客户端组件glanceclient中的/glanceclient/client.py----def Client(version, *args, **kwargs):
def Client(version, *args, **kwargs): """ 确定正确的glanceclient.version.client.Client客户端类; 因为一共有两个版本的客户端: glanceclient.v1和glanceclient.v2; """ # import_versioned_module:导入模块:glanceclient.version.client; # version:版本信息; # 'client'; module = utils.import_versioned_module(version, 'client') # client_class=glanceclient.version.client.Client; client_class = getattr(module, 'Client') return client_class(*args, **kwargs)可以看到这个方法根据传入的版本参数version确定了要访问的客户端版本,并且进一步确定了正确的glance客户端类glanceclient.version.client.Client,返回类的实例对象;这也实现了nova对glanceclient模块的访问;
最终返回客户端类的实例对象,如方法call中的:client = self.client or self._create_onetime_client(context, version),client也就是客户端类的实例对象;
3)return getattr(client.images, method)(*args, **kwargs)
因为传入的menthod参数为‘get’,所以这条语句就相当于:return client.images.get(*args, **kwargs);
即调用了/glanceclient/glanceclient/v1/images.py----def get(self, image),来获取指定的镜像元数据;
def get(self, image): """ 为指定的镜像获取元数据; image: 用于查找镜像的对象或者是镜像ID; """ # 根据image获取image的ID值; image_id = base.getid(image) resp, body = self.api.raw_request('HEAD', '/v1/images/%s' % urllib.quote(image_id)) meta = self._image_meta_from_headers(dict(resp.getheaders())) return Image(self, meta)
到底是如何通过glance客户端获取指定镜像元数据的,而获取到的元数据又是什么,我将会写一篇博客加以解析。(查看链接)
至此,方法/nova/image/glance.py----def call(self, context, version, method, *args, **kwargs)解析完成,这个方法主要完成了:
根据配置参数确定最大链接访问glance客户端的次数,在不超过最大次数的情况下,尝试确定正确的客户端版本,建立glance客户端类的对象,通过glance客户端中images.py中的get方法,获取指定的镜像元数据;
最后回到方法show中,语句image = self._client.call(context, 1, 'get', image_id)解析完成;
1.2.2.2 base_image_meta = self._translate_from_glance(image)
这条语句实现了把通过glanceclient获取的镜像元数据转换为python可处理的数据格式(原为JSON格式);
至此,语句image = self.service.show(context, image_uuid)完成解析,它主要实现了:
调用/nova/image/glance.py----def show(self, context, image_id)方法,完成通过glance客户端获取image_uuid指定的镜像元数据,并转换为python可处理的数据格式返回;
相关文章推荐
- OpenStack建立实例完整过程源码详细分析(12)----依据AMQP通信架构实现消息发送机制解析之一
- OpenStack建立实例完整过程源码详细分析(13)----依据AMQP通信架构实现消息发送机制解析之二
- OpenStack建立实例完整过程源码详细分析(14)----依据AMQP通信架构实现消息接收机制解析之一
- OpenStack建立实例完整过程源码详细分析(7)
- OpenStack建立实例完整过程源码详细分析(5)
- OpenStack建立实例完整过程源码详细分析(8)
- OpenStack建立实例完整过程源码详细分析(6)
- OpenStack建立实例完整过程源码详细分析(15)----依据AMQP通信架构实现消息接收机制解析之二
- OpenStack建立实例完整过程源码详细分析(4)
- OpenStack建立实例完整过程源码详细分析(3)
- OpenStack建立实例完整过程源码详细分析(10)
- OpenStack建立实例完整过程源码详细分析(1)
- OpenStack建立实例完整过程源码详细分析(9)
- OpenStack建立实例完整过程源码详细分析(11)
- Android 4.0 Launcher2源码分析——Launcher内容加载详细过程
- mybatis源码分析(1)——SqlSessionFactory实例的产生过程
- Android 4.0 Launcher2源码分析——Launcher内容加载详细过程
- ARMv8(aarch64)页表建立过程详细分析
- Openstack Cinder中建立volume过程的源码解析(3)
- OpenStack 创建快照(Create Snapshot)过程源码分析