OpenStack之Glance源码简析
Glance简介
OpenStack镜像服务器是一套虚拟机镜像发现、注册、检索。
glance架构图:

Glance源码结构:

glance/api:主要负责接收响应镜像管理命令的Restful请求,分析消息请求信息并分发其所带的命令(如新增,删除,更新等)。默认绑定端口是9292。
glance/registry:主要负责接收响应镜像元数据命令的Restful请求。分析消息请求信息并分发其所带的命令(如获取元数据,更新元数据等)。默认绑定的端口是9191。
glance/db:主要负责与数据库Mysql的交互
glance/store:主要负责存储适配
本次主要从简单的查询来简析glance源码,看一下glance代码是如何执行的。
查询的API:/v1/images/detail,method:GET,有兴趣的朋友可以用火狐浏览器自带的RESTClient来进行REST服务的测试。
好了,废话不多说,源码走起。
源码分析

图为glance/api/v1中的源码目录树。
此次就从glance的查询来分析glance的源码,从horizon的传过来的HTTP请求首先来到glance/api/v1/router.py中,查找匹配的HTTP请求:
代码如下:
mapper.connect("/images/detail",
controller=images_resource,
action='detail',
conditions={'method': ['GET']})
可以看到,这与Glance的API文档是相符的,GET请求,然后是/v1/images/detail。
而后,找到匹配的请求之后,就会进入glance/api/v1/images.py文件中,下面是有关的代码:
def detail(self, req):
"""
Returns detailed information for all available images :param req: The WSGI/Webob Request object
:retval The response body is a mapping of the following form:: {'images': [
{'id': <ID>,
'name': <NAME>,
'size': <SIZE>,
'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM>,
'min_disk': <MIN_DISK>,
'min_ram': <MIN_RAM>,
'store': <STORE>,
'status': <STATUS>,
'created_at': <TIMESTAMP>,
'updated_at': <TIMESTAMP>,
'deleted_at': <TIMESTAMP>|<NONE>,
'properties': {'distro': 'Ubuntu 10.04 LTS', ...}}, ...
]}
"""
self._enforce(req, 'get_images')
params = self._get_query_params(req)
try:
images = registry.get_images_detail(req.context, **params)
# Strip out the Location attribute. Temporary fix for
# LP Bug #755916. This information is still coming back
# from the registry, since the API server still needs access
# to it, however we do not return this potential security
# information to the API end user...
for image in images:
redact_loc(image, copy_dict=False)
self._enforce_read_protected_props(image, req)
except exception.Invalid as e:
raise HTTPBadRequest(explanation="%s" % e)
return dict(images=images)
26行是根据获取查询条件,在此不深入谈,想了解的朋友可以留言,主要查询语句在try里面,也就是第28行:
images = registry.get_images_detail(req.context, **params)
从这里,查询就跳入了glance/registry/client/v1/api.py文件中。

图为glance/registry的目录树,glance/registry/client/v1/api.py中相关代码如下:
def get_images_detail(context, **kwargs):
c = get_registry_client(context)
return c.get_images_detailed(**kwargs)
首先,会在glance/registry/client/v1/api.py文件进行registry端口的认证连接,
def get_registry_client(cxt):
global _CLIENT_CREDS, _CLIENT_KWARGS, _CLIENT_HOST, _CLIENT_PORT
global _METADATA_ENCRYPTION_KEY
kwargs = _CLIENT_KWARGS.copy()
if CONF.use_user_token:
kwargs['auth_tok'] = cxt.auth_tok
if _CLIENT_CREDS:
kwargs['creds'] = _CLIENT_CREDS if CONF.send_identity_headers:
identity_headers = {
'X-User-Id': cxt.user,
'X-Tenant-Id': cxt.tenant,
'X-Roles': ','.join(cxt.roles),
'X-Identity-Status': 'Confirmed',
'X-Service-Catalog': jsonutils.dumps(cxt.service_catalog),
}
kwargs['identity_headers'] = identity_headers
return client.RegistryClient(_CLIENT_HOST, _CLIENT_PORT,
_METADATA_ENCRYPTION_KEY, **kwargs)
然后第三行返回查询,进入glance/registry/client/v1/client.py中:
def get_images_detailed(self, **kwargs):
"""
Returns a list of detailed image data mappings from Registry :param filters: dict of keys & expected values to filter results
:param marker: image id after which to start page
:param limit: max number of images to return
:param sort_key: results will be ordered by this image attribute
:param sort_dir: direction in which to to order results (asc, desc)
"""
params = self._extract_params(kwargs, images.SUPPORTED_PARAMS)
res = self.do_request("GET", "/images/detail", params=params)
image_list = jsonutils.loads(res.read())['images']
for image in image_list:
image = self.decrypt_metadata(image)
return image_list
在12行再次发出请求,然后在glance/registry/api/v1/__init__.py中查找匹配的请求:
mapper.connect("/images/detail",
controller=images_resource,
action="detail",
conditions={'method': ['GET']})
在glance/registry/api/v1/images.py中找到相应的方法进行查询:
def detail(self, req):
"""Return a filtered list of public, non-deleted images in detail :param req: the Request object coming from the wsgi layer
:retval a mapping of the following form:: dict(images=[image_list]) Where image_list is a sequence of mappings containing
all image model fields.
"""
params = self._get_query_params(req) images = self._get_images(req.context, **params)
image_dicts = [make_image_dict(i) for i in images]
LOG.info(_("Returning detailed image list"))
return dict(images=image_dicts)
第14行又调用glance/registry/api/v1/images.py的_get_images(req.context, **params)方法:
def _get_images(self, context, filters, **params):
"""Get images, wrapping in exception if necessary."""
# NOTE(markwash): for backwards compatibility, is_public=True for
# admins actually means "treat me as if I'm not an admin and show me
# all my images"
if context.is_admin and params.get('is_public') is True:
params['admin_as_user'] = True
del params['is_public']
try:
return self.db_api.image_get_all(context, filters=filters,
**params)
except exception.NotFound:
LOG.info(_("Invalid marker. Image %(id)s could not be "
"found.") % {'id': params.get('marker')})
msg = _("Invalid marker. Image could not be found.")
raise exc.HTTPBadRequest(explanation=msg)
except exception.Forbidden:
LOG.info(_("Access denied to image %(id)s but returning "
"'not found'") % {'id': params.get('marker')})
msg = _("Invalid marker. Image could not be found.")
raise exc.HTTPBadRequest(explanation=msg)
except Exception:
LOG.exception(_("Unable to get images"))
raise
在第10行中,进入glance/db/sqlalchemy/api.py中:

图为glance/db的目录树。下面是调用的glance/db/sqlalchemy/api.py中的image_get_all方法,
def image_get_all(context, filters=None, marker=None, limit=None,
sort_key='created_at', sort_dir='desc',
member_status='accepted', is_public=None,
admin_as_user=False):
"""
Get all images that match zero or more filters. :param filters: dict of filter keys and values. If a 'properties'
key is present, it is treated as a dict of key/value
filters on the image properties attribute
:param marker: image id after which to start page
:param limit: maximum number of images to return
:param sort_key: image attribute by which results should be sorted
:param sort_dir: direction in which results should be sorted (asc, desc)
:param member_status: only return shared images that have this membership
status
:param is_public: If true, return only public images. If false, return
only private and shared images.
:param admin_as_user: For backwards compatibility. If true, then return to
an admin the equivalent set of images which it would see
if it were a regular user
"""
filters = filters or {} visibility = filters.pop('visibility', None)
showing_deleted = 'changes-since' in filters or filters.get('deleted',
False) img_conditions, prop_conditions, tag_conditions = \
_make_conditions_from_filters(filters, is_public) query = _select_images_query(context,
img_conditions,
admin_as_user,
member_status,
visibility) if visibility is not None:
if visibility == 'public':
query = query.filter(models.Image.is_public == True)
elif visibility == 'private':
query = query.filter(models.Image.is_public == False) if prop_conditions:
for prop_condition in prop_conditions:
query = query.join(models.ImageProperty, aliased=True)\
.filter(sa_sql.and_(*prop_condition)) if tag_conditions:
for tag_condition in tag_conditions:
query = query.join(models.ImageTag, aliased=True)\
.filter(sa_sql.and_(*tag_condition)) marker_image = None
if marker is not None:
marker_image = _image_get(context,
marker,
force_show_deleted=showing_deleted) sort_keys = ['created_at', 'id']
sort_keys.insert(0, sort_key) if sort_key not in sort_keys else sort_keys query = _paginate_query(query, models.Image, limit,
sort_keys,
marker=marker_image,
sort_dir=sort_dir) query = query.options(sa_orm.joinedload(models.Image.properties))\
.options(sa_orm.joinedload(models.Image.locations)) return [_normalize_locations(image.to_dict()) for image in query.all()]
此方法最后将查询结果返回字典,至此,glance查询方法就此结束。
如果有不对的地方,欢迎各位大神指出。
PS:本博客欢迎转发,但请注明博客地址及作者~
博客地址:http://www.cnblogs.com/voidy/
<。)#)))≦
OpenStack之Glance源码简析的更多相关文章
- SpringMVC学习(一)——概念、流程图、源码简析
学习资料:开涛的<跟我学SpringMVC.pdf> 众所周知,springMVC是比较常用的web框架,通常整合spring使用.这里抛开spring,单纯的对springMVC做一下总 ...
- Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析
一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...
- django-jwt token校验源码简析
一. jwt token校验源码简析 1.1 前言 之前使用jwt签发了token,里面的头部包含了加密的方式.是否有签名等,而载荷中包含用户名.用户主键.过期时间等信息,最后的签名还使用了摘要算法进 ...
- 0002 - Spring MVC 拦截器源码简析:拦截器加载与执行
1.概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日 ...
- AFNetworking源码简析
AFNetworking基本是苹果开发中网络请求库的标配,它是一个轻量级的网络库,专门针对iOS和OS X的网络应用设计,具有模块化的架构和丰富的APIs接口,功能强大并且使用简单,深受苹果应用开发人 ...
- ElementUI 源码简析——源码结构篇
ElementUI 作为当前运用的最广的 Vue PC 端组件库,很多 Vue 组件库的架构都是参照 ElementUI 做的.作为一个有梦想的前端(咸鱼),当然需要好好学习一番这套比较成熟的架构. ...
- DRF之APIView源码简析
一. 安装djangorestframework 安装的方式有以下三种,注意,模块就叫djangorestframework. 方式一:pip3 install djangorestframework ...
- spring ioc源码简析
ClassPathXmlApplicationContext 首先我们先从平时启动spring常用的ClassPathXmlApplicationContext开始解析 ApplicationCont ...
- 并发系列(二)——FutureTask类源码简析
背景 本文基于JDK 11,主要介绍FutureTask类中的run().get()和cancel() 方法,没有过多解析相应interface中的注释,但阅读源码时建议先阅读注释,明白方法的主要的功 ...
随机推荐
- Java开发工具IntelliJ IDEA创建Andriod项目示例说明
IntelliJ IDEA社区版作为一个轻量级的Java开发IDE,是一个开箱即用的Android开发工具. 注意:在本次的教程中我们将以Android平台2.2为例进行IntelliJ IDEA的使 ...
- LAMP stack-5.6.22 (OpenLogic CentOS 7.2)
平台: CentOS 类型: 虚拟机镜像 软件包: apache2.4.20 mysql5.6.30 php5.6.22 apache application server basic softwar ...
- Android商城开发系列(十二)—— 首页推荐布局实现
首页新品推荐的布局效果如下图: 这块布局是使用LinearLayout和GridView去实现,新建recommend_item.xml,代码如下所示: <?xml version=" ...
- linux 命令——41 ps(转)
Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...
- 【洛谷3275】[SCOI2011] 糖果(差分约束系统入门题)
点此看题面 大致题意: 有\(N\)个小朋友,要求每个人都得到糖果,且每个人的糖果总数满足一定的关系式,请你求出至少共分给小朋友们多少糖果. 关系式的转换 首先,我们可以将题目中给定的式子进行转换: ...
- 破解 D-H 协议
756: 破解 D-H 协议 时间限制: 1 Sec 内存限制: 128 MB提交: 78 解决: 18[提交] [状态] [讨论版] [命题人:admin] 题目描述 Diffie-Hellma ...
- 深入理解计算机系统_3e 第十章家庭作业 CS:APP3e chapter 10 homework
10.6 1.若成功打开"foo.txt": -->1.1若成功打开"baz.txt": 输出"4\n" -->1.2若未能成功 ...
- CUDA核函数参数示意:Kernel<<<Dg,Db, Ns, S>>>(param list)
核函数是GPU每个thread上运行的程序.必须通过__gloabl__函数类型限定符定义.形式如下: __global__ void kernel(param list){ } 核函数只能在主机端 ...
- windows下安装php依赖关系管理工具composer
1.安装Composer Composer是PHP的依赖管理工具之一,官方网站 http://getcomposer.org/ .它支持多种安装方式,对于在win下做开发的草来说,最便捷的方式就是下载 ...
- java 实现猜数字游戏 随机给定一个数字,猜大小直到正确
package com.swift; import java.util.Random; import java.util.Scanner; public class GuessBigSmall { p ...