设为首页 收藏本站
查看: 5161|回复: 0

[经验分享] OpenStack之Glance源码简析

[复制链接]

尚未签到

发表于 2015-4-11 15:30:30 | 显示全部楼层 |阅读模式
  Glance简介
  OpenStack镜像服务器是一套虚拟机镜像发现、注册、检索。
   glance架构图:
DSC0000.png
  Glance源码结构:
DSC0001.jpg
  glance/api:主要负责接收响应镜像管理命令的Restful请求,分析消息请求信息并分发其所带的命令(如新增,删除,更新等)。默认绑定端口是9292。
  glance/registry:主要负责接收响应镜像元数据命令的Restful请求。分析消息请求信息并分发其所带的命令(如获取元数据,更新元数据等)。默认绑定的端口是9191。
  glance/db:主要负责与数据库Mysql的交互
  glance/store:主要负责存储适配
  本次主要从简单的查询来简析glance源码,看一下glance代码是如何执行的。
  查询的API:/v1/images/detail,method:GET,有兴趣的朋友可以用火狐浏览器自带的RESTClient来进行REST服务的测试。
  好了,废话不多说,源码走起。
  源码分析
  
DSC0002.jpg
  图为glance/api/v1中的源码目录树。
     此次就从glance的查询来分析glance的源码,从horizon的传过来的HTTP请求首先来到glance/api/v1/router.py中,查找匹配的HTTP请求:
      代码如下:   



1 mapper.connect("/images/detail",
2                        controller=images_resource,
3                        action='detail',
4                        conditions={'method': ['GET']})
  可以看到,这与Glance的API文档是相符的,GET请求,然后是/v1/images/detail。
  而后,找到匹配的请求之后,就会进入glance/api/v1/images.py文件中,下面是有关的代码:  



1 def detail(self, req):
2         """
3         Returns detailed information for all available images
4
5         :param req: The WSGI/Webob Request object
6         :retval The response body is a mapping of the following form::
7
8             {'images': [
9                 {'id': ,
10                  'name': ,
11                  'size': ,
12                  'disk_format': ,
13                  'container_format': ,
14                  'checksum': ,
15                  'min_disk': ,
16                  'min_ram': ,
17                  'store': ,
18                  'status': ,
19                  'created_at': ,
20                  'updated_at': ,
21                  'deleted_at': |,
22                  'properties': {'distro': 'Ubuntu 10.04 LTS', ...}}, ...
23             ]}
24         """
25         self._enforce(req, 'get_images')
26         params = self._get_query_params(req)
27         try:
28             images = registry.get_images_detail(req.context, **params)
29             # Strip out the Location attribute. Temporary fix for
30             # LP Bug #755916. This information is still coming back
31             # from the registry, since the API server still needs access
32             # to it, however we do not return this potential security
33             # information to the API end user...
34             for image in images:
35                 redact_loc(image, copy_dict=False)
36                 self._enforce_read_protected_props(image, req)
37         except exception.Invalid as e:
38             raise HTTPBadRequest(explanation="%s" % e)
39         return dict(images=images)
  
  26行是根据获取查询条件,在此不深入谈,想了解的朋友可以留言,主要查询语句在try里面,也就是第28行: 



1 images = registry.get_images_detail(req.context, **params)
  
  从这里,查询就跳入了glance/registry/client/v1/api.py文件中。
DSC0003.jpg
  图为glance/registry的目录树,glance/registry/client/v1/api.py中相关代码如下: 



1 def get_images_detail(context, **kwargs):
2     c = get_registry_client(context)
3     return c.get_images_detailed(**kwargs)
  
  首先,会在glance/registry/client/v1/api.py文件进行registry端口的认证连接, 



1 def get_registry_client(cxt):
2     global _CLIENT_CREDS, _CLIENT_KWARGS, _CLIENT_HOST, _CLIENT_PORT
3     global _METADATA_ENCRYPTION_KEY
4     kwargs = _CLIENT_KWARGS.copy()
5     if CONF.use_user_token:
6         kwargs['auth_tok'] = cxt.auth_tok
7     if _CLIENT_CREDS:
8         kwargs['creds'] = _CLIENT_CREDS
9
10     if CONF.send_identity_headers:
11         identity_headers = {
12             'X-User-Id': cxt.user,
13             'X-Tenant-Id': cxt.tenant,
14             'X-Roles': ','.join(cxt.roles),
15             'X-Identity-Status': 'Confirmed',
16             'X-Service-Catalog': jsonutils.dumps(cxt.service_catalog),
17         }
18         kwargs['identity_headers'] = identity_headers
19     return client.RegistryClient(_CLIENT_HOST, _CLIENT_PORT,
20                                  _METADATA_ENCRYPTION_KEY, **kwargs)
  
  然后第三行返回查询,进入glance/registry/client/v1/client.py中: 



1 def get_images_detailed(self, **kwargs):
2         """
3         Returns a list of detailed image data mappings from Registry
4
5         :param filters: dict of keys & expected values to filter results
6         :param marker: image id after which to start page
7         :param limit: max number of images to return
8         :param sort_key: results will be ordered by this image attribute
9         :param sort_dir: direction in which to to order results (asc, desc)
10         """
11         params = self._extract_params(kwargs, images.SUPPORTED_PARAMS)
12         res = self.do_request("GET", "/images/detail", params=params)
13         image_list = jsonutils.loads(res.read())['images']
14         for image in image_list:
15             image = self.decrypt_metadata(image)
16         return image_list
  
  在12行再次发出请求,然后在glance/registry/api/v1/__init__.py中查找匹配的请求:  



1 mapper.connect("/images/detail",
2                        controller=images_resource,
3                        action="detail",
4                        conditions={'method': ['GET']})
  
  在glance/registry/api/v1/images.py中找到相应的方法进行查询:



1 def detail(self, req):
2         """Return a filtered list of public, non-deleted images in detail
3
4         :param req: the Request object coming from the wsgi layer
5         :retval a mapping of the following form::
6
7             dict(images=[image_list])
8
9         Where image_list is a sequence of mappings containing
10         all image model fields.
11         """
12         params = self._get_query_params(req)
13
14         images = self._get_images(req.context, **params)
15         image_dicts = [make_image_dict(i) for i in images]
16         LOG.info(_("Returning detailed image list"))
17         return dict(images=image_dicts)
  
  第14行又调用glance/registry/api/v1/images.py的_get_images(req.context, **params)方法:



1 def _get_images(self, context, filters, **params):
2         """Get images, wrapping in exception if necessary."""
3         # NOTE(markwash): for backwards compatibility, is_public=True for
4         # admins actually means "treat me as if I'm not an admin and show me
5         # all my images"
6         if context.is_admin and params.get('is_public') is True:
7             params['admin_as_user'] = True
8             del params['is_public']
9         try:
10             return self.db_api.image_get_all(context, filters=filters,
11                                              **params)
12         except exception.NotFound:
13             LOG.info(_("Invalid marker. Image %(id)s could not be "
14                        "found.") % {'id': params.get('marker')})
15             msg = _("Invalid marker. Image could not be found.")
16             raise exc.HTTPBadRequest(explanation=msg)
17         except exception.Forbidden:
18             LOG.info(_("Access denied to image %(id)s but returning "
19                        "'not found'") % {'id': params.get('marker')})
20             msg = _("Invalid marker. Image could not be found.")
21             raise exc.HTTPBadRequest(explanation=msg)
22         except Exception:
23             LOG.exception(_("Unable to get images"))
24             raise
  
  在第10行中,进入glance/db/sqlalchemy/api.py中:
DSC0004.jpg
  图为glance/db的目录树。下面是调用的glance/db/sqlalchemy/api.py中的image_get_all方法,
  



1 def image_get_all(context, filters=None, marker=None, limit=None,
2                   sort_key='created_at', sort_dir='desc',
3                   member_status='accepted', is_public=None,
4                   admin_as_user=False):
5     """
6     Get all images that match zero or more filters.
7
8     :param filters: dict of filter keys and values. If a 'properties'
9                     key is present, it is treated as a dict of key/value
10                     filters on the image properties attribute
11     :param marker: image id after which to start page
12     :param limit: maximum number of images to return
13     :param sort_key: image attribute by which results should be sorted
14     :param sort_dir: direction in which results should be sorted (asc, desc)
15     :param member_status: only return shared images that have this membership
16                           status
17     :param is_public: If true, return only public images. If false, return
18                       only private and shared images.
19     :param admin_as_user: For backwards compatibility. If true, then return to
20                       an admin the equivalent set of images which it would see
21                       if it were a regular user
22     """
23     filters = filters or {}
24
25     visibility = filters.pop('visibility', None)
26     showing_deleted = 'changes-since' in filters or filters.get('deleted',
27                                                                 False)
28
29     img_conditions, prop_conditions, tag_conditions = \
30         _make_conditions_from_filters(filters, is_public)
31
32     query = _select_images_query(context,
33                                  img_conditions,
34                                  admin_as_user,
35                                  member_status,
36                                  visibility)
37
38     if visibility is not None:
39         if visibility == 'public':
40             query = query.filter(models.Image.is_public == True)
41         elif visibility == 'private':
42             query = query.filter(models.Image.is_public == False)
43
44     if prop_conditions:
45         for prop_condition in prop_conditions:
46             query = query.join(models.ImageProperty, aliased=True)\
47                 .filter(sa_sql.and_(*prop_condition))
48
49     if tag_conditions:
50         for tag_condition in tag_conditions:
51             query = query.join(models.ImageTag, aliased=True)\
52                 .filter(sa_sql.and_(*tag_condition))
53
54     marker_image = None
55     if marker is not None:
56         marker_image = _image_get(context,
57                                   marker,
58                                   force_show_deleted=showing_deleted)
59
60     sort_keys = ['created_at', 'id']
61     sort_keys.insert(0, sort_key) if sort_key not in sort_keys else sort_keys
62
63     query = _paginate_query(query, models.Image, limit,
64                             sort_keys,
65                             marker=marker_image,
66                             sort_dir=sort_dir)
67
68     query = query.options(sa_orm.joinedload(models.Image.properties))\
69                  .options(sa_orm.joinedload(models.Image.locations))
70
71     return [_normalize_locations(image.to_dict()) for image in query.all()]
  此方法最后将查询结果返回字典,至此,glance查询方法就此结束。
  如果有不对的地方,欢迎各位大神指出。
  
  PS:本博客欢迎转发,但请注明博客地址及作者~
    博客地址:http://www.iyunv.com/voidy/
    

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-56053-1-1.html 上篇帖子: openstack-ceilometer 下篇帖子: Openstack Neutron OVS ARP Responder
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表